17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
55703ae8talley * Common Development and Distribution License (the "License").
65703ae8talley * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
221f6eb02Liane Praza * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*
277c478bdstevel@tonic-gate * svccfg - modify service configuration repository
287c478bdstevel@tonic-gate */
297c478bdstevel@tonic-gate
307c478bdstevel@tonic-gate#include <sys/stat.h>
317c478bdstevel@tonic-gate#include <sys/types.h>
327c478bdstevel@tonic-gate#include <sys/wait.h>
337c478bdstevel@tonic-gate
347c478bdstevel@tonic-gate#include <errno.h>
357c478bdstevel@tonic-gate#include <libintl.h>
367c478bdstevel@tonic-gate#include <libscf.h>
377c478bdstevel@tonic-gate#include <libscf_priv.h>
387c478bdstevel@tonic-gate#include <libuutil.h>
397c478bdstevel@tonic-gate#include <locale.h>
407c478bdstevel@tonic-gate#include <signal.h>
417c478bdstevel@tonic-gate#include <stdarg.h>
427c478bdstevel@tonic-gate#include <stddef.h>
437c478bdstevel@tonic-gate#include <stdio.h>
447c478bdstevel@tonic-gate#include <stdlib.h>
457c478bdstevel@tonic-gate#include <string.h>
467c478bdstevel@tonic-gate#include <unistd.h>
477c478bdstevel@tonic-gate
487c478bdstevel@tonic-gate#include "svccfg.h"
497c478bdstevel@tonic-gate
507c478bdstevel@tonic-gate#ifndef TEXT_DOMAIN
517c478bdstevel@tonic-gate#define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
527c478bdstevel@tonic-gate#endif /* TEXT_DOMAIN */
537c478bdstevel@tonic-gate
547c478bdstevel@tonic-gate#define	MAX_CMD_LINE_SZ	2048
557c478bdstevel@tonic-gate
567c478bdstevel@tonic-gatestatic const char *myname;
577c478bdstevel@tonic-gateint g_verbose = 0;
587c478bdstevel@tonic-gateconst char *fmri;
597c478bdstevel@tonic-gate
607c478bdstevel@tonic-gatestatic void
617c478bdstevel@tonic-gateusage()
627c478bdstevel@tonic-gate{
637c478bdstevel@tonic-gate	(void) fprintf(stderr, gettext(
647c478bdstevel@tonic-gate	    "Usage:\tsvccfg [-v] [-s FMRI] [-f file]\n"
657c478bdstevel@tonic-gate	    "\tsvccfg [-v] [-s FMRI] <command> [args]\n"));
667c478bdstevel@tonic-gate	exit(UU_EXIT_USAGE);
677c478bdstevel@tonic-gate}
687c478bdstevel@tonic-gate
697c478bdstevel@tonic-gatevoid *
707c478bdstevel@tonic-gatesafe_malloc(size_t sz)
717c478bdstevel@tonic-gate{
727c478bdstevel@tonic-gate	void *p;
737c478bdstevel@tonic-gate
747c478bdstevel@tonic-gate	if ((p = calloc(1, sz)) == NULL)
757c478bdstevel@tonic-gate		uu_die(gettext("Out of memory.\n"));
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gate	return (p);
787c478bdstevel@tonic-gate}
797c478bdstevel@tonic-gate
807c478bdstevel@tonic-gatechar *
817c478bdstevel@tonic-gatesafe_strdup(const char *cp)
827c478bdstevel@tonic-gate{
837c478bdstevel@tonic-gate	char *result;
847c478bdstevel@tonic-gate
857c478bdstevel@tonic-gate	result = strdup(cp);
867c478bdstevel@tonic-gate	if (result == NULL)
877c478bdstevel@tonic-gate		uu_die(gettext("Out of memory.\n"));
887c478bdstevel@tonic-gate
897c478bdstevel@tonic-gate	return (result);
907c478bdstevel@tonic-gate}
917c478bdstevel@tonic-gate
927c478bdstevel@tonic-gate/*
937c478bdstevel@tonic-gate * Send a message to the user.  If we're interactive, send it to stdout.
947c478bdstevel@tonic-gate * Otherwise send it to stderr.
957c478bdstevel@tonic-gate */
967c478bdstevel@tonic-gatestatic void
977c478bdstevel@tonic-gatevmessage(const char *fmt, va_list va)
987c478bdstevel@tonic-gate{
997c478bdstevel@tonic-gate	int interactive = est->sc_cmd_flags & SC_CMD_IACTIVE;
1007c478bdstevel@tonic-gate	FILE *strm = interactive ? stdout : stderr;
1017c478bdstevel@tonic-gate	const char *ptr;
1027c478bdstevel@tonic-gate
1037c478bdstevel@tonic-gate	if (!interactive) {
1047c478bdstevel@tonic-gate		if (est->sc_cmd_file == NULL)
1057c478bdstevel@tonic-gate			(void) fprintf(stderr, "%s: ", myname);
1067c478bdstevel@tonic-gate		else
1077c478bdstevel@tonic-gate			(void) fprintf(stderr, "%s (%s, line %d): ", myname,
1087c478bdstevel@tonic-gate			    est->sc_cmd_filename, est->sc_cmd_lineno - 1);
1097c478bdstevel@tonic-gate	}
1107c478bdstevel@tonic-gate
1117c478bdstevel@tonic-gate	if (vfprintf(strm, fmt, va) < 0 && interactive)
1127c478bdstevel@tonic-gate		uu_die(gettext("printf() error"));
1137c478bdstevel@tonic-gate
1147c478bdstevel@tonic-gate	ptr = strchr(fmt, '\0');
1157c478bdstevel@tonic-gate	if (*(ptr - 1) != '\n')
1167c478bdstevel@tonic-gate		(void) fprintf(strm, ": %s.\n", strerror(errno));
1177c478bdstevel@tonic-gate}
1187c478bdstevel@tonic-gate
1197c478bdstevel@tonic-gate/*
1207c478bdstevel@tonic-gate * Display a warning.  Should usually be predicated by g_verbose.
1217c478bdstevel@tonic-gate */
1227c478bdstevel@tonic-gate/* PRINTFLIKE1 */
1237c478bdstevel@tonic-gatevoid
1247c478bdstevel@tonic-gatewarn(const char *fmt, ...)
1257c478bdstevel@tonic-gate{
1267c478bdstevel@tonic-gate	va_list va;
1277c478bdstevel@tonic-gate
1287c478bdstevel@tonic-gate	va_start(va, fmt);
1297c478bdstevel@tonic-gate	vmessage(fmt, va);
1307c478bdstevel@tonic-gate	va_end(va);
1317c478bdstevel@tonic-gate}
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gate/*
1347c478bdstevel@tonic-gate * Syntax error.
1357c478bdstevel@tonic-gate */
1367c478bdstevel@tonic-gatevoid
1377c478bdstevel@tonic-gatesynerr(int com)
1387c478bdstevel@tonic-gate{
1397c478bdstevel@tonic-gate	if (est->sc_cmd_flags & SC_CMD_IACTIVE) {
1407c478bdstevel@tonic-gate		help(com);
1417c478bdstevel@tonic-gate		return;
1427c478bdstevel@tonic-gate	}
1437c478bdstevel@tonic-gate
1447c478bdstevel@tonic-gate	warn(gettext("Syntax error.\n"));
1455703ae8talley
1465703ae8talley	if ((est->sc_cmd_flags & SC_CMD_DONT_EXIT) == 0)
1475703ae8talley		exit(1);
1487c478bdstevel@tonic-gate}
1497c478bdstevel@tonic-gate
1507c478bdstevel@tonic-gate/*
1517c478bdstevel@tonic-gate * Semantic error.  Display the warning and exit if we're not interactive.
1527c478bdstevel@tonic-gate */
1537c478bdstevel@tonic-gate/* PRINTFLIKE1 */
1547c478bdstevel@tonic-gatevoid
1557c478bdstevel@tonic-gatesemerr(const char *fmt, ...)
1567c478bdstevel@tonic-gate{
1577c478bdstevel@tonic-gate	va_list va;
1587c478bdstevel@tonic-gate
1597c478bdstevel@tonic-gate	va_start(va, fmt);
1607c478bdstevel@tonic-gate	vmessage(fmt, va);
1617c478bdstevel@tonic-gate	va_end(va);
1627c478bdstevel@tonic-gate
1637c478bdstevel@tonic-gate	if ((est->sc_cmd_flags & (SC_CMD_IACTIVE | SC_CMD_DONT_EXIT)) == 0)
1647c478bdstevel@tonic-gate		exit(1);
1657c478bdstevel@tonic-gate}
1667c478bdstevel@tonic-gate
1677c478bdstevel@tonic-gate/*ARGSUSED*/
1687c478bdstevel@tonic-gatestatic void
1697c478bdstevel@tonic-gateinitialize(int argc, char *argv[])
1707c478bdstevel@tonic-gate{
1717c478bdstevel@tonic-gate	myname = uu_setpname(argv[0]);
1727c478bdstevel@tonic-gate	(void) atexit(lscf_cleanup);
1737c478bdstevel@tonic-gate
1747c478bdstevel@tonic-gate	(void) setlocale(LC_ALL, "");
1757c478bdstevel@tonic-gate	(void) textdomain(TEXT_DOMAIN);
1767c478bdstevel@tonic-gate
1777c478bdstevel@tonic-gate	(void) lxml_init();
1787c478bdstevel@tonic-gate	internal_init();
1797c478bdstevel@tonic-gate	engine_init();
1807c478bdstevel@tonic-gate	lscf_init();			/* must follow engine_init() */
1811f6eb02Liane Praza	tmpl_init();
1827c478bdstevel@tonic-gate}
1837c478bdstevel@tonic-gate
1847c478bdstevel@tonic-gateint
1857c478bdstevel@tonic-gatemain(int argc, char *argv[])
1867c478bdstevel@tonic-gate{
1877c478bdstevel@tonic-gate	char *cmd, *command_file = NULL;
1887c478bdstevel@tonic-gate	char *fmri = NULL;
1897c478bdstevel@tonic-gate	int c;
1907c478bdstevel@tonic-gate
1917c478bdstevel@tonic-gate	while ((c = getopt(argc, argv, "vf:s:")) != EOF)
1927c478bdstevel@tonic-gate		switch (c) {
1937c478bdstevel@tonic-gate		case 'v':
1947c478bdstevel@tonic-gate			g_verbose = 1;
1957c478bdstevel@tonic-gate			break;
1967c478bdstevel@tonic-gate
1977c478bdstevel@tonic-gate		case 's':
1987c478bdstevel@tonic-gate			fmri = optarg;
1997c478bdstevel@tonic-gate			break;
2007c478bdstevel@tonic-gate
2017c478bdstevel@tonic-gate		case 'f':
2027c478bdstevel@tonic-gate			command_file = optarg;
2037c478bdstevel@tonic-gate			break;
2047c478bdstevel@tonic-gate
2057c478bdstevel@tonic-gate		default:
2067c478bdstevel@tonic-gate			usage();
2077c478bdstevel@tonic-gate			break;
2087c478bdstevel@tonic-gate		}
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate	initialize(argc, argv);
2117c478bdstevel@tonic-gate
2127c478bdstevel@tonic-gate	if (fmri != NULL)
2137c478bdstevel@tonic-gate		lscf_select(fmri);
2147c478bdstevel@tonic-gate
2157c478bdstevel@tonic-gate	if (command_file != NULL)
2167c478bdstevel@tonic-gate		return (engine_source(command_file, 0));
2177c478bdstevel@tonic-gate
2187c478bdstevel@tonic-gate	if (optind == argc) {
2197c478bdstevel@tonic-gate		if (isatty(fileno(stdin)))
2207c478bdstevel@tonic-gate			return (engine_interp());
2217c478bdstevel@tonic-gate		else
2227c478bdstevel@tonic-gate			return (engine_source("-", 0));
2237c478bdstevel@tonic-gate	}
2247c478bdstevel@tonic-gate
2257c478bdstevel@tonic-gate	/*
2267c478bdstevel@tonic-gate	 * Knit together remaining arguments into a single statement.
2277c478bdstevel@tonic-gate	 */
2287c478bdstevel@tonic-gate	cmd = safe_malloc(MAX_CMD_LINE_SZ);
2297c478bdstevel@tonic-gate	for (c = optind; c < argc; c++) {
2307c478bdstevel@tonic-gate		(void) strlcat(cmd, argv[c], MAX_CMD_LINE_SZ);
2317c478bdstevel@tonic-gate		(void) strlcat(cmd, " ", MAX_CMD_LINE_SZ);
2327c478bdstevel@tonic-gate	}
2337c478bdstevel@tonic-gate
2347c478bdstevel@tonic-gate	return (engine_exec(cmd));
2357c478bdstevel@tonic-gate}
236