17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50209230bSgjelinek * Common Development and Distribution License (the "License"). 60209230bSgjelinek * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*d362b749Svk199839 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/param.h> 297c478bd9Sstevel@tonic-gate #include <libintl.h> 307c478bd9Sstevel@tonic-gate #include <stdarg.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <syslog.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include "utils.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate static char ERRNO_FMT[] = ": %s"; 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate static char *pname = NULL; 437c478bd9Sstevel@tonic-gate static rcm_level_t message_priority = RCM_WARN; 447c478bd9Sstevel@tonic-gate static rcm_dst_t message_dst = RCD_STD; 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate static void dmesg(int level, char *msg); 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 497c478bd9Sstevel@tonic-gate void 507c478bd9Sstevel@tonic-gate dprintfe(int level, char *format, ...) 517c478bd9Sstevel@tonic-gate { 527c478bd9Sstevel@tonic-gate va_list alist; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate va_start(alist, format); 557c478bd9Sstevel@tonic-gate vdprintfe(level, format, alist); 567c478bd9Sstevel@tonic-gate va_end(alist); 577c478bd9Sstevel@tonic-gate } 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 607c478bd9Sstevel@tonic-gate void 61*d362b749Svk199839 vdprintfe(int level, const char *format, va_list alist) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate char buf[LINELEN]; 647c478bd9Sstevel@tonic-gate char *c; 657c478bd9Sstevel@tonic-gate int err = errno; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate *buf = 0; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if ((strlen(buf) + 1) < LINELEN) 707c478bd9Sstevel@tonic-gate (void) vsnprintf(buf + strlen(buf), LINELEN - 1 - strlen(buf), 717c478bd9Sstevel@tonic-gate format, alist); 727c478bd9Sstevel@tonic-gate if ((c = strchr(buf, '\n')) == NULL) { 737c478bd9Sstevel@tonic-gate if ((strlen(buf) + 1) < LINELEN) 747c478bd9Sstevel@tonic-gate (void) snprintf(buf + strlen(buf), LINELEN - 1 - 757c478bd9Sstevel@tonic-gate strlen(buf), gettext(ERRNO_FMT), strerror(err)); 767c478bd9Sstevel@tonic-gate } else 777c478bd9Sstevel@tonic-gate *c = 0; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate dmesg(level, buf); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate #ifdef DEBUG_MSG 837c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 847c478bd9Sstevel@tonic-gate void 857c478bd9Sstevel@tonic-gate debug(char *format, ...) 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate va_list alist; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if (get_message_priority() < RCM_DEBUG) 907c478bd9Sstevel@tonic-gate return; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate va_start(alist, format); 937c478bd9Sstevel@tonic-gate vdprintfe(RCM_DEBUG, format, alist); 947c478bd9Sstevel@tonic-gate va_end(alist); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 987c478bd9Sstevel@tonic-gate void 997c478bd9Sstevel@tonic-gate debug_high(char *format, ...) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate va_list alist; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate if (get_message_priority() < RCM_DEBUG_HIGH) 1047c478bd9Sstevel@tonic-gate return; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate va_start(alist, format); 1077c478bd9Sstevel@tonic-gate vdprintfe(RCM_DEBUG_HIGH, format, alist); 1087c478bd9Sstevel@tonic-gate va_end(alist); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate #endif /* DEBUG_MSG */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1137c478bd9Sstevel@tonic-gate void 114*d362b749Svk199839 warn(const char *format, ...) 1157c478bd9Sstevel@tonic-gate { 1167c478bd9Sstevel@tonic-gate va_list alist; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate if (get_message_priority() < RCM_WARN) 1197c478bd9Sstevel@tonic-gate return; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate va_start(alist, format); 1227c478bd9Sstevel@tonic-gate vdprintfe(RCM_WARN, format, alist); 1237c478bd9Sstevel@tonic-gate va_end(alist); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1277c478bd9Sstevel@tonic-gate void 1287c478bd9Sstevel@tonic-gate die(char *format, ...) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate va_list alist; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if (get_message_priority() < RCM_ERR) 1337c478bd9Sstevel@tonic-gate return; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate va_start(alist, format); 1367c478bd9Sstevel@tonic-gate vdprintfe(RCM_ERR, format, alist); 1377c478bd9Sstevel@tonic-gate va_end(alist); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate exit(E_ERROR); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1437c478bd9Sstevel@tonic-gate void 1447c478bd9Sstevel@tonic-gate info(char *format, ...) 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate va_list alist; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if (get_message_priority() < RCM_INFO) 1497c478bd9Sstevel@tonic-gate return; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate va_start(alist, format); 1527c478bd9Sstevel@tonic-gate vdprintfe(RCM_INFO, format, alist); 1537c478bd9Sstevel@tonic-gate va_end(alist); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate char * 1577c478bd9Sstevel@tonic-gate setprogname(char *arg0) 1587c478bd9Sstevel@tonic-gate { 1597c478bd9Sstevel@tonic-gate char *p = strrchr(arg0, '/'); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (p == NULL) 1627c478bd9Sstevel@tonic-gate p = arg0; 1637c478bd9Sstevel@tonic-gate else 1647c478bd9Sstevel@tonic-gate p++; 1657c478bd9Sstevel@tonic-gate pname = p; 1667c478bd9Sstevel@tonic-gate return (pname); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * Output a message to the controlling tty or log, depending on which is 1717c478bd9Sstevel@tonic-gate * configured. The message should contain no newlines. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate static void 1747c478bd9Sstevel@tonic-gate dmesg(int level, char *msg) 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate if (message_priority >= level) { 1777c478bd9Sstevel@tonic-gate FILE *fp; 1787c478bd9Sstevel@tonic-gate int syslog_severity = -1; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate switch (message_dst) { 1817c478bd9Sstevel@tonic-gate case RCD_STD: 1827c478bd9Sstevel@tonic-gate fp = level >= RCM_DEBUG ? stderr : stdout; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (pname != NULL) { 1857c478bd9Sstevel@tonic-gate (void) fputs(pname, fp); 1867c478bd9Sstevel@tonic-gate (void) fputs(": ", fp); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate (void) fputs(msg, fp); 1897c478bd9Sstevel@tonic-gate (void) fputc('\n', fp); 1907c478bd9Sstevel@tonic-gate (void) fflush(fp); 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate case RCD_SYSLOG: 1937c478bd9Sstevel@tonic-gate switch (level) { 1947c478bd9Sstevel@tonic-gate case RCM_ERR: 1957c478bd9Sstevel@tonic-gate syslog_severity = LOG_ERR; 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate case RCM_WARN: 1987c478bd9Sstevel@tonic-gate syslog_severity = LOG_WARNING; 1997c478bd9Sstevel@tonic-gate break; 2007c478bd9Sstevel@tonic-gate case RCM_INFO: 2017c478bd9Sstevel@tonic-gate syslog_severity = LOG_INFO; 2027c478bd9Sstevel@tonic-gate break; 2037c478bd9Sstevel@tonic-gate case RCM_DEBUG: 2047c478bd9Sstevel@tonic-gate syslog_severity = LOG_DEBUG; 2057c478bd9Sstevel@tonic-gate break; 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate if (syslog_severity >= 0) 2087c478bd9Sstevel@tonic-gate (void) syslog(syslog_severity, "%s", msg); 2097c478bd9Sstevel@tonic-gate break; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate rcm_level_t 2157c478bd9Sstevel@tonic-gate get_message_priority(void) 2167c478bd9Sstevel@tonic-gate { 2177c478bd9Sstevel@tonic-gate return (message_priority); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate rcm_level_t 2217c478bd9Sstevel@tonic-gate set_message_priority(rcm_level_t new_priority) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate rcm_level_t old_priority = message_priority; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate message_priority = new_priority; 2267c478bd9Sstevel@tonic-gate return (old_priority); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate rcm_dst_t 2307c478bd9Sstevel@tonic-gate set_message_destination(rcm_dst_t new_dst) 2317c478bd9Sstevel@tonic-gate { 2327c478bd9Sstevel@tonic-gate rcm_dst_t old_dst = message_dst; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if ((message_dst = new_dst) == RCD_SYSLOG) 2357c478bd9Sstevel@tonic-gate openlog(pname, LOG_ODELAY | LOG_PID, LOG_DAEMON); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate return (old_dst); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate void 2417c478bd9Sstevel@tonic-gate hrt2ts(hrtime_t hrt, timestruc_t *tsp) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate tsp->tv_sec = hrt / NANOSEC; 2447c478bd9Sstevel@tonic-gate tsp->tv_nsec = hrt % NANOSEC; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate int 2487c478bd9Sstevel@tonic-gate xatoi(char *p) 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate int i; 2517c478bd9Sstevel@tonic-gate char *q; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate errno = 0; 2547c478bd9Sstevel@tonic-gate i = (int)strtol(p, &q, 10); 2557c478bd9Sstevel@tonic-gate if (errno != 0 || q == p || i < 0 || *q != '\0') { 2567c478bd9Sstevel@tonic-gate warn(gettext("illegal argument -- %s\n"), p); 2577c478bd9Sstevel@tonic-gate return (-1); 2587c478bd9Sstevel@tonic-gate } else { 2597c478bd9Sstevel@tonic-gate return (i); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate } 2620209230bSgjelinek 2630209230bSgjelinek /* 2640209230bSgjelinek * get_running_zones() calls zone_list(2) to find out how many zones are 2650209230bSgjelinek * running. It then calls zone_list(2) again to fetch the list of running 2660209230bSgjelinek * zones (stored in *zents). 2670209230bSgjelinek */ 2680209230bSgjelinek int 2690209230bSgjelinek get_running_zones(uint_t *nzents, zone_entry_t **zents) 2700209230bSgjelinek { 2710209230bSgjelinek zoneid_t *zids; 2720209230bSgjelinek uint_t nzents_saved; 2730209230bSgjelinek int i; 2740209230bSgjelinek zone_entry_t *zentp; 2750209230bSgjelinek zone_state_t zstate; 2760209230bSgjelinek 2770209230bSgjelinek *zents = NULL; 2780209230bSgjelinek if (zone_list(NULL, nzents) != 0) { 2790209230bSgjelinek warn(gettext("could not get zoneid list\n")); 2800209230bSgjelinek return (E_ERROR); 2810209230bSgjelinek } 2820209230bSgjelinek 2830209230bSgjelinek again: 2840209230bSgjelinek if (*nzents == 0) 2850209230bSgjelinek return (E_SUCCESS); 2860209230bSgjelinek 2870209230bSgjelinek if ((zids = (zoneid_t *)calloc(*nzents, sizeof (zoneid_t))) == NULL) { 2880209230bSgjelinek warn(gettext("out of memory: zones will not be capped\n")); 2890209230bSgjelinek return (E_ERROR); 2900209230bSgjelinek } 2910209230bSgjelinek 2920209230bSgjelinek nzents_saved = *nzents; 2930209230bSgjelinek 2940209230bSgjelinek if (zone_list(zids, nzents) != 0) { 2950209230bSgjelinek warn(gettext("could not get zone list\n")); 2960209230bSgjelinek free(zids); 2970209230bSgjelinek return (E_ERROR); 2980209230bSgjelinek } 2990209230bSgjelinek if (*nzents != nzents_saved) { 3000209230bSgjelinek /* list changed, try again */ 3010209230bSgjelinek free(zids); 3020209230bSgjelinek goto again; 3030209230bSgjelinek } 3040209230bSgjelinek 3050209230bSgjelinek *zents = calloc(*nzents, sizeof (zone_entry_t)); 3060209230bSgjelinek if (*zents == NULL) { 3070209230bSgjelinek warn(gettext("out of memory: zones will not be capped\n")); 3080209230bSgjelinek free(zids); 3090209230bSgjelinek return (E_ERROR); 3100209230bSgjelinek } 3110209230bSgjelinek 3120209230bSgjelinek zentp = *zents; 3130209230bSgjelinek for (i = 0; i < *nzents; i++) { 3140209230bSgjelinek char name[ZONENAME_MAX]; 3150209230bSgjelinek 3160209230bSgjelinek if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { 3170209230bSgjelinek warn(gettext("could not get name for " 3180209230bSgjelinek "zoneid %d\n"), zids[i]); 3190209230bSgjelinek continue; 3200209230bSgjelinek } 3210209230bSgjelinek 3220209230bSgjelinek (void) strlcpy(zentp->zname, name, sizeof (zentp->zname)); 3230209230bSgjelinek zentp->zid = zids[i]; 3240209230bSgjelinek if (zone_get_state(name, &zstate) != Z_OK || 3250209230bSgjelinek zstate != ZONE_STATE_RUNNING) 3260209230bSgjelinek continue; 3270209230bSgjelinek 3280209230bSgjelinek 3290209230bSgjelinek zentp++; 3300209230bSgjelinek } 3310209230bSgjelinek *nzents = zentp - *zents; 3320209230bSgjelinek 3330209230bSgjelinek free(zids); 3340209230bSgjelinek return (E_SUCCESS); 3350209230bSgjelinek } 336