Home | History | Annotate | Download | only in svccfg
      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