xref: /illumos-gate/usr/src/cmd/svc/svcprop/svcprop.c (revision 3eae19d9cf3390cf5b75e10c9c1945fd36ad856a)
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
5*3eae19d9Swesolows  * Common Development and Distribution License (the "License").
6*3eae19d9Swesolows  * 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  */
21*3eae19d9Swesolows 
227c478bd9Sstevel@tonic-gate /*
23*3eae19d9Swesolows  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * svcprop - report service configuration properties
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <locale.h>
347c478bd9Sstevel@tonic-gate #include <libintl.h>
357c478bd9Sstevel@tonic-gate #include <libscf.h>
367c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
377c478bd9Sstevel@tonic-gate #include <libuutil.h>
387c478bd9Sstevel@tonic-gate #include <stddef.h>
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <unistd.h>
427c478bd9Sstevel@tonic-gate #include <strings.h>
437c478bd9Sstevel@tonic-gate #include <assert.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
467c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
477c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Error functions.  These can change if the quiet (-q) option is used.
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate static void (*warn)(const char *, ...) = uu_warn;
537c478bd9Sstevel@tonic-gate static void (*die)(const char *, ...) = uu_die;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * Entity encapsulation.  This allows me to treat services and instances
577c478bd9Sstevel@tonic-gate  * similarly, and avoid duplicating process_ent().
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate typedef struct {
607c478bd9Sstevel@tonic-gate 	char type;			/* !=0: service, 0: instance */
617c478bd9Sstevel@tonic-gate 	union {
627c478bd9Sstevel@tonic-gate 		scf_service_t *svc;
637c478bd9Sstevel@tonic-gate 		scf_instance_t *inst;
647c478bd9Sstevel@tonic-gate 	} u;
657c478bd9Sstevel@tonic-gate } scf_entityp_t;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #define	ENT_INSTANCE	0
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	SCF_ENTITY_SET_TO_SERVICE(ent, s)	{ ent.type = 1; ent.u.svc = s; }
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #define	SCF_ENTITY_SET_TO_INSTANCE(ent, i)	\
727c478bd9Sstevel@tonic-gate 	{ ent.type = ENT_INSTANCE; ent.u.inst = i; }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate #define	scf_entity_get_pg(ent, name, pg) \
757c478bd9Sstevel@tonic-gate 	(ent.type ? scf_service_get_pg(ent.u.svc, name, pg) : \
767c478bd9Sstevel@tonic-gate 	scf_instance_get_pg(ent.u.inst, name, pg))
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	scf_entity_to_fmri(ent, buf, buf_sz) \
797c478bd9Sstevel@tonic-gate 	(ent.type ? scf_service_to_fmri(ent.u.svc, buf, buf_sz) : \
807c478bd9Sstevel@tonic-gate 	scf_instance_to_fmri(ent.u.inst, buf, buf_sz))
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #define	SCF_ENTITY_TYPE_NAME(ent)	(ent.type ? "service" : "instance")
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Data structure for -p arguments.  Since they may be name or name/name, we
867c478bd9Sstevel@tonic-gate  * just track the components.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate typedef struct svcprop_prop_node {
897c478bd9Sstevel@tonic-gate 	uu_list_node_t	spn_list_node;
907c478bd9Sstevel@tonic-gate 	const char	*spn_comp1;
917c478bd9Sstevel@tonic-gate 	const char	*spn_comp2;
927c478bd9Sstevel@tonic-gate } svcprop_prop_node_t;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate static uu_list_pool_t	*prop_pool;
957c478bd9Sstevel@tonic-gate static uu_list_t	*prop_list;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate static scf_handle_t *hndl;
987c478bd9Sstevel@tonic-gate static ssize_t max_scf_name_length;
997c478bd9Sstevel@tonic-gate static ssize_t max_scf_value_length;
1007c478bd9Sstevel@tonic-gate static ssize_t max_scf_fmri_length;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /* Options */
1037c478bd9Sstevel@tonic-gate static int quiet = 0;			/* No output. Nothing found, exit(1) */
1047c478bd9Sstevel@tonic-gate static int types = 0;			/* Display types of properties. */
1057c478bd9Sstevel@tonic-gate static int verbose = 0;			/* Print not found errors to stderr. */
1067c478bd9Sstevel@tonic-gate static int fmris = 0;			/* Display full FMRIs for properties. */
1077c478bd9Sstevel@tonic-gate static int wait = 0;			/* Wait mode. */
1087c478bd9Sstevel@tonic-gate static char *snapshot = "running";	/* Snapshot to use. */
1097c478bd9Sstevel@tonic-gate static int Cflag = 0;			/* C option supplied */
1107c478bd9Sstevel@tonic-gate static int cflag = 0;			/* c option supplied */
1117c478bd9Sstevel@tonic-gate static int sflag = 0;			/* s option supplied */
1127c478bd9Sstevel@tonic-gate static int return_code;			/* main's return code */
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate #define	PRINT_NOPROP_ERRORS	(!quiet || verbose)
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  * For unexpected libscf errors.  The ending newline is necessary to keep
1187c478bd9Sstevel@tonic-gate  * uu_die() from appending the errno error.
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate static void
1217c478bd9Sstevel@tonic-gate scfdie()
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	die(gettext("Unexpected libscf error: %s.  Exiting.\n"),
1247c478bd9Sstevel@tonic-gate 	    scf_strerror(scf_error()));
1257c478bd9Sstevel@tonic-gate }
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate static void *
1287c478bd9Sstevel@tonic-gate safe_malloc(size_t sz)
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate 	void *p;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	p = malloc(sz);
1337c478bd9Sstevel@tonic-gate 	if (p == NULL)
1347c478bd9Sstevel@tonic-gate 		die(gettext("Could not allocate memory"));
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	return (p);
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate static void
1407c478bd9Sstevel@tonic-gate usage()
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Usage: %1$s [-fqtv] "
1437c478bd9Sstevel@tonic-gate 	    "[-C | -c | -s snapshot] "
1447c478bd9Sstevel@tonic-gate 	    "[-p [name/]name]... \n"
1457c478bd9Sstevel@tonic-gate 	    "         {FMRI | pattern}...\n"
1467c478bd9Sstevel@tonic-gate 	    "       %1$s -w [-fqtv] [-p [name/]name] "
1477c478bd9Sstevel@tonic-gate 	    "{FMRI | pattern}\n"), uu_getpname());
1487c478bd9Sstevel@tonic-gate 	exit(UU_EXIT_USAGE);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * Return an allocated copy of str, with the Bourne shell's metacharacters
1537c478bd9Sstevel@tonic-gate  * escaped by '\'.
1547c478bd9Sstevel@tonic-gate  *
1557c478bd9Sstevel@tonic-gate  * What about unicode?
1567c478bd9Sstevel@tonic-gate  */
1577c478bd9Sstevel@tonic-gate static char *
1587c478bd9Sstevel@tonic-gate quote_for_shell(const char *str)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	const char *sp;
1617c478bd9Sstevel@tonic-gate 	char *dst, *dp;
1627c478bd9Sstevel@tonic-gate 	size_t dst_len;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	const char * const metachars = ";&()|^<>\n \t\\\"\'`";
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (str[0] == '\0')
1677c478bd9Sstevel@tonic-gate 		return (strdup("\"\""));
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	dst_len = 0;
1707c478bd9Sstevel@tonic-gate 	for (sp = str; *sp != '\0'; ++sp) {
1717c478bd9Sstevel@tonic-gate 		++dst_len;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 		if (strchr(metachars, *sp) != NULL)
1747c478bd9Sstevel@tonic-gate 			++dst_len;
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	if (sp - str == dst_len)
1787c478bd9Sstevel@tonic-gate 		return (strdup(str));
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	dst = safe_malloc(dst_len + 1);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	for (dp = dst, sp = str; *sp != '\0'; ++dp, ++sp) {
1837c478bd9Sstevel@tonic-gate 		if (strchr(metachars, *sp) != NULL)
1847c478bd9Sstevel@tonic-gate 			*dp++ = '\\';
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 		*dp = *sp;
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 	*dp = '\0';
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	return (dst);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate static void
1947c478bd9Sstevel@tonic-gate print_value(scf_value_t *val)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 	char *buf, *qbuf;
1977c478bd9Sstevel@tonic-gate 	ssize_t bufsz, r;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	bufsz = scf_value_get_as_string(val, NULL, 0) + 1;
2007c478bd9Sstevel@tonic-gate 	if (bufsz - 1 < 0)
2017c478bd9Sstevel@tonic-gate 		scfdie();
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	buf = safe_malloc(bufsz);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	r = scf_value_get_as_string(val, buf, bufsz);
2067c478bd9Sstevel@tonic-gate 	assert(r + 1 == bufsz);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	qbuf = quote_for_shell(buf);
2097c478bd9Sstevel@tonic-gate 	(void) fputs(qbuf, stdout);
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	free(qbuf);
2127c478bd9Sstevel@tonic-gate 	free(buf);
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate /*
2167c478bd9Sstevel@tonic-gate  * Display a property's values on a line.  If types is true, prepend
2177c478bd9Sstevel@tonic-gate  * identification (the FMRI if fmris is true, pg/prop otherwise) and the type
2187c478bd9Sstevel@tonic-gate  * of the property.
2197c478bd9Sstevel@tonic-gate  */
2207c478bd9Sstevel@tonic-gate static void
2217c478bd9Sstevel@tonic-gate display_prop(scf_propertygroup_t *pg, scf_property_t *prop)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	scf_value_t *val;
2247c478bd9Sstevel@tonic-gate 	scf_iter_t *iter;
225*3eae19d9Swesolows 	int ret, first, err;
226*3eae19d9Swesolows 
227*3eae19d9Swesolows 	const char * const permission_denied_emsg =
228*3eae19d9Swesolows 	    gettext("Permission denied.\n");
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (types) {
2317c478bd9Sstevel@tonic-gate 		scf_type_t ty;
2327c478bd9Sstevel@tonic-gate 		char *buf;
2337c478bd9Sstevel@tonic-gate 		size_t buf_sz;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 		if (fmris) {
2367c478bd9Sstevel@tonic-gate 			buf_sz = max_scf_fmri_length + 1;
2377c478bd9Sstevel@tonic-gate 			buf = safe_malloc(buf_sz);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 			if (scf_property_to_fmri(prop, buf, buf_sz) == -1)
2407c478bd9Sstevel@tonic-gate 				scfdie();
2417c478bd9Sstevel@tonic-gate 			(void) fputs(buf, stdout);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 			free(buf);
2447c478bd9Sstevel@tonic-gate 		} else {
2457c478bd9Sstevel@tonic-gate 			buf_sz = max_scf_name_length + 1;
2467c478bd9Sstevel@tonic-gate 			buf = safe_malloc(buf_sz);
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 			if (scf_pg_get_name(pg, buf, buf_sz) < 0)
2497c478bd9Sstevel@tonic-gate 				scfdie();
2507c478bd9Sstevel@tonic-gate 			(void) fputs(buf, stdout);
2517c478bd9Sstevel@tonic-gate 			(void) putchar('/');
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 			if (scf_property_get_name(prop, buf, buf_sz) < 0)
2547c478bd9Sstevel@tonic-gate 				scfdie();
2557c478bd9Sstevel@tonic-gate 			(void) fputs(buf, stdout);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 			free(buf);
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 		(void) putchar(' ');
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 		if (scf_property_type(prop, &ty) == -1)
2637c478bd9Sstevel@tonic-gate 			scfdie();
2647c478bd9Sstevel@tonic-gate 		(void) fputs(scf_type_to_string(ty), stdout);
2657c478bd9Sstevel@tonic-gate 		(void) putchar(' ');
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	if ((iter = scf_iter_create(hndl)) == NULL ||
2697c478bd9Sstevel@tonic-gate 	    (val = scf_value_create(hndl)) == NULL)
2707c478bd9Sstevel@tonic-gate 		scfdie();
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	if (scf_iter_property_values(iter, prop) == -1)
2737c478bd9Sstevel@tonic-gate 		scfdie();
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	first = 1;
2767c478bd9Sstevel@tonic-gate 	while ((ret = scf_iter_next_value(iter, val)) == 1) {
2777c478bd9Sstevel@tonic-gate 		if (first)
2787c478bd9Sstevel@tonic-gate 			first = 0;
2797c478bd9Sstevel@tonic-gate 		else
2807c478bd9Sstevel@tonic-gate 			(void) putchar(' ');
2817c478bd9Sstevel@tonic-gate 		print_value(val);
2827c478bd9Sstevel@tonic-gate 	}
283*3eae19d9Swesolows 	if (ret == -1) {
284*3eae19d9Swesolows 		err = scf_error();
285*3eae19d9Swesolows 		if (err == SCF_ERROR_PERMISSION_DENIED) {
286*3eae19d9Swesolows 			if (uu_list_numnodes(prop_list) > 0)
287*3eae19d9Swesolows 				die(permission_denied_emsg);
288*3eae19d9Swesolows 		} else {
289*3eae19d9Swesolows 			scfdie();
290*3eae19d9Swesolows 		}
291*3eae19d9Swesolows 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
2967c478bd9Sstevel@tonic-gate 	(void) scf_value_destroy(val);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate  * display_prop() all of the properties in the given property group.  Force
3017c478bd9Sstevel@tonic-gate  * types to true so identification will be displayed.
3027c478bd9Sstevel@tonic-gate  */
3037c478bd9Sstevel@tonic-gate static void
3047c478bd9Sstevel@tonic-gate display_pg(scf_propertygroup_t *pg)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate 	scf_property_t *prop;
3077c478bd9Sstevel@tonic-gate 	scf_iter_t *iter;
3087c478bd9Sstevel@tonic-gate 	int ret;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	types = 1;	/* Always display types for whole propertygroups. */
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	if ((prop = scf_property_create(hndl)) == NULL ||
3137c478bd9Sstevel@tonic-gate 	    (iter = scf_iter_create(hndl)) == NULL)
3147c478bd9Sstevel@tonic-gate 		scfdie();
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	if (scf_iter_pg_properties(iter, pg) == -1)
3177c478bd9Sstevel@tonic-gate 		scfdie();
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	while ((ret = scf_iter_next_property(iter, prop)) == 1)
3207c478bd9Sstevel@tonic-gate 		display_prop(pg, prop);
3217c478bd9Sstevel@tonic-gate 	if (ret == -1)
3227c478bd9Sstevel@tonic-gate 		scfdie();
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
3257c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate /*
3297c478bd9Sstevel@tonic-gate  * Common code to execute when a nonexistant property is encountered.
3307c478bd9Sstevel@tonic-gate  */
3317c478bd9Sstevel@tonic-gate static void
3327c478bd9Sstevel@tonic-gate noprop_common_action()
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 	if (!PRINT_NOPROP_ERRORS)
3357c478bd9Sstevel@tonic-gate 		/* We're not printing errors, so we can cut out early. */
3367c478bd9Sstevel@tonic-gate 		exit(UU_EXIT_FATAL);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	return_code = UU_EXIT_FATAL;
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate /*
3427c478bd9Sstevel@tonic-gate  * Iterate the properties of a service or an instance when no snapshot
3437c478bd9Sstevel@tonic-gate  * is specified.
3447c478bd9Sstevel@tonic-gate  */
3457c478bd9Sstevel@tonic-gate static int
3467c478bd9Sstevel@tonic-gate scf_iter_entity_pgs(scf_iter_t *iter, scf_entityp_t ent)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	int ret = 0;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	if (ent.type) {
3517c478bd9Sstevel@tonic-gate 		/*
3527c478bd9Sstevel@tonic-gate 		 * If we are displaying properties for a service,
3537c478bd9Sstevel@tonic-gate 		 * treat it as though it were a composed, current
3547c478bd9Sstevel@tonic-gate 		 * lookup. (implicit cflag) However, if a snapshot
3557c478bd9Sstevel@tonic-gate 		 * was specified, fail.
3567c478bd9Sstevel@tonic-gate 		 */
3577c478bd9Sstevel@tonic-gate 		if (sflag)
3587c478bd9Sstevel@tonic-gate 			die(gettext("Only instances have "
3597c478bd9Sstevel@tonic-gate 			    "snapshots.\n"));
3607c478bd9Sstevel@tonic-gate 		ret = scf_iter_service_pgs(iter, ent.u.svc);
3617c478bd9Sstevel@tonic-gate 	} else {
3627c478bd9Sstevel@tonic-gate 		if (Cflag)
3637c478bd9Sstevel@tonic-gate 			ret = scf_iter_instance_pgs(iter, ent.u.inst);
3647c478bd9Sstevel@tonic-gate 		else
3657c478bd9Sstevel@tonic-gate 			ret = scf_iter_instance_pgs_composed(iter, ent.u.inst,
3667c478bd9Sstevel@tonic-gate 			    NULL);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 	return (ret);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate  * Return a snapshot for the supplied instance and snapshot name.
3737c478bd9Sstevel@tonic-gate  */
3747c478bd9Sstevel@tonic-gate static scf_snapshot_t *
3757c478bd9Sstevel@tonic-gate get_snapshot(const scf_instance_t *inst, const char *snapshot)
3767c478bd9Sstevel@tonic-gate {
3777c478bd9Sstevel@tonic-gate 	scf_snapshot_t *snap = scf_snapshot_create(hndl);
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (snap == NULL)
3807c478bd9Sstevel@tonic-gate 		scfdie();
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	if (scf_instance_get_snapshot(inst, snapshot, snap) == -1) {
3837c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
3847c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
3857c478bd9Sstevel@tonic-gate 			die(gettext("Invalid snapshot name.\n"));
3867c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
3897c478bd9Sstevel@tonic-gate 			if (sflag == 0) {
3907c478bd9Sstevel@tonic-gate 				scf_snapshot_destroy(snap);
3917c478bd9Sstevel@tonic-gate 				snap = NULL;
3927c478bd9Sstevel@tonic-gate 			} else
3937c478bd9Sstevel@tonic-gate 				die(gettext("No such snapshot.\n"));
3947c478bd9Sstevel@tonic-gate 			break;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 		default:
3977c478bd9Sstevel@tonic-gate 			scfdie();
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	return (snap);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate  * Entity (service or instance): If there are -p options,
4067c478bd9Sstevel@tonic-gate  * display_{pg,prop}() the named property groups and/or properties.  Otherwise
4077c478bd9Sstevel@tonic-gate  * display_pg() all property groups.
4087c478bd9Sstevel@tonic-gate  */
4097c478bd9Sstevel@tonic-gate static void
4107c478bd9Sstevel@tonic-gate process_ent(scf_entityp_t ent)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	scf_snapshot_t *snap = NULL;
4137c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *pg;
4147c478bd9Sstevel@tonic-gate 	scf_property_t *prop;
4157c478bd9Sstevel@tonic-gate 	scf_iter_t *iter;
4167c478bd9Sstevel@tonic-gate 	svcprop_prop_node_t *spn;
4177c478bd9Sstevel@tonic-gate 	int ret, err;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	if (uu_list_numnodes(prop_list) == 0) {
4207c478bd9Sstevel@tonic-gate 		if (quiet)
4217c478bd9Sstevel@tonic-gate 			return;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 		if ((pg = scf_pg_create(hndl)) == NULL ||
4247c478bd9Sstevel@tonic-gate 		    (iter = scf_iter_create(hndl)) == NULL)
4257c478bd9Sstevel@tonic-gate 			scfdie();
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 		if (cflag || Cflag || ent.type != ENT_INSTANCE) {
4287c478bd9Sstevel@tonic-gate 			if (scf_iter_entity_pgs(iter, ent) == -1)
4297c478bd9Sstevel@tonic-gate 				scfdie();
4307c478bd9Sstevel@tonic-gate 		} else {
4317c478bd9Sstevel@tonic-gate 			if (snapshot != NULL)
4327c478bd9Sstevel@tonic-gate 				snap = get_snapshot(ent.u.inst, snapshot);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			if (scf_iter_instance_pgs_composed(iter, ent.u.inst,
4357c478bd9Sstevel@tonic-gate 			    snap) == -1)
4367c478bd9Sstevel@tonic-gate 				scfdie();
4377c478bd9Sstevel@tonic-gate 			if (snap)
4387c478bd9Sstevel@tonic-gate 				scf_snapshot_destroy(snap);
4397c478bd9Sstevel@tonic-gate 		}
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 		while ((ret = scf_iter_next_pg(iter, pg)) == 1)
4427c478bd9Sstevel@tonic-gate 			display_pg(pg);
4437c478bd9Sstevel@tonic-gate 		if (ret == -1)
4447c478bd9Sstevel@tonic-gate 			scfdie();
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 		/*
4477c478bd9Sstevel@tonic-gate 		 * In normal usage, i.e. against the running snapshot,
4487c478bd9Sstevel@tonic-gate 		 * we must iterate over the current non-persistent
4497c478bd9Sstevel@tonic-gate 		 * pg's.
4507c478bd9Sstevel@tonic-gate 		 */
4517c478bd9Sstevel@tonic-gate 		if (sflag == 0 && snap != NULL) {
4527c478bd9Sstevel@tonic-gate 			scf_iter_reset(iter);
4537c478bd9Sstevel@tonic-gate 			if (scf_iter_instance_pgs_composed(iter, ent.u.inst,
4547c478bd9Sstevel@tonic-gate 			    NULL) == -1)
4557c478bd9Sstevel@tonic-gate 				scfdie();
4567c478bd9Sstevel@tonic-gate 			while ((ret = scf_iter_next_pg(iter, pg)) == 1) {
4577c478bd9Sstevel@tonic-gate 				uint32_t flags;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 				if (scf_pg_get_flags(pg, &flags) == -1)
4607c478bd9Sstevel@tonic-gate 					scfdie();
4617c478bd9Sstevel@tonic-gate 				if (flags & SCF_PG_FLAG_NONPERSISTENT)
4627c478bd9Sstevel@tonic-gate 					display_pg(pg);
4637c478bd9Sstevel@tonic-gate 			}
4647c478bd9Sstevel@tonic-gate 		}
4657c478bd9Sstevel@tonic-gate 		if (ret == -1)
4667c478bd9Sstevel@tonic-gate 			scfdie();
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		scf_iter_destroy(iter);
4697c478bd9Sstevel@tonic-gate 		scf_pg_destroy(pg);
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		return;
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	if ((pg = scf_pg_create(hndl)) == NULL ||
4757c478bd9Sstevel@tonic-gate 	    (prop = scf_property_create(hndl)) == NULL)
4767c478bd9Sstevel@tonic-gate 		scfdie();
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	if (ent.type == ENT_INSTANCE && snapshot != NULL)
4797c478bd9Sstevel@tonic-gate 		snap = get_snapshot(ent.u.inst, snapshot);
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	for (spn = uu_list_first(prop_list);
4827c478bd9Sstevel@tonic-gate 	    spn != NULL;
4837c478bd9Sstevel@tonic-gate 	    spn = uu_list_next(prop_list, spn)) {
4847c478bd9Sstevel@tonic-gate 		if (ent.type == ENT_INSTANCE) {
4857c478bd9Sstevel@tonic-gate 			if (Cflag)
4867c478bd9Sstevel@tonic-gate 				ret = scf_instance_get_pg(ent.u.inst,
4877c478bd9Sstevel@tonic-gate 				    spn->spn_comp1, pg);
4887c478bd9Sstevel@tonic-gate 			else
4897c478bd9Sstevel@tonic-gate 				ret = scf_instance_get_pg_composed(ent.u.inst,
4907c478bd9Sstevel@tonic-gate 				    snap, spn->spn_comp1, pg);
4917c478bd9Sstevel@tonic-gate 			err = scf_error();
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 			/*
4947c478bd9Sstevel@tonic-gate 			 * If we didn't find it in the specified snapshot, use
4957c478bd9Sstevel@tonic-gate 			 * the current values if the pg is nonpersistent.
4967c478bd9Sstevel@tonic-gate 			 */
4977c478bd9Sstevel@tonic-gate 			if (ret == -1 && !Cflag &&snap != NULL && err ==
4987c478bd9Sstevel@tonic-gate 			    SCF_ERROR_NOT_FOUND) {
4997c478bd9Sstevel@tonic-gate 				ret = scf_instance_get_pg_composed(
5007c478bd9Sstevel@tonic-gate 				    ent.u.inst, NULL, spn->spn_comp1,
5017c478bd9Sstevel@tonic-gate 				    pg);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 				if (ret == 0) {
5047c478bd9Sstevel@tonic-gate 					uint32_t flags;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 					if (scf_pg_get_flags(pg, &flags) == -1)
5077c478bd9Sstevel@tonic-gate 						scfdie();
5087c478bd9Sstevel@tonic-gate 					if ((flags & SCF_PG_FLAG_NONPERSISTENT)
5097c478bd9Sstevel@tonic-gate 					    == 0) {
5107c478bd9Sstevel@tonic-gate 						ret = -1;
5117c478bd9Sstevel@tonic-gate 					}
5127c478bd9Sstevel@tonic-gate 				}
5137c478bd9Sstevel@tonic-gate 			}
5147c478bd9Sstevel@tonic-gate 		} else {
5157c478bd9Sstevel@tonic-gate 			/*
5167c478bd9Sstevel@tonic-gate 			 * If we are displaying properties for a service,
5177c478bd9Sstevel@tonic-gate 			 * treat it as though it were a composed, current
5187c478bd9Sstevel@tonic-gate 			 * lookup. (implicit cflag) However, if a snapshot
5197c478bd9Sstevel@tonic-gate 			 * was specified, fail.
5207c478bd9Sstevel@tonic-gate 			 */
5217c478bd9Sstevel@tonic-gate 			if (sflag)
5227c478bd9Sstevel@tonic-gate 				die(gettext("Only instances have "
5237c478bd9Sstevel@tonic-gate 				    "snapshots.\n"));
5247c478bd9Sstevel@tonic-gate 			ret = scf_entity_get_pg(ent, spn->spn_comp1, pg);
5257c478bd9Sstevel@tonic-gate 			err = scf_error();
5267c478bd9Sstevel@tonic-gate 		}
5277c478bd9Sstevel@tonic-gate 		if (ret == -1) {
5287c478bd9Sstevel@tonic-gate 			if (err != SCF_ERROR_NOT_FOUND)
5297c478bd9Sstevel@tonic-gate 				scfdie();
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 			if (PRINT_NOPROP_ERRORS) {
5327c478bd9Sstevel@tonic-gate 				char *buf;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 				buf = safe_malloc(max_scf_fmri_length + 1);
5357c478bd9Sstevel@tonic-gate 				if (scf_entity_to_fmri(ent, buf,
5367c478bd9Sstevel@tonic-gate 				    max_scf_fmri_length + 1) == -1)
5377c478bd9Sstevel@tonic-gate 					scfdie();
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 				uu_warn(gettext("Couldn't find property group "
5407c478bd9Sstevel@tonic-gate 				    "`%s' for %s `%s'.\n"), spn->spn_comp1,
5417c478bd9Sstevel@tonic-gate 				    SCF_ENTITY_TYPE_NAME(ent), buf);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 				free(buf);
5447c478bd9Sstevel@tonic-gate 			}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 			noprop_common_action();
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 			continue;
5497c478bd9Sstevel@tonic-gate 		}
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 		if (spn->spn_comp2 == NULL) {
5527c478bd9Sstevel@tonic-gate 			if (!quiet)
5537c478bd9Sstevel@tonic-gate 				display_pg(pg);
5547c478bd9Sstevel@tonic-gate 			continue;
5557c478bd9Sstevel@tonic-gate 		}
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 		if (scf_pg_get_property(pg, spn->spn_comp2, prop) == -1) {
5587c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_NOT_FOUND)
5597c478bd9Sstevel@tonic-gate 				scfdie();
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 			if (PRINT_NOPROP_ERRORS) {
5627c478bd9Sstevel@tonic-gate 				char *buf;
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 				buf = safe_malloc(max_scf_fmri_length + 1);
5657c478bd9Sstevel@tonic-gate 				if (scf_entity_to_fmri(ent, buf,
5667c478bd9Sstevel@tonic-gate 				    max_scf_fmri_length + 1) == -1)
5677c478bd9Sstevel@tonic-gate 					scfdie();
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 				/* FMRI syntax knowledge */
5707c478bd9Sstevel@tonic-gate 				uu_warn(gettext("Couldn't find property "
5717c478bd9Sstevel@tonic-gate 				    "`%s/%s' for %s `%s'.\n"), spn->spn_comp1,
5727c478bd9Sstevel@tonic-gate 				    spn->spn_comp2, SCF_ENTITY_TYPE_NAME(ent),
5737c478bd9Sstevel@tonic-gate 				    buf);
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 				free(buf);
5767c478bd9Sstevel@tonic-gate 			}
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 			noprop_common_action();
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 			continue;
5817c478bd9Sstevel@tonic-gate 		}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 		if (!quiet)
5847c478bd9Sstevel@tonic-gate 			display_prop(pg, prop);
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
5887c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
5897c478bd9Sstevel@tonic-gate 	if (snap)
5907c478bd9Sstevel@tonic-gate 		scf_snapshot_destroy(snap);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate /*
5947c478bd9Sstevel@tonic-gate  * Without -p options, just call display_pg().  Otherwise display_prop() the
5957c478bd9Sstevel@tonic-gate  * named properties of the property group.
5967c478bd9Sstevel@tonic-gate  */
5977c478bd9Sstevel@tonic-gate static void
5987c478bd9Sstevel@tonic-gate process_pg(scf_propertygroup_t *pg)
5997c478bd9Sstevel@tonic-gate {
6007c478bd9Sstevel@tonic-gate 	scf_property_t *prop;
6017c478bd9Sstevel@tonic-gate 	svcprop_prop_node_t *spn;
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	if (uu_list_first(prop_list) == NULL) {
6047c478bd9Sstevel@tonic-gate 		if (quiet)
6057c478bd9Sstevel@tonic-gate 			return;
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 		display_pg(pg);
6087c478bd9Sstevel@tonic-gate 		return;
6097c478bd9Sstevel@tonic-gate 	}
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	prop = scf_property_create(hndl);
6127c478bd9Sstevel@tonic-gate 	if (prop == NULL)
6137c478bd9Sstevel@tonic-gate 		scfdie();
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	for (spn = uu_list_first(prop_list);
6167c478bd9Sstevel@tonic-gate 	    spn != NULL;
6177c478bd9Sstevel@tonic-gate 	    spn = uu_list_next(prop_list, spn)) {
6187c478bd9Sstevel@tonic-gate 		if (spn->spn_comp2 != NULL) {
6197c478bd9Sstevel@tonic-gate 			char *buf;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 			buf = safe_malloc(max_scf_fmri_length + 1);
6227c478bd9Sstevel@tonic-gate 			if (scf_pg_to_fmri(pg, buf, max_scf_fmri_length + 1) ==
6237c478bd9Sstevel@tonic-gate 			    -1)
6247c478bd9Sstevel@tonic-gate 				scfdie();
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 			uu_xdie(UU_EXIT_USAGE, gettext("-p argument `%s/%s' "
6277c478bd9Sstevel@tonic-gate 			    "has too many components for property "
6287c478bd9Sstevel@tonic-gate 			    "group `%s'.\n"), spn->spn_comp1, spn->spn_comp2,
6297c478bd9Sstevel@tonic-gate 			    buf);
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 			free(buf);
6327c478bd9Sstevel@tonic-gate 		}
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 		if (scf_pg_get_property(pg, spn->spn_comp1, prop) == 0) {
6357c478bd9Sstevel@tonic-gate 			if (!quiet)
6367c478bd9Sstevel@tonic-gate 				display_prop(pg, prop);
6377c478bd9Sstevel@tonic-gate 			continue;
6387c478bd9Sstevel@tonic-gate 		}
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
6417c478bd9Sstevel@tonic-gate 			scfdie();
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 		if (PRINT_NOPROP_ERRORS) {
6447c478bd9Sstevel@tonic-gate 			char *buf;
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 			buf = safe_malloc(max_scf_fmri_length + 1);
6477c478bd9Sstevel@tonic-gate 			if (scf_pg_to_fmri(pg, buf, max_scf_fmri_length + 1) ==
6487c478bd9Sstevel@tonic-gate 			    -1)
6497c478bd9Sstevel@tonic-gate 				scfdie();
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 			uu_warn(gettext("Couldn't find property `%s' in "
6527c478bd9Sstevel@tonic-gate 			    "property group `%s'.\n"), spn->spn_comp1, buf);
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 			free(buf);
6557c478bd9Sstevel@tonic-gate 		}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 		noprop_common_action();
6587c478bd9Sstevel@tonic-gate 	}
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate /*
6627c478bd9Sstevel@tonic-gate  * If there are -p options, show the error.  Otherwise just call
6637c478bd9Sstevel@tonic-gate  * display_prop().
6647c478bd9Sstevel@tonic-gate  */
6657c478bd9Sstevel@tonic-gate static void
6667c478bd9Sstevel@tonic-gate process_prop(scf_propertygroup_t *pg, scf_property_t *prop)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	if (uu_list_first(prop_list) != NULL) {
6697c478bd9Sstevel@tonic-gate 		uu_warn(gettext("The -p option cannot be used with property "
6707c478bd9Sstevel@tonic-gate 		    "operands.\n"));
6717c478bd9Sstevel@tonic-gate 		usage();
6727c478bd9Sstevel@tonic-gate 	}
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	if (quiet)
6757c478bd9Sstevel@tonic-gate 		return;
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	display_prop(pg, prop);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /* Decode an operand & dispatch. */
6817c478bd9Sstevel@tonic-gate /* ARGSUSED */
6827c478bd9Sstevel@tonic-gate static int
6837c478bd9Sstevel@tonic-gate process_fmri(void *unused, scf_walkinfo_t *wip)
6847c478bd9Sstevel@tonic-gate {
6857c478bd9Sstevel@tonic-gate 	scf_entityp_t ent;
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 	/* Multiple matches imply multiple entities. */
6887c478bd9Sstevel@tonic-gate 	if (wip->count > 1)
6897c478bd9Sstevel@tonic-gate 		types = fmris = 1;
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	if (wip->prop != NULL) {
6927c478bd9Sstevel@tonic-gate 		process_prop(wip->pg, wip->prop);
6937c478bd9Sstevel@tonic-gate 	} else if (wip->pg != NULL) {
6947c478bd9Sstevel@tonic-gate 		process_pg(wip->pg);
6957c478bd9Sstevel@tonic-gate 	} else if (wip->inst != NULL) {
6967c478bd9Sstevel@tonic-gate 		SCF_ENTITY_SET_TO_INSTANCE(ent, wip->inst);
6977c478bd9Sstevel@tonic-gate 		process_ent(ent);
6987c478bd9Sstevel@tonic-gate 	} else {
6997c478bd9Sstevel@tonic-gate 		/* scf_walk_fmri() won't let this happen */
7007c478bd9Sstevel@tonic-gate 		assert(wip->svc != NULL);
7017c478bd9Sstevel@tonic-gate 		SCF_ENTITY_SET_TO_SERVICE(ent, wip->svc);
7027c478bd9Sstevel@tonic-gate 		process_ent(ent);
7037c478bd9Sstevel@tonic-gate 	}
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	return (0);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate static void
7097c478bd9Sstevel@tonic-gate add_prop(char *property)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate 	svcprop_prop_node_t *p, *last;
7127c478bd9Sstevel@tonic-gate 	char *slash;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	const char * const invalid_component_emsg =
7157c478bd9Sstevel@tonic-gate 	    gettext("Invalid component name `%s'.\n");
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	/* FMRI syntax knowledge. */
7187c478bd9Sstevel@tonic-gate 	slash = strchr(property, '/');
7197c478bd9Sstevel@tonic-gate 	if (slash != NULL) {
7207c478bd9Sstevel@tonic-gate 		if (strchr(slash + 1, '/') != NULL) {
7217c478bd9Sstevel@tonic-gate 			uu_warn(gettext("-p argument `%s' has too many "
7227c478bd9Sstevel@tonic-gate 			    "components.\n"), property);
7237c478bd9Sstevel@tonic-gate 			usage();
7247c478bd9Sstevel@tonic-gate 		}
7257c478bd9Sstevel@tonic-gate 	}
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	if (slash != NULL)
7287c478bd9Sstevel@tonic-gate 		*slash = '\0';
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	p = safe_malloc(sizeof (svcprop_prop_node_t));
7317c478bd9Sstevel@tonic-gate 	uu_list_node_init(p, &p->spn_list_node, prop_pool);
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	p->spn_comp1 = property;
7347c478bd9Sstevel@tonic-gate 	p->spn_comp2 = (slash == NULL) ? NULL : slash + 1;
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	if (uu_check_name(p->spn_comp1, UU_NAME_DOMAIN) == -1)
7377c478bd9Sstevel@tonic-gate 		uu_xdie(UU_EXIT_USAGE, invalid_component_emsg, p->spn_comp1);
7387c478bd9Sstevel@tonic-gate 	if (p->spn_comp2 != NULL &&
7397c478bd9Sstevel@tonic-gate 	    uu_check_name(p->spn_comp2, UU_NAME_DOMAIN) == -1)
7407c478bd9Sstevel@tonic-gate 		uu_xdie(UU_EXIT_USAGE, invalid_component_emsg, p->spn_comp2);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	last = uu_list_last(prop_list);
7437c478bd9Sstevel@tonic-gate 	if (last != NULL) {
7447c478bd9Sstevel@tonic-gate 		if ((last->spn_comp2 == NULL) ^ (p->spn_comp2 == NULL)) {
7457c478bd9Sstevel@tonic-gate 			/*
7467c478bd9Sstevel@tonic-gate 			 * The -p options have mixed numbers of components.
7477c478bd9Sstevel@tonic-gate 			 * If they both turn out to be valid, then the
7487c478bd9Sstevel@tonic-gate 			 * single-component ones will specify property groups,
7497c478bd9Sstevel@tonic-gate 			 * so we need to turn on types to keep the output of
7507c478bd9Sstevel@tonic-gate 			 * display_prop() consistent with display_pg().
7517c478bd9Sstevel@tonic-gate 			 */
7527c478bd9Sstevel@tonic-gate 			types = 1;
7537c478bd9Sstevel@tonic-gate 		}
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	(void) uu_list_insert_after(prop_list, NULL, p);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate /*
7617c478bd9Sstevel@tonic-gate  * Wait for a property group or property change.
7627c478bd9Sstevel@tonic-gate  *
7637c478bd9Sstevel@tonic-gate  * Extract a pg and optionally a property name from fmri & prop_list.
7647c478bd9Sstevel@tonic-gate  * _scf_pg_wait() for the pg, and display_pg(pg) or display_prop(pg, prop)
7657c478bd9Sstevel@tonic-gate  * when it returns.
7667c478bd9Sstevel@tonic-gate  */
7677c478bd9Sstevel@tonic-gate /* ARGSUSED */
7687c478bd9Sstevel@tonic-gate static int
7697c478bd9Sstevel@tonic-gate do_wait(void *unused, scf_walkinfo_t *wip)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	scf_property_t *prop;
7727c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *lpg, *pg;
7737c478bd9Sstevel@tonic-gate 	const char *propname;
7747c478bd9Sstevel@tonic-gate 	svcprop_prop_node_t *p;
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	const char *emsg_not_found = gettext("Not found.\n");
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	if ((lpg = scf_pg_create(hndl)) == NULL ||
7797c478bd9Sstevel@tonic-gate 	    (prop = scf_property_create(hndl)) == NULL)
7807c478bd9Sstevel@tonic-gate 		scfdie();
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	if (wip->prop != NULL) {
7837c478bd9Sstevel@tonic-gate 		if (uu_list_numnodes(prop_list) > 0)
7847c478bd9Sstevel@tonic-gate 			uu_xdie(UU_EXIT_USAGE, gettext("-p cannot be used with "
7857c478bd9Sstevel@tonic-gate 			    "property FMRIs.\n"));
7867c478bd9Sstevel@tonic-gate 		pg = wip->pg;
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 		assert(strrchr(wip->fmri, '/') != NULL);
7897c478bd9Sstevel@tonic-gate 		propname = strrchr(wip->fmri, '/') + 1;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	} else if (wip->pg != NULL) {
7927c478bd9Sstevel@tonic-gate 		p = uu_list_first(prop_list);
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 		if (p != NULL) {
7957c478bd9Sstevel@tonic-gate 			if (p->spn_comp2 != NULL)
7967c478bd9Sstevel@tonic-gate 				uu_xdie(UU_EXIT_USAGE, gettext("-p argument "
7977c478bd9Sstevel@tonic-gate 				    "\"%s/%s\" has too many components for "
7987c478bd9Sstevel@tonic-gate 				    "property group %s.\n"),
7997c478bd9Sstevel@tonic-gate 				    p->spn_comp1, p->spn_comp2, wip->fmri);
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 			propname = p->spn_comp1;
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 			if (scf_pg_get_property(wip->pg, propname, prop) !=
8047c478bd9Sstevel@tonic-gate 			    SCF_SUCCESS) {
8057c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
8067c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
8077c478bd9Sstevel@tonic-gate 					uu_xdie(UU_EXIT_USAGE,
8087c478bd9Sstevel@tonic-gate 					    gettext("Invalid property name "
8097c478bd9Sstevel@tonic-gate 					    "\"%s\".\n"), propname);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_FOUND:
8147c478bd9Sstevel@tonic-gate 					die(emsg_not_found);
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 				default:
8197c478bd9Sstevel@tonic-gate 					scfdie();
8207c478bd9Sstevel@tonic-gate 				}
8217c478bd9Sstevel@tonic-gate 			}
8227c478bd9Sstevel@tonic-gate 		} else {
8237c478bd9Sstevel@tonic-gate 			propname = NULL;
8247c478bd9Sstevel@tonic-gate 		}
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 		pg = wip->pg;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	} else if (wip->inst != NULL) {
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 		p = uu_list_first(prop_list);
8317c478bd9Sstevel@tonic-gate 		if (p == NULL)
8327c478bd9Sstevel@tonic-gate 			uu_xdie(UU_EXIT_USAGE,
8337c478bd9Sstevel@tonic-gate 			    gettext("Cannot wait for an instance.\n"));
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 		if (scf_instance_get_pg(wip->inst, p->spn_comp1, lpg) !=
8367c478bd9Sstevel@tonic-gate 		    SCF_SUCCESS) {
8377c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
8387c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
8397c478bd9Sstevel@tonic-gate 				uu_xdie(UU_EXIT_USAGE, gettext("Invalid "
8407c478bd9Sstevel@tonic-gate 				    "property group name \"%s\".\n"),
8417c478bd9Sstevel@tonic-gate 				    p->spn_comp1);
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
8447c478bd9Sstevel@tonic-gate 				die(emsg_not_found);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 				/* NOTREACHED */
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 			default:
8497c478bd9Sstevel@tonic-gate 				scfdie();
8507c478bd9Sstevel@tonic-gate 			}
8517c478bd9Sstevel@tonic-gate 		}
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 		propname = p->spn_comp2;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 		if (propname != NULL) {
8567c478bd9Sstevel@tonic-gate 			if (scf_pg_get_property(lpg, propname, prop) !=
8577c478bd9Sstevel@tonic-gate 			    SCF_SUCCESS) {
8587c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
8597c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
8607c478bd9Sstevel@tonic-gate 					uu_xdie(UU_EXIT_USAGE,
8617c478bd9Sstevel@tonic-gate 					    gettext("Invalid property name "
8627c478bd9Sstevel@tonic-gate 					    "\"%s\".\n"), propname);
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_FOUND:
8657c478bd9Sstevel@tonic-gate 					die(emsg_not_found);
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 				default:
8707c478bd9Sstevel@tonic-gate 					scfdie();
8717c478bd9Sstevel@tonic-gate 				}
8727c478bd9Sstevel@tonic-gate 			}
8737c478bd9Sstevel@tonic-gate 		}
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 		pg = lpg;
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	} else if (wip->svc != NULL) {
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 		p = uu_list_first(prop_list);
8807c478bd9Sstevel@tonic-gate 		if (p == NULL)
8817c478bd9Sstevel@tonic-gate 			uu_xdie(UU_EXIT_USAGE,
8827c478bd9Sstevel@tonic-gate 			    gettext("Cannot wait for a service.\n"));
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 		if (scf_service_get_pg(wip->svc, p->spn_comp1, lpg) !=
8857c478bd9Sstevel@tonic-gate 		    SCF_SUCCESS) {
8867c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
8877c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
8887c478bd9Sstevel@tonic-gate 				uu_xdie(UU_EXIT_USAGE, gettext("Invalid "
8897c478bd9Sstevel@tonic-gate 				    "property group name \"%s\".\n"),
8907c478bd9Sstevel@tonic-gate 				    p->spn_comp1);
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
8937c478bd9Sstevel@tonic-gate 				die(emsg_not_found);
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 			default:
8967c478bd9Sstevel@tonic-gate 				scfdie();
8977c478bd9Sstevel@tonic-gate 			}
8987c478bd9Sstevel@tonic-gate 		}
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 		propname = p->spn_comp2;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 		if (propname != NULL) {
9037c478bd9Sstevel@tonic-gate 			if (scf_pg_get_property(lpg, propname, prop) !=
9047c478bd9Sstevel@tonic-gate 			    SCF_SUCCESS) {
9057c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
9067c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
9077c478bd9Sstevel@tonic-gate 					uu_xdie(UU_EXIT_USAGE,
9087c478bd9Sstevel@tonic-gate 					    gettext("Invalid property name "
9097c478bd9Sstevel@tonic-gate 					    "\"%s\".\n"), propname);
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_FOUND:
9147c478bd9Sstevel@tonic-gate 					die(emsg_not_found);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 				default:
9197c478bd9Sstevel@tonic-gate 					scfdie();
9207c478bd9Sstevel@tonic-gate 				}
9217c478bd9Sstevel@tonic-gate 			}
9227c478bd9Sstevel@tonic-gate 		}
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 		pg = lpg;
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	} else {
9277c478bd9Sstevel@tonic-gate 		uu_xdie(UU_EXIT_USAGE, gettext("FMRI must specify an entity, "
9287c478bd9Sstevel@tonic-gate 		    "property group, or property.\n"));
9297c478bd9Sstevel@tonic-gate 	}
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	for (;;) {
9327c478bd9Sstevel@tonic-gate 		int ret;
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		ret = _scf_pg_wait(pg, -1);
9357c478bd9Sstevel@tonic-gate 		if (ret != SCF_SUCCESS)
9367c478bd9Sstevel@tonic-gate 			scfdie();
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 		ret = scf_pg_update(pg);
9397c478bd9Sstevel@tonic-gate 		if (ret < 0) {
9407c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_DELETED)
9417c478bd9Sstevel@tonic-gate 				scfdie();
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 			die(emsg_not_found);
9447c478bd9Sstevel@tonic-gate 		}
9457c478bd9Sstevel@tonic-gate 		if (ret == SCF_COMPLETE)
9467c478bd9Sstevel@tonic-gate 			break;
9477c478bd9Sstevel@tonic-gate 	}
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	if (propname != NULL) {
9507c478bd9Sstevel@tonic-gate 		if (scf_pg_get_property(pg, propname, prop) == SCF_SUCCESS) {
9517c478bd9Sstevel@tonic-gate 			if (!quiet)
9527c478bd9Sstevel@tonic-gate 				display_prop(pg, prop);
9537c478bd9Sstevel@tonic-gate 		} else {
9547c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_NOT_FOUND)
9557c478bd9Sstevel@tonic-gate 				scfdie();
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 			if (PRINT_NOPROP_ERRORS)
9587c478bd9Sstevel@tonic-gate 				uu_warn(emsg_not_found);
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 			return_code = UU_EXIT_FATAL;
9617c478bd9Sstevel@tonic-gate 		}
9627c478bd9Sstevel@tonic-gate 	} else {
9637c478bd9Sstevel@tonic-gate 		if (!quiet)
9647c478bd9Sstevel@tonic-gate 			display_pg(pg);
9657c478bd9Sstevel@tonic-gate 	}
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
9687c478bd9Sstevel@tonic-gate 	scf_pg_destroy(lpg);
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate 	return (0);
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate /*
9747c478bd9Sstevel@tonic-gate  * These functions replace uu_warn() and uu_die() when the quiet (-q) option is
9757c478bd9Sstevel@tonic-gate  * used, and silently ignore any output.
9767c478bd9Sstevel@tonic-gate  */
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9797c478bd9Sstevel@tonic-gate static void
9807c478bd9Sstevel@tonic-gate quiet_warn(const char *fmt, ...)
9817c478bd9Sstevel@tonic-gate {
9827c478bd9Sstevel@tonic-gate 	/* Do nothing */
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9867c478bd9Sstevel@tonic-gate static void
9877c478bd9Sstevel@tonic-gate quiet_die(const char *fmt, ...)
9887c478bd9Sstevel@tonic-gate {
9897c478bd9Sstevel@tonic-gate 	exit(UU_EXIT_FATAL);
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate int
9937c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
9947c478bd9Sstevel@tonic-gate {
9957c478bd9Sstevel@tonic-gate 	int c;
9967c478bd9Sstevel@tonic-gate 	scf_walk_callback callback;
9977c478bd9Sstevel@tonic-gate 	int flags;
9987c478bd9Sstevel@tonic-gate 	int err;
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
10017c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	return_code = UU_EXIT_OK;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	(void) uu_setpname(argv[0]);
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	prop_pool = uu_list_pool_create("properties",
10087c478bd9Sstevel@tonic-gate 	    sizeof (svcprop_prop_node_t),
10097c478bd9Sstevel@tonic-gate 	    offsetof(svcprop_prop_node_t, spn_list_node), NULL, 0);
10107c478bd9Sstevel@tonic-gate 	if (prop_pool == NULL)
10117c478bd9Sstevel@tonic-gate 		uu_die("%s\n", uu_strerror(uu_error()));
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	prop_list = uu_list_create(prop_pool, NULL, 0);
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "Ccfp:qs:tvw")) != -1) {
10167c478bd9Sstevel@tonic-gate 		switch (c) {
10177c478bd9Sstevel@tonic-gate 		case 'C':
10187c478bd9Sstevel@tonic-gate 			if (cflag || sflag || wait)
10197c478bd9Sstevel@tonic-gate 				usage();	/* Not with -c, -s or -w */
10207c478bd9Sstevel@tonic-gate 			Cflag++;
10217c478bd9Sstevel@tonic-gate 			snapshot = NULL;
10227c478bd9Sstevel@tonic-gate 			break;
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 		case 'c':
10257c478bd9Sstevel@tonic-gate 			if (Cflag || sflag || wait)
10267c478bd9Sstevel@tonic-gate 				usage();	/* Not with -C, -s or -w */
10277c478bd9Sstevel@tonic-gate 			cflag++;
10287c478bd9Sstevel@tonic-gate 			snapshot = NULL;
10297c478bd9Sstevel@tonic-gate 			break;
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 		case 'f':
10327c478bd9Sstevel@tonic-gate 			types = 1;
10337c478bd9Sstevel@tonic-gate 			fmris = 1;
10347c478bd9Sstevel@tonic-gate 			break;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 		case 'p':
10377c478bd9Sstevel@tonic-gate 			add_prop(optarg);
10387c478bd9Sstevel@tonic-gate 			break;
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 		case 'q':
10417c478bd9Sstevel@tonic-gate 			quiet = 1;
10427c478bd9Sstevel@tonic-gate 			warn = quiet_warn;
10437c478bd9Sstevel@tonic-gate 			die = quiet_die;
10447c478bd9Sstevel@tonic-gate 			break;
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 		case 's':
10477c478bd9Sstevel@tonic-gate 			if (Cflag || cflag || wait)
10487c478bd9Sstevel@tonic-gate 				usage();	/* Not with -C, -c or -w */
10497c478bd9Sstevel@tonic-gate 			snapshot = optarg;
10507c478bd9Sstevel@tonic-gate 			sflag++;
10517c478bd9Sstevel@tonic-gate 			break;
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate 		case 't':
10547c478bd9Sstevel@tonic-gate 			types = 1;
10557c478bd9Sstevel@tonic-gate 			break;
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 		case 'v':
10587c478bd9Sstevel@tonic-gate 			verbose = 1;
10597c478bd9Sstevel@tonic-gate 			break;
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 		case 'w':
10627c478bd9Sstevel@tonic-gate 			if (Cflag || cflag || sflag)
10637c478bd9Sstevel@tonic-gate 				usage();	/* Not with -C, -c or -s */
10647c478bd9Sstevel@tonic-gate 			wait = 1;
10657c478bd9Sstevel@tonic-gate 			break;
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 		case '?':
10687c478bd9Sstevel@tonic-gate 			switch (optopt) {
10697c478bd9Sstevel@tonic-gate 			case 'p':
10707c478bd9Sstevel@tonic-gate 				usage();
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 			default:
10737c478bd9Sstevel@tonic-gate 				break;
10747c478bd9Sstevel@tonic-gate 			}
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 		default:
10797c478bd9Sstevel@tonic-gate 			usage();
10807c478bd9Sstevel@tonic-gate 		}
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	if (optind == argc)
10847c478bd9Sstevel@tonic-gate 		usage();
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	max_scf_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
10877c478bd9Sstevel@tonic-gate 	max_scf_value_length = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
10887c478bd9Sstevel@tonic-gate 	max_scf_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
10897c478bd9Sstevel@tonic-gate 	if (max_scf_name_length == -1 || max_scf_value_length == -1 ||
10907c478bd9Sstevel@tonic-gate 	    max_scf_fmri_length == -1)
10917c478bd9Sstevel@tonic-gate 		scfdie();
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	hndl = scf_handle_create(SCF_VERSION);
10947c478bd9Sstevel@tonic-gate 	if (hndl == NULL)
10957c478bd9Sstevel@tonic-gate 		scfdie();
10967c478bd9Sstevel@tonic-gate 	if (scf_handle_bind(hndl) == -1)
10977c478bd9Sstevel@tonic-gate 		die(gettext("Could not connect to configuration repository: "
10987c478bd9Sstevel@tonic-gate 		    "%s.\n"), scf_strerror(scf_error()));
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	flags = SCF_WALK_PROPERTY | SCF_WALK_SERVICE | SCF_WALK_EXPLICIT;
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	if (wait) {
11037c478bd9Sstevel@tonic-gate 		if (uu_list_numnodes(prop_list) > 1)
11047c478bd9Sstevel@tonic-gate 			usage();
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 		if (argc - optind > 1)
11077c478bd9Sstevel@tonic-gate 			usage();
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 		callback = do_wait;
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	} else {
11127c478bd9Sstevel@tonic-gate 		callback = process_fmri;
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 		flags |= SCF_WALK_MULTIPLE;
11157c478bd9Sstevel@tonic-gate 	}
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 	if ((err = scf_walk_fmri(hndl, argc - optind, argv + optind, flags,
11187c478bd9Sstevel@tonic-gate 	    callback, NULL, &return_code, warn)) != 0) {
11197c478bd9Sstevel@tonic-gate 		warn(gettext("failed to iterate over instances: %s\n"),
11207c478bd9Sstevel@tonic-gate 		    scf_strerror(err));
11217c478bd9Sstevel@tonic-gate 		return_code = UU_EXIT_FATAL;
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	scf_handle_destroy(hndl);
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 	return (return_code);
11277c478bd9Sstevel@tonic-gate }
1128