10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2643Stalley * Common Development and Distribution License (the "License"). 6*2643Stalley * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2643Stalley * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * svccfg - modify service configuration repository 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <sys/stat.h> 330Sstevel@tonic-gate #include <sys/types.h> 340Sstevel@tonic-gate #include <sys/wait.h> 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <errno.h> 370Sstevel@tonic-gate #include <libintl.h> 380Sstevel@tonic-gate #include <libscf.h> 390Sstevel@tonic-gate #include <libscf_priv.h> 400Sstevel@tonic-gate #include <libuutil.h> 410Sstevel@tonic-gate #include <locale.h> 420Sstevel@tonic-gate #include <signal.h> 430Sstevel@tonic-gate #include <stdarg.h> 440Sstevel@tonic-gate #include <stddef.h> 450Sstevel@tonic-gate #include <stdio.h> 460Sstevel@tonic-gate #include <stdlib.h> 470Sstevel@tonic-gate #include <string.h> 480Sstevel@tonic-gate #include <unistd.h> 490Sstevel@tonic-gate 500Sstevel@tonic-gate #include "svccfg.h" 510Sstevel@tonic-gate 520Sstevel@tonic-gate #ifndef TEXT_DOMAIN 530Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD" 540Sstevel@tonic-gate #endif /* TEXT_DOMAIN */ 550Sstevel@tonic-gate 560Sstevel@tonic-gate #define MAX_CMD_LINE_SZ 2048 570Sstevel@tonic-gate 580Sstevel@tonic-gate static const char *myname; 590Sstevel@tonic-gate int g_verbose = 0; 600Sstevel@tonic-gate const char *fmri; 610Sstevel@tonic-gate 620Sstevel@tonic-gate static void 630Sstevel@tonic-gate usage() 640Sstevel@tonic-gate { 650Sstevel@tonic-gate (void) fprintf(stderr, gettext( 660Sstevel@tonic-gate "Usage:\tsvccfg [-v] [-s FMRI] [-f file]\n" 670Sstevel@tonic-gate "\tsvccfg [-v] [-s FMRI] <command> [args]\n")); 680Sstevel@tonic-gate exit(UU_EXIT_USAGE); 690Sstevel@tonic-gate } 700Sstevel@tonic-gate 710Sstevel@tonic-gate void * 720Sstevel@tonic-gate safe_malloc(size_t sz) 730Sstevel@tonic-gate { 740Sstevel@tonic-gate void *p; 750Sstevel@tonic-gate 760Sstevel@tonic-gate if ((p = calloc(1, sz)) == NULL) 770Sstevel@tonic-gate uu_die(gettext("Out of memory.\n")); 780Sstevel@tonic-gate 790Sstevel@tonic-gate return (p); 800Sstevel@tonic-gate } 810Sstevel@tonic-gate 820Sstevel@tonic-gate char * 830Sstevel@tonic-gate safe_strdup(const char *cp) 840Sstevel@tonic-gate { 850Sstevel@tonic-gate char *result; 860Sstevel@tonic-gate 870Sstevel@tonic-gate result = strdup(cp); 880Sstevel@tonic-gate if (result == NULL) 890Sstevel@tonic-gate uu_die(gettext("Out of memory.\n")); 900Sstevel@tonic-gate 910Sstevel@tonic-gate return (result); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* 950Sstevel@tonic-gate * Send a message to the user. If we're interactive, send it to stdout. 960Sstevel@tonic-gate * Otherwise send it to stderr. 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate static void 990Sstevel@tonic-gate vmessage(const char *fmt, va_list va) 1000Sstevel@tonic-gate { 1010Sstevel@tonic-gate int interactive = est->sc_cmd_flags & SC_CMD_IACTIVE; 1020Sstevel@tonic-gate FILE *strm = interactive ? stdout : stderr; 1030Sstevel@tonic-gate const char *ptr; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (!interactive) { 1060Sstevel@tonic-gate if (est->sc_cmd_file == NULL) 1070Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", myname); 1080Sstevel@tonic-gate else 1090Sstevel@tonic-gate (void) fprintf(stderr, "%s (%s, line %d): ", myname, 1100Sstevel@tonic-gate est->sc_cmd_filename, est->sc_cmd_lineno - 1); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate if (vfprintf(strm, fmt, va) < 0 && interactive) 1140Sstevel@tonic-gate uu_die(gettext("printf() error")); 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate ptr = strchr(fmt, '\0'); 1170Sstevel@tonic-gate if (*(ptr - 1) != '\n') 1180Sstevel@tonic-gate (void) fprintf(strm, ": %s.\n", strerror(errno)); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate /* 1220Sstevel@tonic-gate * Display a warning. Should usually be predicated by g_verbose. 1230Sstevel@tonic-gate */ 1240Sstevel@tonic-gate /* PRINTFLIKE1 */ 1250Sstevel@tonic-gate void 1260Sstevel@tonic-gate warn(const char *fmt, ...) 1270Sstevel@tonic-gate { 1280Sstevel@tonic-gate va_list va; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate va_start(va, fmt); 1310Sstevel@tonic-gate vmessage(fmt, va); 1320Sstevel@tonic-gate va_end(va); 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* 1360Sstevel@tonic-gate * Syntax error. 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate void 1390Sstevel@tonic-gate synerr(int com) 1400Sstevel@tonic-gate { 1410Sstevel@tonic-gate if (est->sc_cmd_flags & SC_CMD_IACTIVE) { 1420Sstevel@tonic-gate help(com); 1430Sstevel@tonic-gate return; 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate warn(gettext("Syntax error.\n")); 147*2643Stalley 148*2643Stalley if ((est->sc_cmd_flags & SC_CMD_DONT_EXIT) == 0) 149*2643Stalley exit(1); 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate /* 1530Sstevel@tonic-gate * Semantic error. Display the warning and exit if we're not interactive. 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate /* PRINTFLIKE1 */ 1560Sstevel@tonic-gate void 1570Sstevel@tonic-gate semerr(const char *fmt, ...) 1580Sstevel@tonic-gate { 1590Sstevel@tonic-gate va_list va; 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate va_start(va, fmt); 1620Sstevel@tonic-gate vmessage(fmt, va); 1630Sstevel@tonic-gate va_end(va); 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate if ((est->sc_cmd_flags & (SC_CMD_IACTIVE | SC_CMD_DONT_EXIT)) == 0) 1660Sstevel@tonic-gate exit(1); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate /*ARGSUSED*/ 1700Sstevel@tonic-gate static void 1710Sstevel@tonic-gate initialize(int argc, char *argv[]) 1720Sstevel@tonic-gate { 1730Sstevel@tonic-gate myname = uu_setpname(argv[0]); 1740Sstevel@tonic-gate (void) atexit(lscf_cleanup); 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1770Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate (void) lxml_init(); 1800Sstevel@tonic-gate internal_init(); 1810Sstevel@tonic-gate engine_init(); 1820Sstevel@tonic-gate lscf_init(); /* must follow engine_init() */ 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate int 1860Sstevel@tonic-gate main(int argc, char *argv[]) 1870Sstevel@tonic-gate { 1880Sstevel@tonic-gate char *cmd, *command_file = NULL; 1890Sstevel@tonic-gate char *fmri = NULL; 1900Sstevel@tonic-gate int c; 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate while ((c = getopt(argc, argv, "vf:s:")) != EOF) 1930Sstevel@tonic-gate switch (c) { 1940Sstevel@tonic-gate case 'v': 1950Sstevel@tonic-gate g_verbose = 1; 1960Sstevel@tonic-gate break; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate case 's': 1990Sstevel@tonic-gate fmri = optarg; 2000Sstevel@tonic-gate break; 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate case 'f': 2030Sstevel@tonic-gate command_file = optarg; 2040Sstevel@tonic-gate break; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate default: 2070Sstevel@tonic-gate usage(); 2080Sstevel@tonic-gate break; 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate initialize(argc, argv); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate if (fmri != NULL) 2140Sstevel@tonic-gate lscf_select(fmri); 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate if (command_file != NULL) 2170Sstevel@tonic-gate return (engine_source(command_file, 0)); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate if (optind == argc) { 2200Sstevel@tonic-gate if (isatty(fileno(stdin))) 2210Sstevel@tonic-gate return (engine_interp()); 2220Sstevel@tonic-gate else 2230Sstevel@tonic-gate return (engine_source("-", 0)); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate /* 2270Sstevel@tonic-gate * Knit together remaining arguments into a single statement. 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate cmd = safe_malloc(MAX_CMD_LINE_SZ); 2300Sstevel@tonic-gate for (c = optind; c < argc; c++) { 2310Sstevel@tonic-gate (void) strlcat(cmd, argv[c], MAX_CMD_LINE_SZ); 2320Sstevel@tonic-gate (void) strlcat(cmd, " ", MAX_CMD_LINE_SZ); 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate return (engine_exec(cmd)); 2360Sstevel@tonic-gate } 237