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 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 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 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 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 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 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 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 * 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 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 213 get_message_priority(void) 214 { 215 return (message_priority); 216 } 217 218 rcm_level_t 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 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 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 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 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