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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * svccfg - modify service configuration repository 28 */ 29 30 #include <sys/stat.h> 31 #include <sys/types.h> 32 #include <sys/wait.h> 33 34 #include <errno.h> 35 #include <libintl.h> 36 #include <libscf.h> 37 #include <libscf_priv.h> 38 #include <libuutil.h> 39 #include <locale.h> 40 #include <signal.h> 41 #include <stdarg.h> 42 #include <stddef.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "svccfg.h" 49 50 #ifndef TEXT_DOMAIN 51 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 52 #endif /* TEXT_DOMAIN */ 53 54 #define MAX_CMD_LINE_SZ 2048 55 56 static const char *myname; 57 int g_verbose = 0; 58 const char *fmri; 59 60 static void 61 usage() 62 { 63 (void) fprintf(stderr, gettext( 64 "Usage:\tsvccfg [-v] [-s FMRI] [-f file]\n" 65 "\tsvccfg [-v] [-s FMRI] <command> [args]\n")); 66 exit(UU_EXIT_USAGE); 67 } 68 69 void * 70 safe_malloc(size_t sz) 71 { 72 void *p; 73 74 if ((p = calloc(1, sz)) == NULL) 75 uu_die(gettext("Out of memory.\n")); 76 77 return (p); 78 } 79 80 char * 81 safe_strdup(const char *cp) 82 { 83 char *result; 84 85 result = strdup(cp); 86 if (result == NULL) 87 uu_die(gettext("Out of memory.\n")); 88 89 return (result); 90 } 91 92 /* 93 * Send a message to the user. If we're interactive, send it to stdout. 94 * Otherwise send it to stderr. 95 */ 96 static void 97 vmessage(const char *fmt, va_list va) 98 { 99 int interactive = est->sc_cmd_flags & SC_CMD_IACTIVE; 100 FILE *strm = interactive ? stdout : stderr; 101 const char *ptr; 102 103 if (!interactive) { 104 if (est->sc_cmd_file == NULL) 105 (void) fprintf(stderr, "%s: ", myname); 106 else 107 (void) fprintf(stderr, "%s (%s, line %d): ", myname, 108 est->sc_cmd_filename, est->sc_cmd_lineno - 1); 109 } 110 111 if (vfprintf(strm, fmt, va) < 0 && interactive) 112 uu_die(gettext("printf() error")); 113 114 ptr = strchr(fmt, '\0'); 115 if (*(ptr - 1) != '\n') 116 (void) fprintf(strm, ": %s.\n", strerror(errno)); 117 } 118 119 /* 120 * Display a warning. Should usually be predicated by g_verbose. 121 */ 122 /* PRINTFLIKE1 */ 123 void 124 warn(const char *fmt, ...) 125 { 126 va_list va; 127 128 va_start(va, fmt); 129 vmessage(fmt, va); 130 va_end(va); 131 } 132 133 /* 134 * Syntax error. 135 */ 136 void 137 synerr(int com) 138 { 139 if (est->sc_cmd_flags & SC_CMD_IACTIVE) { 140 help(com); 141 return; 142 } 143 144 warn(gettext("Syntax error.\n")); 145 146 if ((est->sc_cmd_flags & SC_CMD_DONT_EXIT) == 0) 147 exit(1); 148 } 149 150 /* 151 * Semantic error. Display the warning and exit if we're not interactive. 152 */ 153 /* PRINTFLIKE1 */ 154 void 155 semerr(const char *fmt, ...) 156 { 157 va_list va; 158 159 va_start(va, fmt); 160 vmessage(fmt, va); 161 va_end(va); 162 163 if ((est->sc_cmd_flags & (SC_CMD_IACTIVE | SC_CMD_DONT_EXIT)) == 0) 164 exit(1); 165 } 166 167 /*ARGSUSED*/ 168 static void 169 initialize(int argc, char *argv[]) 170 { 171 myname = uu_setpname(argv[0]); 172 (void) atexit(lscf_cleanup); 173 174 (void) setlocale(LC_ALL, ""); 175 (void) textdomain(TEXT_DOMAIN); 176 177 (void) lxml_init(); 178 internal_init(); 179 engine_init(); 180 lscf_init(); /* must follow engine_init() */ 181 tmpl_init(); 182 } 183 184 int 185 main(int argc, char *argv[]) 186 { 187 char *cmd, *command_file = NULL; 188 char *fmri = NULL; 189 int c; 190 191 while ((c = getopt(argc, argv, "vf:s:")) != EOF) 192 switch (c) { 193 case 'v': 194 g_verbose = 1; 195 break; 196 197 case 's': 198 fmri = optarg; 199 break; 200 201 case 'f': 202 command_file = optarg; 203 break; 204 205 default: 206 usage(); 207 break; 208 } 209 210 initialize(argc, argv); 211 212 if (fmri != NULL) 213 lscf_select(fmri); 214 215 if (command_file != NULL) 216 return (engine_source(command_file, 0)); 217 218 if (optind == argc) { 219 if (isatty(fileno(stdin))) 220 return (engine_interp()); 221 else 222 return (engine_source("-", 0)); 223 } 224 225 /* 226 * Knit together remaining arguments into a single statement. 227 */ 228 cmd = safe_malloc(MAX_CMD_LINE_SZ); 229 for (c = optind; c < argc; c++) { 230 (void) strlcat(cmd, argv[c], MAX_CMD_LINE_SZ); 231 (void) strlcat(cmd, " ", MAX_CMD_LINE_SZ); 232 } 233 234 return (engine_exec(cmd)); 235 } 236