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 */
25
26 #include <sys/param.h>
27 #include <libintl.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 #include <syslog.h>
33 #include <unistd.h>
34 #include <errno.h>
35
36 #include "utils.h"
37
38 static char ERRNO_FMT[] = ": %s";
39
40 static char *pname = NULL;
41 static rcm_level_t message_priority = RCM_WARN;
42 static rcm_dst_t message_dst = RCD_STD;
43
44 static void dmesg(int level, char *msg);
45
46 /*PRINTFLIKE2*/
47 void
dprintfe(int level,char * format,...)48 dprintfe(int level, char *format, ...)
49 {
50 va_list alist;
51
52 va_start(alist, format);
53 vdprintfe(level, format, alist);
54 va_end(alist);
55 }
56
57 /*PRINTFLIKE2*/
58 void
vdprintfe(int level,const char * format,va_list alist)59 vdprintfe(int level, const char *format, va_list alist)
60 {
61 char buf[LINELEN];
62 char *c;
63 int err = errno;
64
65 *buf = 0;
66
67 if ((strlen(buf) + 1) < LINELEN)
68 (void) vsnprintf(buf + strlen(buf), LINELEN - 1 - strlen(buf),
69 format, alist);
70 if ((c = strchr(buf, '\n')) == NULL) {
71 if ((strlen(buf) + 1) < LINELEN)
72 (void) snprintf(buf + strlen(buf), LINELEN - 1 -
73 strlen(buf), gettext(ERRNO_FMT), strerror(err));
74 } else
75 *c = 0;
76
77 dmesg(level, buf);
78 }
79
80 #ifdef DEBUG_MSG
81 /*PRINTFLIKE1*/
82 void
debug(char * format,...)83 debug(char *format, ...)
84 {
85 va_list alist;
86
87 if (get_message_priority() < RCM_DEBUG)
88 return;
89
90 va_start(alist, format);
91 vdprintfe(RCM_DEBUG, format, alist);
92 va_end(alist);
93 }
94
95 /*PRINTFLIKE1*/
96 void
debug_high(char * format,...)97 debug_high(char *format, ...)
98 {
99 va_list alist;
100
101 if (get_message_priority() < RCM_DEBUG_HIGH)
102 return;
103
104 va_start(alist, format);
105 vdprintfe(RCM_DEBUG_HIGH, format, alist);
106 va_end(alist);
107 }
108 #endif /* DEBUG_MSG */
109
110 /*PRINTFLIKE1*/
111 void
warn(const char * format,...)112 warn(const char *format, ...)
113 {
114 va_list alist;
115
116 if (get_message_priority() < RCM_WARN)
117 return;
118
119 va_start(alist, format);
120 vdprintfe(RCM_WARN, format, alist);
121 va_end(alist);
122 }
123
124 /*PRINTFLIKE1*/
125 void
die(char * format,...)126 die(char *format, ...)
127 {
128 va_list alist;
129
130 if (get_message_priority() < RCM_ERR)
131 return;
132
133 va_start(alist, format);
134 vdprintfe(RCM_ERR, format, alist);
135 va_end(alist);
136
137 exit(E_ERROR);
138 }
139
140 /*PRINTFLIKE1*/
141 void
info(char * format,...)142 info(char *format, ...)
143 {
144 va_list alist;
145
146 if (get_message_priority() < RCM_INFO)
147 return;
148
149 va_start(alist, format);
150 vdprintfe(RCM_INFO, format, alist);
151 va_end(alist);
152 }
153
154 char *
setpname(char * arg0)155 setpname(char *arg0)
156 {
157 char *p = strrchr(arg0, '/');
158
159 if (p == NULL)
160 p = arg0;
161 else
162 p++;
163 pname = p;
164 return (pname);
165 }
166
167 /*
168 * Output a message to the controlling tty or log, depending on which is
169 * configured. The message should contain no newlines.
170 */
171 static void
dmesg(int level,char * msg)172 dmesg(int level, char *msg)
173 {
174 if (message_priority >= level) {
175 FILE *fp;
176 int syslog_severity = -1;
177
178 switch (message_dst) {
179 case RCD_STD:
180 fp = level >= RCM_DEBUG ? stderr : stdout;
181
182 if (pname != NULL) {
183 (void) fputs(pname, fp);
184 (void) fputs(": ", fp);
185 }
186 (void) fputs(msg, fp);
187 (void) fputc('\n', fp);
188 (void) fflush(fp);
189 break;
190 case RCD_SYSLOG:
191 switch (level) {
192 case RCM_ERR:
193 syslog_severity = LOG_ERR;
194 break;
195 case RCM_WARN:
196 syslog_severity = LOG_WARNING;
197 break;
198 case RCM_INFO:
199 syslog_severity = LOG_INFO;
200 break;
201 case RCM_DEBUG:
202 syslog_severity = LOG_DEBUG;
203 break;
204 }
205 if (syslog_severity >= 0)
206 (void) syslog(syslog_severity, "%s", msg);
207 break;
208 }
209 }
210 }
211
212 rcm_level_t
get_message_priority(void)213 get_message_priority(void)
214 {
215 return (message_priority);
216 }
217
218 rcm_level_t
set_message_priority(rcm_level_t new_priority)219 set_message_priority(rcm_level_t new_priority)
220 {
221 rcm_level_t old_priority = message_priority;
222
223 message_priority = new_priority;
224 return (old_priority);
225 }
226
227 rcm_dst_t
set_message_destination(rcm_dst_t new_dst)228 set_message_destination(rcm_dst_t new_dst)
229 {
230 rcm_dst_t old_dst = message_dst;
231
232 if ((message_dst = new_dst) == RCD_SYSLOG)
233 openlog(pname, LOG_ODELAY | LOG_PID, LOG_DAEMON);
234
235 return (old_dst);
236 }
237
238 void
hrt2ts(hrtime_t hrt,timestruc_t * tsp)239 hrt2ts(hrtime_t hrt, timestruc_t *tsp)
240 {
241 tsp->tv_sec = hrt / NANOSEC;
242 tsp->tv_nsec = hrt % NANOSEC;
243 }
244
245 int
xatoi(char * p)246 xatoi(char *p)
247 {
248 int i;
249 char *q;
250
251 errno = 0;
252 i = (int)strtol(p, &q, 10);
253 if (errno != 0 || q == p || i < 0 || *q != '\0') {
254 warn(gettext("illegal argument -- %s\n"), p);
255 return (-1);
256 } else {
257 return (i);
258 }
259 }
260
261 /*
262 * get_running_zones() calls zone_list(2) to find out how many zones are
263 * running. It then calls zone_list(2) again to fetch the list of running
264 * zones (stored in *zents).
265 */
266 int
get_running_zones(uint_t * nzents,zone_entry_t ** zents)267 get_running_zones(uint_t *nzents, zone_entry_t **zents)
268 {
269 zoneid_t *zids;
270 uint_t nzents_saved;
271 int i;
272 zone_entry_t *zentp;
273 zone_state_t zstate;
274
275 *zents = NULL;
276 if (zone_list(NULL, nzents) != 0) {
277 warn(gettext("could not get zoneid list\n"));
278 return (E_ERROR);
279 }
280
281 again:
282 if (*nzents == 0)
283 return (E_SUCCESS);
284
285 if ((zids = (zoneid_t *)calloc(*nzents, sizeof (zoneid_t))) == NULL) {
286 warn(gettext("out of memory: zones will not be capped\n"));
287 return (E_ERROR);
288 }
289
290 nzents_saved = *nzents;
291
292 if (zone_list(zids, nzents) != 0) {
293 warn(gettext("could not get zone list\n"));
294 free(zids);
295 return (E_ERROR);
296 }
297 if (*nzents != nzents_saved) {
298 /* list changed, try again */
299 free(zids);
300 goto again;
301 }
302
303 *zents = calloc(*nzents, sizeof (zone_entry_t));
304 if (*zents == NULL) {
305 warn(gettext("out of memory: zones will not be capped\n"));
306 free(zids);
307 return (E_ERROR);
308 }
309
310 zentp = *zents;
311 for (i = 0; i < *nzents; i++) {
312 char name[ZONENAME_MAX];
313
314 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
315 warn(gettext("could not get name for "
316 "zoneid %d\n"), zids[i]);
317 continue;
318 }
319
320 (void) strlcpy(zentp->zname, name, sizeof (zentp->zname));
321 zentp->zid = zids[i];
322 if (zone_get_state(name, &zstate) != Z_OK ||
323 zstate != ZONE_STATE_RUNNING)
324 continue;
325
326
327 zentp++;
328 }
329 *nzents = zentp - *zents;
330
331 free(zids);
332 return (E_SUCCESS);
333 }
334