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