1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent, Inc. All rights reserved.
25 */
26
27 #include <sys/param.h>
28 #include <libintl.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <syslog.h>
34 #include <unistd.h>
35 #include <errno.h>
36
37 #include "utils.h"
38
39 static char ERRNO_FMT[] = ": %s";
40
41 static char *pname = NULL;
42 static rcm_level_t message_priority = RCM_WARN;
43 static rcm_dst_t message_dst = RCD_STD;
44
45 static void dmesg(int level, char *msg);
46
47 /*PRINTFLIKE2*/
48 void
49 dprintfe(int level, char *format, ...)
50 {
51 va_list alist;
52
53 va_start(alist, format);
54 vdprintfe(level, format, alist);
55 va_end(alist);
56 }
57
58 /*PRINTFLIKE2*/
59 void
60 vdprintfe(int level, const char *format, va_list alist)
61 {
62 char buf[LINELEN];
63 char *c;
64 int err = errno;
65
66 *buf = 0;
67
68 if ((strlen(buf) + 1) < LINELEN)
69 (void) vsnprintf(buf + strlen(buf), LINELEN - 1 - strlen(buf),
70 format, alist);
71 if ((c = strchr(buf, '\n')) == NULL) {
72 if ((strlen(buf) + 1) < LINELEN)
73 (void) snprintf(buf + strlen(buf), LINELEN - 1 -
74 strlen(buf), gettext(ERRNO_FMT), strerror(err));
75 } else
76 *c = 0;
77
78 dmesg(level, buf);
79 }
80
81 #ifdef DEBUG_MSG
82 /*PRINTFLIKE1*/
83 void
84 debug(char *format, ...)
85 {
86 va_list alist;
87
88 if (get_message_priority() < RCM_DEBUG)
89 return;
90
91 va_start(alist, format);
92 vdprintfe(RCM_DEBUG, format, alist);
93 va_end(alist);
94 }
95
96 /*PRINTFLIKE1*/
97 void
98 debug_high(char *format, ...)
99 {
100 va_list alist;
101
102 if (get_message_priority() < RCM_DEBUG_HIGH)
103 return;
104
105 va_start(alist, format);
106 vdprintfe(RCM_DEBUG_HIGH, format, alist);
107 va_end(alist);
108 }
109 #endif /* DEBUG_MSG */
110
111 /*PRINTFLIKE1*/
112 void
113 warn(const char *format, ...)
114 {
115 va_list alist;
116
117 if (get_message_priority() < RCM_WARN)
118 return;
119
120 va_start(alist, format);
121 vdprintfe(RCM_WARN, format, alist);
122 va_end(alist);
123 }
124
125 /*PRINTFLIKE1*/
126 void
127 die(char *format, ...)
128 {
129 va_list alist;
130
131 if (get_message_priority() < RCM_ERR)
132 return;
133
134 va_start(alist, format);
135 vdprintfe(RCM_ERR, format, alist);
136 va_end(alist);
137
138 exit(E_ERROR);
139 }
140
141 /*PRINTFLIKE1*/
142 void
143 info(char *format, ...)
144 {
145 va_list alist;
146
147 if (get_message_priority() < RCM_INFO)
148 return;
149
150 va_start(alist, format);
151 vdprintfe(RCM_INFO, format, alist);
152 va_end(alist);
153 }
154
155 char *
156 setpname(char *arg0)
157 {
158 char *p = strrchr(arg0, '/');
159
160 if (p == NULL)
161 p = arg0;
162 else
163 p++;
164 pname = p;
165 return (pname);
166 }
167
168 /*
169 * Output a message to the controlling tty or log, depending on which is
170 * configured. The message should contain no newlines.
171 */
172 static void
173 dmesg(int level, char *msg)
174 {
175 if (message_priority >= level) {
176 FILE *fp;
177 int syslog_severity = -1;
178
179 switch (message_dst) {
180 case RCD_STD:
181 fp = level >= RCM_DEBUG ? stderr : stdout;
182
183 if (pname != NULL) {
184 (void) fputs(pname, fp);
185 (void) fputs(": ", fp);
186 }
187 (void) fputs(msg, fp);
188 (void) fputc('\n', fp);
189 (void) fflush(fp);
190 break;
191 case RCD_SYSLOG:
192 switch (level) {
193 case RCM_ERR:
194 syslog_severity = LOG_ERR;
195 break;
196 case RCM_WARN:
197 syslog_severity = LOG_WARNING;
198 break;
199 case RCM_INFO:
200 syslog_severity = LOG_INFO;
201 break;
202 case RCM_DEBUG:
203 syslog_severity = LOG_DEBUG;
204 break;
205 }
206 if (syslog_severity >= 0)
207 (void) syslog(syslog_severity, "%s", msg);
208 break;
209 }
210 }
211 }
212
213 rcm_level_t
214 get_message_priority(void)
215 {
216 return (message_priority);
217 }
218
219 rcm_level_t
220 set_message_priority(rcm_level_t new_priority)
221 {
222 rcm_level_t old_priority = message_priority;
223
224 message_priority = new_priority;
225 return (old_priority);
226 }
227
228 rcm_dst_t
229 set_message_destination(rcm_dst_t new_dst)
230 {
231 rcm_dst_t old_dst = message_dst;
232
233 if ((message_dst = new_dst) == RCD_SYSLOG)
234 openlog(pname, LOG_ODELAY | LOG_PID, LOG_DAEMON);
235
236 return (old_dst);
237 }
238
239 void
240 hrt2ts(hrtime_t hrt, timestruc_t *tsp)
241 {
242 tsp->tv_sec = hrt / NANOSEC;
243 tsp->tv_nsec = hrt % NANOSEC;
244 }
245
246 int
247 xatoi(char *p)
248 {
249 int i;
250 char *q;
251
252 errno = 0;
253 i = (int)strtol(p, &q, 10);
254 if (errno != 0 || q == p || i < 0 || *q != '\0') {
255 warn(gettext("illegal argument -- %s\n"), p);
256 return (-1);
257 } else {
258 return (i);
259 }
260 }