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*5040Swesolows * Common Development and Distribution License (the "License").
6*5040Swesolows * 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 */
21*5040Swesolows
220Sstevel@tonic-gate /*
23*5040Swesolows * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * svcprop - report service configuration properties
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <locale.h>
340Sstevel@tonic-gate #include <libintl.h>
350Sstevel@tonic-gate #include <libscf.h>
360Sstevel@tonic-gate #include <libscf_priv.h>
370Sstevel@tonic-gate #include <libuutil.h>
380Sstevel@tonic-gate #include <stddef.h>
390Sstevel@tonic-gate #include <stdio.h>
400Sstevel@tonic-gate #include <stdlib.h>
410Sstevel@tonic-gate #include <unistd.h>
420Sstevel@tonic-gate #include <strings.h>
430Sstevel@tonic-gate #include <assert.h>
440Sstevel@tonic-gate
450Sstevel@tonic-gate #ifndef TEXT_DOMAIN
460Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD"
470Sstevel@tonic-gate #endif /* TEXT_DOMAIN */
480Sstevel@tonic-gate
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate * Error functions. These can change if the quiet (-q) option is used.
510Sstevel@tonic-gate */
520Sstevel@tonic-gate static void (*warn)(const char *, ...) = uu_warn;
530Sstevel@tonic-gate static void (*die)(const char *, ...) = uu_die;
540Sstevel@tonic-gate
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * Entity encapsulation. This allows me to treat services and instances
570Sstevel@tonic-gate * similarly, and avoid duplicating process_ent().
580Sstevel@tonic-gate */
590Sstevel@tonic-gate typedef struct {
600Sstevel@tonic-gate char type; /* !=0: service, 0: instance */
610Sstevel@tonic-gate union {
620Sstevel@tonic-gate scf_service_t *svc;
630Sstevel@tonic-gate scf_instance_t *inst;
640Sstevel@tonic-gate } u;
650Sstevel@tonic-gate } scf_entityp_t;
660Sstevel@tonic-gate
670Sstevel@tonic-gate #define ENT_INSTANCE 0
680Sstevel@tonic-gate
690Sstevel@tonic-gate #define SCF_ENTITY_SET_TO_SERVICE(ent, s) { ent.type = 1; ent.u.svc = s; }
700Sstevel@tonic-gate
710Sstevel@tonic-gate #define SCF_ENTITY_SET_TO_INSTANCE(ent, i) \
720Sstevel@tonic-gate { ent.type = ENT_INSTANCE; ent.u.inst = i; }
730Sstevel@tonic-gate
740Sstevel@tonic-gate #define scf_entity_get_pg(ent, name, pg) \
750Sstevel@tonic-gate (ent.type ? scf_service_get_pg(ent.u.svc, name, pg) : \
760Sstevel@tonic-gate scf_instance_get_pg(ent.u.inst, name, pg))
770Sstevel@tonic-gate
780Sstevel@tonic-gate #define scf_entity_to_fmri(ent, buf, buf_sz) \
790Sstevel@tonic-gate (ent.type ? scf_service_to_fmri(ent.u.svc, buf, buf_sz) : \
800Sstevel@tonic-gate scf_instance_to_fmri(ent.u.inst, buf, buf_sz))
810Sstevel@tonic-gate
820Sstevel@tonic-gate #define SCF_ENTITY_TYPE_NAME(ent) (ent.type ? "service" : "instance")
830Sstevel@tonic-gate
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate * Data structure for -p arguments. Since they may be name or name/name, we
860Sstevel@tonic-gate * just track the components.
870Sstevel@tonic-gate */
880Sstevel@tonic-gate typedef struct svcprop_prop_node {
890Sstevel@tonic-gate uu_list_node_t spn_list_node;
900Sstevel@tonic-gate const char *spn_comp1;
910Sstevel@tonic-gate const char *spn_comp2;
920Sstevel@tonic-gate } svcprop_prop_node_t;
930Sstevel@tonic-gate
940Sstevel@tonic-gate static uu_list_pool_t *prop_pool;
950Sstevel@tonic-gate static uu_list_t *prop_list;
960Sstevel@tonic-gate
970Sstevel@tonic-gate static scf_handle_t *hndl;
980Sstevel@tonic-gate static ssize_t max_scf_name_length;
990Sstevel@tonic-gate static ssize_t max_scf_value_length;
1000Sstevel@tonic-gate static ssize_t max_scf_fmri_length;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate /* Options */
1030Sstevel@tonic-gate static int quiet = 0; /* No output. Nothing found, exit(1) */
1040Sstevel@tonic-gate static int types = 0; /* Display types of properties. */
1050Sstevel@tonic-gate static int verbose = 0; /* Print not found errors to stderr. */
1060Sstevel@tonic-gate static int fmris = 0; /* Display full FMRIs for properties. */
1070Sstevel@tonic-gate static int wait = 0; /* Wait mode. */
1080Sstevel@tonic-gate static char *snapshot = "running"; /* Snapshot to use. */
1090Sstevel@tonic-gate static int Cflag = 0; /* C option supplied */
1100Sstevel@tonic-gate static int cflag = 0; /* c option supplied */
1110Sstevel@tonic-gate static int sflag = 0; /* s option supplied */
1120Sstevel@tonic-gate static int return_code; /* main's return code */
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate #define PRINT_NOPROP_ERRORS (!quiet || verbose)
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate /*
1170Sstevel@tonic-gate * For unexpected libscf errors. The ending newline is necessary to keep
1180Sstevel@tonic-gate * uu_die() from appending the errno error.
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate static void
scfdie()1210Sstevel@tonic-gate scfdie()
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate die(gettext("Unexpected libscf error: %s. Exiting.\n"),
1240Sstevel@tonic-gate scf_strerror(scf_error()));
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate static void *
safe_malloc(size_t sz)1280Sstevel@tonic-gate safe_malloc(size_t sz)
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate void *p;
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate p = malloc(sz);
1330Sstevel@tonic-gate if (p == NULL)
1340Sstevel@tonic-gate die(gettext("Could not allocate memory"));
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate return (p);
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate static void
usage()1400Sstevel@tonic-gate usage()
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage: %1$s [-fqtv] "
1430Sstevel@tonic-gate "[-C | -c | -s snapshot] "
1440Sstevel@tonic-gate "[-p [name/]name]... \n"
1450Sstevel@tonic-gate " {FMRI | pattern}...\n"
1460Sstevel@tonic-gate " %1$s -w [-fqtv] [-p [name/]name] "
1470Sstevel@tonic-gate "{FMRI | pattern}\n"), uu_getpname());
1480Sstevel@tonic-gate exit(UU_EXIT_USAGE);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate * Return an allocated copy of str, with the Bourne shell's metacharacters
1530Sstevel@tonic-gate * escaped by '\'.
1540Sstevel@tonic-gate *
1550Sstevel@tonic-gate * What about unicode?
1560Sstevel@tonic-gate */
1570Sstevel@tonic-gate static char *
quote_for_shell(const char * str)1580Sstevel@tonic-gate quote_for_shell(const char *str)
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate const char *sp;
1610Sstevel@tonic-gate char *dst, *dp;
1620Sstevel@tonic-gate size_t dst_len;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate const char * const metachars = ";&()|^<>\n \t\\\"\'`";
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate if (str[0] == '\0')
1670Sstevel@tonic-gate return (strdup("\"\""));
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate dst_len = 0;
1700Sstevel@tonic-gate for (sp = str; *sp != '\0'; ++sp) {
1710Sstevel@tonic-gate ++dst_len;
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate if (strchr(metachars, *sp) != NULL)
1740Sstevel@tonic-gate ++dst_len;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate if (sp - str == dst_len)
1780Sstevel@tonic-gate return (strdup(str));
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate dst = safe_malloc(dst_len + 1);
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate for (dp = dst, sp = str; *sp != '\0'; ++dp, ++sp) {
1830Sstevel@tonic-gate if (strchr(metachars, *sp) != NULL)
1840Sstevel@tonic-gate *dp++ = '\\';
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate *dp = *sp;
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate *dp = '\0';
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate return (dst);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate static void
print_value(scf_value_t * val)1940Sstevel@tonic-gate print_value(scf_value_t *val)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate char *buf, *qbuf;
1970Sstevel@tonic-gate ssize_t bufsz, r;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate bufsz = scf_value_get_as_string(val, NULL, 0) + 1;
2000Sstevel@tonic-gate if (bufsz - 1 < 0)
2010Sstevel@tonic-gate scfdie();
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate buf = safe_malloc(bufsz);
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate r = scf_value_get_as_string(val, buf, bufsz);
2060Sstevel@tonic-gate assert(r + 1 == bufsz);
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate qbuf = quote_for_shell(buf);
2090Sstevel@tonic-gate (void) fputs(qbuf, stdout);
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate free(qbuf);
2120Sstevel@tonic-gate free(buf);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate /*
2160Sstevel@tonic-gate * Display a property's values on a line. If types is true, prepend
2170Sstevel@tonic-gate * identification (the FMRI if fmris is true, pg/prop otherwise) and the type
2180Sstevel@tonic-gate * of the property.
2190Sstevel@tonic-gate */
2200Sstevel@tonic-gate static void
display_prop(scf_propertygroup_t * pg,scf_property_t * prop)2210Sstevel@tonic-gate display_prop(scf_propertygroup_t *pg, scf_property_t *prop)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate scf_value_t *val;
2240Sstevel@tonic-gate scf_iter_t *iter;
225*5040Swesolows int ret, first, err;
226*5040Swesolows
227*5040Swesolows const char * const permission_denied_emsg =
228*5040Swesolows gettext("Permission denied.\n");
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate if (types) {
2310Sstevel@tonic-gate scf_type_t ty;
2320Sstevel@tonic-gate char *buf;
2330Sstevel@tonic-gate size_t buf_sz;
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate if (fmris) {
2360Sstevel@tonic-gate buf_sz = max_scf_fmri_length + 1;
2370Sstevel@tonic-gate buf = safe_malloc(buf_sz);
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (scf_property_to_fmri(prop, buf, buf_sz) == -1)
2400Sstevel@tonic-gate scfdie();
2410Sstevel@tonic-gate (void) fputs(buf, stdout);
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate free(buf);
2440Sstevel@tonic-gate } else {
2450Sstevel@tonic-gate buf_sz = max_scf_name_length + 1;
2460Sstevel@tonic-gate buf = safe_malloc(buf_sz);
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate if (scf_pg_get_name(pg, buf, buf_sz) < 0)
2490Sstevel@tonic-gate scfdie();
2500Sstevel@tonic-gate (void) fputs(buf, stdout);
2510Sstevel@tonic-gate (void) putchar('/');
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate if (scf_property_get_name(prop, buf, buf_sz) < 0)
2540Sstevel@tonic-gate scfdie();
2550Sstevel@tonic-gate (void) fputs(buf, stdout);
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate free(buf);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate (void) putchar(' ');
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate if (scf_property_type(prop, &ty) == -1)
2630Sstevel@tonic-gate scfdie();
2640Sstevel@tonic-gate (void) fputs(scf_type_to_string(ty), stdout);
2650Sstevel@tonic-gate (void) putchar(' ');
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate if ((iter = scf_iter_create(hndl)) == NULL ||
2690Sstevel@tonic-gate (val = scf_value_create(hndl)) == NULL)
2700Sstevel@tonic-gate scfdie();
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) == -1)
2730Sstevel@tonic-gate scfdie();
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate first = 1;
2760Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) {
2770Sstevel@tonic-gate if (first)
2780Sstevel@tonic-gate first = 0;
2790Sstevel@tonic-gate else
2800Sstevel@tonic-gate (void) putchar(' ');
2810Sstevel@tonic-gate print_value(val);
2820Sstevel@tonic-gate }
283*5040Swesolows if (ret == -1) {
284*5040Swesolows err = scf_error();
285*5040Swesolows if (err == SCF_ERROR_PERMISSION_DENIED) {
286*5040Swesolows if (uu_list_numnodes(prop_list) > 0)
287*5040Swesolows die(permission_denied_emsg);
288*5040Swesolows } else {
289*5040Swesolows scfdie();
290*5040Swesolows }
291*5040Swesolows }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate (void) putchar('\n');
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate scf_iter_destroy(iter);
2960Sstevel@tonic-gate (void) scf_value_destroy(val);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate * display_prop() all of the properties in the given property group. Force
3010Sstevel@tonic-gate * types to true so identification will be displayed.
3020Sstevel@tonic-gate */
3030Sstevel@tonic-gate static void
display_pg(scf_propertygroup_t * pg)3040Sstevel@tonic-gate display_pg(scf_propertygroup_t *pg)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate scf_property_t *prop;
3070Sstevel@tonic-gate scf_iter_t *iter;
3080Sstevel@tonic-gate int ret;
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate types = 1; /* Always display types for whole propertygroups. */
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate if ((prop = scf_property_create(hndl)) == NULL ||
3130Sstevel@tonic-gate (iter = scf_iter_create(hndl)) == NULL)
3140Sstevel@tonic-gate scfdie();
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate if (scf_iter_pg_properties(iter, pg) == -1)
3170Sstevel@tonic-gate scfdie();
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate while ((ret = scf_iter_next_property(iter, prop)) == 1)
3200Sstevel@tonic-gate display_prop(pg, prop);
3210Sstevel@tonic-gate if (ret == -1)
3220Sstevel@tonic-gate scfdie();
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate scf_iter_destroy(iter);
3250Sstevel@tonic-gate scf_property_destroy(prop);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate /*
3290Sstevel@tonic-gate * Common code to execute when a nonexistant property is encountered.
3300Sstevel@tonic-gate */
3310Sstevel@tonic-gate static void
noprop_common_action()3320Sstevel@tonic-gate noprop_common_action()
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate if (!PRINT_NOPROP_ERRORS)
3350Sstevel@tonic-gate /* We're not printing errors, so we can cut out early. */
3360Sstevel@tonic-gate exit(UU_EXIT_FATAL);
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate return_code = UU_EXIT_FATAL;
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate /*
3420Sstevel@tonic-gate * Iterate the properties of a service or an instance when no snapshot
3430Sstevel@tonic-gate * is specified.
3440Sstevel@tonic-gate */
3450Sstevel@tonic-gate static int
scf_iter_entity_pgs(scf_iter_t * iter,scf_entityp_t ent)3460Sstevel@tonic-gate scf_iter_entity_pgs(scf_iter_t *iter, scf_entityp_t ent)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate int ret = 0;
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate if (ent.type) {
3510Sstevel@tonic-gate /*
3520Sstevel@tonic-gate * If we are displaying properties for a service,
3530Sstevel@tonic-gate * treat it as though it were a composed, current
3540Sstevel@tonic-gate * lookup. (implicit cflag) However, if a snapshot
3550Sstevel@tonic-gate * was specified, fail.
3560Sstevel@tonic-gate */
3570Sstevel@tonic-gate if (sflag)
3580Sstevel@tonic-gate die(gettext("Only instances have "
3590Sstevel@tonic-gate "snapshots.\n"));
3600Sstevel@tonic-gate ret = scf_iter_service_pgs(iter, ent.u.svc);
3610Sstevel@tonic-gate } else {
3620Sstevel@tonic-gate if (Cflag)
3630Sstevel@tonic-gate ret = scf_iter_instance_pgs(iter, ent.u.inst);
3640Sstevel@tonic-gate else
3650Sstevel@tonic-gate ret = scf_iter_instance_pgs_composed(iter, ent.u.inst,
3660Sstevel@tonic-gate NULL);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate return (ret);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate * Return a snapshot for the supplied instance and snapshot name.
3730Sstevel@tonic-gate */
3740Sstevel@tonic-gate static scf_snapshot_t *
get_snapshot(const scf_instance_t * inst,const char * snapshot)3750Sstevel@tonic-gate get_snapshot(const scf_instance_t *inst, const char *snapshot)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate scf_snapshot_t *snap = scf_snapshot_create(hndl);
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate if (snap == NULL)
3800Sstevel@tonic-gate scfdie();
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, snapshot, snap) == -1) {
3830Sstevel@tonic-gate switch (scf_error()) {
3840Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
3850Sstevel@tonic-gate die(gettext("Invalid snapshot name.\n"));
3860Sstevel@tonic-gate /* NOTREACHED */
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
3890Sstevel@tonic-gate if (sflag == 0) {
3900Sstevel@tonic-gate scf_snapshot_destroy(snap);
3910Sstevel@tonic-gate snap = NULL;
3920Sstevel@tonic-gate } else
3930Sstevel@tonic-gate die(gettext("No such snapshot.\n"));
3940Sstevel@tonic-gate break;
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate default:
3970Sstevel@tonic-gate scfdie();
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate return (snap);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate /*
4050Sstevel@tonic-gate * Entity (service or instance): If there are -p options,
4060Sstevel@tonic-gate * display_{pg,prop}() the named property groups and/or properties. Otherwise
4070Sstevel@tonic-gate * display_pg() all property groups.
4080Sstevel@tonic-gate */
4090Sstevel@tonic-gate static void
process_ent(scf_entityp_t ent)4100Sstevel@tonic-gate process_ent(scf_entityp_t ent)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate scf_snapshot_t *snap = NULL;
4130Sstevel@tonic-gate scf_propertygroup_t *pg;
4140Sstevel@tonic-gate scf_property_t *prop;
4150Sstevel@tonic-gate scf_iter_t *iter;
4160Sstevel@tonic-gate svcprop_prop_node_t *spn;
4170Sstevel@tonic-gate int ret, err;
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate if (uu_list_numnodes(prop_list) == 0) {
4200Sstevel@tonic-gate if (quiet)
4210Sstevel@tonic-gate return;
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate if ((pg = scf_pg_create(hndl)) == NULL ||
4240Sstevel@tonic-gate (iter = scf_iter_create(hndl)) == NULL)
4250Sstevel@tonic-gate scfdie();
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if (cflag || Cflag || ent.type != ENT_INSTANCE) {
4280Sstevel@tonic-gate if (scf_iter_entity_pgs(iter, ent) == -1)
4290Sstevel@tonic-gate scfdie();
4300Sstevel@tonic-gate } else {
4310Sstevel@tonic-gate if (snapshot != NULL)
4320Sstevel@tonic-gate snap = get_snapshot(ent.u.inst, snapshot);
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate if (scf_iter_instance_pgs_composed(iter, ent.u.inst,
4350Sstevel@tonic-gate snap) == -1)
4360Sstevel@tonic-gate scfdie();
4370Sstevel@tonic-gate if (snap)
4380Sstevel@tonic-gate scf_snapshot_destroy(snap);
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate while ((ret = scf_iter_next_pg(iter, pg)) == 1)
4420Sstevel@tonic-gate display_pg(pg);
4430Sstevel@tonic-gate if (ret == -1)
4440Sstevel@tonic-gate scfdie();
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate * In normal usage, i.e. against the running snapshot,
4480Sstevel@tonic-gate * we must iterate over the current non-persistent
4490Sstevel@tonic-gate * pg's.
4500Sstevel@tonic-gate */
4510Sstevel@tonic-gate if (sflag == 0 && snap != NULL) {
4520Sstevel@tonic-gate scf_iter_reset(iter);
4530Sstevel@tonic-gate if (scf_iter_instance_pgs_composed(iter, ent.u.inst,
4540Sstevel@tonic-gate NULL) == -1)
4550Sstevel@tonic-gate scfdie();
4560Sstevel@tonic-gate while ((ret = scf_iter_next_pg(iter, pg)) == 1) {
4570Sstevel@tonic-gate uint32_t flags;
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate if (scf_pg_get_flags(pg, &flags) == -1)
4600Sstevel@tonic-gate scfdie();
4610Sstevel@tonic-gate if (flags & SCF_PG_FLAG_NONPERSISTENT)
4620Sstevel@tonic-gate display_pg(pg);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate if (ret == -1)
4660Sstevel@tonic-gate scfdie();
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate scf_iter_destroy(iter);
4690Sstevel@tonic-gate scf_pg_destroy(pg);
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate return;
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate if ((pg = scf_pg_create(hndl)) == NULL ||
4750Sstevel@tonic-gate (prop = scf_property_create(hndl)) == NULL)
4760Sstevel@tonic-gate scfdie();
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate if (ent.type == ENT_INSTANCE && snapshot != NULL)
4790Sstevel@tonic-gate snap = get_snapshot(ent.u.inst, snapshot);
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate for (spn = uu_list_first(prop_list);
4820Sstevel@tonic-gate spn != NULL;
4830Sstevel@tonic-gate spn = uu_list_next(prop_list, spn)) {
4840Sstevel@tonic-gate if (ent.type == ENT_INSTANCE) {
4850Sstevel@tonic-gate if (Cflag)
4860Sstevel@tonic-gate ret = scf_instance_get_pg(ent.u.inst,
4870Sstevel@tonic-gate spn->spn_comp1, pg);
4880Sstevel@tonic-gate else
4890Sstevel@tonic-gate ret = scf_instance_get_pg_composed(ent.u.inst,
4900Sstevel@tonic-gate snap, spn->spn_comp1, pg);
4910Sstevel@tonic-gate err = scf_error();
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate /*
4940Sstevel@tonic-gate * If we didn't find it in the specified snapshot, use
4950Sstevel@tonic-gate * the current values if the pg is nonpersistent.
4960Sstevel@tonic-gate */
4970Sstevel@tonic-gate if (ret == -1 && !Cflag &&snap != NULL && err ==
4980Sstevel@tonic-gate SCF_ERROR_NOT_FOUND) {
4990Sstevel@tonic-gate ret = scf_instance_get_pg_composed(
5000Sstevel@tonic-gate ent.u.inst, NULL, spn->spn_comp1,
5010Sstevel@tonic-gate pg);
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate if (ret == 0) {
5040Sstevel@tonic-gate uint32_t flags;
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate if (scf_pg_get_flags(pg, &flags) == -1)
5070Sstevel@tonic-gate scfdie();
5080Sstevel@tonic-gate if ((flags & SCF_PG_FLAG_NONPERSISTENT)
5090Sstevel@tonic-gate == 0) {
5100Sstevel@tonic-gate ret = -1;
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate } else {
5150Sstevel@tonic-gate /*
5160Sstevel@tonic-gate * If we are displaying properties for a service,
5170Sstevel@tonic-gate * treat it as though it were a composed, current
5180Sstevel@tonic-gate * lookup. (implicit cflag) However, if a snapshot
5190Sstevel@tonic-gate * was specified, fail.
5200Sstevel@tonic-gate */
5210Sstevel@tonic-gate if (sflag)
5220Sstevel@tonic-gate die(gettext("Only instances have "
5230Sstevel@tonic-gate "snapshots.\n"));
5240Sstevel@tonic-gate ret = scf_entity_get_pg(ent, spn->spn_comp1, pg);
5250Sstevel@tonic-gate err = scf_error();
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate if (ret == -1) {
5280Sstevel@tonic-gate if (err != SCF_ERROR_NOT_FOUND)
5290Sstevel@tonic-gate scfdie();
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate if (PRINT_NOPROP_ERRORS) {
5320Sstevel@tonic-gate char *buf;
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate buf = safe_malloc(max_scf_fmri_length + 1);
5350Sstevel@tonic-gate if (scf_entity_to_fmri(ent, buf,
5360Sstevel@tonic-gate max_scf_fmri_length + 1) == -1)
5370Sstevel@tonic-gate scfdie();
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate uu_warn(gettext("Couldn't find property group "
5400Sstevel@tonic-gate "`%s' for %s `%s'.\n"), spn->spn_comp1,
5410Sstevel@tonic-gate SCF_ENTITY_TYPE_NAME(ent), buf);
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate free(buf);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate noprop_common_action();
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate continue;
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate if (spn->spn_comp2 == NULL) {
5520Sstevel@tonic-gate if (!quiet)
5530Sstevel@tonic-gate display_pg(pg);
5540Sstevel@tonic-gate continue;
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate if (scf_pg_get_property(pg, spn->spn_comp2, prop) == -1) {
5580Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
5590Sstevel@tonic-gate scfdie();
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate if (PRINT_NOPROP_ERRORS) {
5620Sstevel@tonic-gate char *buf;
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate buf = safe_malloc(max_scf_fmri_length + 1);
5650Sstevel@tonic-gate if (scf_entity_to_fmri(ent, buf,
5660Sstevel@tonic-gate max_scf_fmri_length + 1) == -1)
5670Sstevel@tonic-gate scfdie();
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate /* FMRI syntax knowledge */
5700Sstevel@tonic-gate uu_warn(gettext("Couldn't find property "
5710Sstevel@tonic-gate "`%s/%s' for %s `%s'.\n"), spn->spn_comp1,
5720Sstevel@tonic-gate spn->spn_comp2, SCF_ENTITY_TYPE_NAME(ent),
5730Sstevel@tonic-gate buf);
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate free(buf);
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate noprop_common_action();
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate continue;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate if (!quiet)
5840Sstevel@tonic-gate display_prop(pg, prop);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate scf_property_destroy(prop);
5880Sstevel@tonic-gate scf_pg_destroy(pg);
5890Sstevel@tonic-gate if (snap)
5900Sstevel@tonic-gate scf_snapshot_destroy(snap);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate * Without -p options, just call display_pg(). Otherwise display_prop() the
5950Sstevel@tonic-gate * named properties of the property group.
5960Sstevel@tonic-gate */
5970Sstevel@tonic-gate static void
process_pg(scf_propertygroup_t * pg)5980Sstevel@tonic-gate process_pg(scf_propertygroup_t *pg)
5990Sstevel@tonic-gate {
6000Sstevel@tonic-gate scf_property_t *prop;
6010Sstevel@tonic-gate svcprop_prop_node_t *spn;
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate if (uu_list_first(prop_list) == NULL) {
6040Sstevel@tonic-gate if (quiet)
6050Sstevel@tonic-gate return;
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate display_pg(pg);
6080Sstevel@tonic-gate return;
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate prop = scf_property_create(hndl);
6120Sstevel@tonic-gate if (prop == NULL)
6130Sstevel@tonic-gate scfdie();
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate for (spn = uu_list_first(prop_list);
6160Sstevel@tonic-gate spn != NULL;
6170Sstevel@tonic-gate spn = uu_list_next(prop_list, spn)) {
6180Sstevel@tonic-gate if (spn->spn_comp2 != NULL) {
6190Sstevel@tonic-gate char *buf;
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate buf = safe_malloc(max_scf_fmri_length + 1);
6220Sstevel@tonic-gate if (scf_pg_to_fmri(pg, buf, max_scf_fmri_length + 1) ==
6230Sstevel@tonic-gate -1)
6240Sstevel@tonic-gate scfdie();
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("-p argument `%s/%s' "
6270Sstevel@tonic-gate "has too many components for property "
6280Sstevel@tonic-gate "group `%s'.\n"), spn->spn_comp1, spn->spn_comp2,
6290Sstevel@tonic-gate buf);
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate free(buf);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate if (scf_pg_get_property(pg, spn->spn_comp1, prop) == 0) {
6350Sstevel@tonic-gate if (!quiet)
6360Sstevel@tonic-gate display_prop(pg, prop);
6370Sstevel@tonic-gate continue;
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
6410Sstevel@tonic-gate scfdie();
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate if (PRINT_NOPROP_ERRORS) {
6440Sstevel@tonic-gate char *buf;
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate buf = safe_malloc(max_scf_fmri_length + 1);
6470Sstevel@tonic-gate if (scf_pg_to_fmri(pg, buf, max_scf_fmri_length + 1) ==
6480Sstevel@tonic-gate -1)
6490Sstevel@tonic-gate scfdie();
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate uu_warn(gettext("Couldn't find property `%s' in "
6520Sstevel@tonic-gate "property group `%s'.\n"), spn->spn_comp1, buf);
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate free(buf);
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate noprop_common_action();
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate /*
6620Sstevel@tonic-gate * If there are -p options, show the error. Otherwise just call
6630Sstevel@tonic-gate * display_prop().
6640Sstevel@tonic-gate */
6650Sstevel@tonic-gate static void
process_prop(scf_propertygroup_t * pg,scf_property_t * prop)6660Sstevel@tonic-gate process_prop(scf_propertygroup_t *pg, scf_property_t *prop)
6670Sstevel@tonic-gate {
6680Sstevel@tonic-gate if (uu_list_first(prop_list) != NULL) {
6690Sstevel@tonic-gate uu_warn(gettext("The -p option cannot be used with property "
6700Sstevel@tonic-gate "operands.\n"));
6710Sstevel@tonic-gate usage();
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate if (quiet)
6750Sstevel@tonic-gate return;
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate display_prop(pg, prop);
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate /* Decode an operand & dispatch. */
6810Sstevel@tonic-gate /* ARGSUSED */
6820Sstevel@tonic-gate static int
process_fmri(void * unused,scf_walkinfo_t * wip)6830Sstevel@tonic-gate process_fmri(void *unused, scf_walkinfo_t *wip)
6840Sstevel@tonic-gate {
6850Sstevel@tonic-gate scf_entityp_t ent;
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /* Multiple matches imply multiple entities. */
6880Sstevel@tonic-gate if (wip->count > 1)
6890Sstevel@tonic-gate types = fmris = 1;
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate if (wip->prop != NULL) {
6920Sstevel@tonic-gate process_prop(wip->pg, wip->prop);
6930Sstevel@tonic-gate } else if (wip->pg != NULL) {
6940Sstevel@tonic-gate process_pg(wip->pg);
6950Sstevel@tonic-gate } else if (wip->inst != NULL) {
6960Sstevel@tonic-gate SCF_ENTITY_SET_TO_INSTANCE(ent, wip->inst);
6970Sstevel@tonic-gate process_ent(ent);
6980Sstevel@tonic-gate } else {
6990Sstevel@tonic-gate /* scf_walk_fmri() won't let this happen */
7000Sstevel@tonic-gate assert(wip->svc != NULL);
7010Sstevel@tonic-gate SCF_ENTITY_SET_TO_SERVICE(ent, wip->svc);
7020Sstevel@tonic-gate process_ent(ent);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate
7050Sstevel@tonic-gate return (0);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate static void
add_prop(char * property)7090Sstevel@tonic-gate add_prop(char *property)
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate svcprop_prop_node_t *p, *last;
7120Sstevel@tonic-gate char *slash;
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate const char * const invalid_component_emsg =
7150Sstevel@tonic-gate gettext("Invalid component name `%s'.\n");
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate /* FMRI syntax knowledge. */
7180Sstevel@tonic-gate slash = strchr(property, '/');
7190Sstevel@tonic-gate if (slash != NULL) {
7200Sstevel@tonic-gate if (strchr(slash + 1, '/') != NULL) {
7210Sstevel@tonic-gate uu_warn(gettext("-p argument `%s' has too many "
7220Sstevel@tonic-gate "components.\n"), property);
7230Sstevel@tonic-gate usage();
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate if (slash != NULL)
7280Sstevel@tonic-gate *slash = '\0';
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate p = safe_malloc(sizeof (svcprop_prop_node_t));
7310Sstevel@tonic-gate uu_list_node_init(p, &p->spn_list_node, prop_pool);
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate p->spn_comp1 = property;
7340Sstevel@tonic-gate p->spn_comp2 = (slash == NULL) ? NULL : slash + 1;
7350Sstevel@tonic-gate
7360Sstevel@tonic-gate if (uu_check_name(p->spn_comp1, UU_NAME_DOMAIN) == -1)
7370Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, invalid_component_emsg, p->spn_comp1);
7380Sstevel@tonic-gate if (p->spn_comp2 != NULL &&
7390Sstevel@tonic-gate uu_check_name(p->spn_comp2, UU_NAME_DOMAIN) == -1)
7400Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, invalid_component_emsg, p->spn_comp2);
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate last = uu_list_last(prop_list);
7430Sstevel@tonic-gate if (last != NULL) {
7440Sstevel@tonic-gate if ((last->spn_comp2 == NULL) ^ (p->spn_comp2 == NULL)) {
7450Sstevel@tonic-gate /*
7460Sstevel@tonic-gate * The -p options have mixed numbers of components.
7470Sstevel@tonic-gate * If they both turn out to be valid, then the
7480Sstevel@tonic-gate * single-component ones will specify property groups,
7490Sstevel@tonic-gate * so we need to turn on types to keep the output of
7500Sstevel@tonic-gate * display_prop() consistent with display_pg().
7510Sstevel@tonic-gate */
7520Sstevel@tonic-gate types = 1;
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate (void) uu_list_insert_after(prop_list, NULL, p);
7570Sstevel@tonic-gate }
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate /*
7610Sstevel@tonic-gate * Wait for a property group or property change.
7620Sstevel@tonic-gate *
7630Sstevel@tonic-gate * Extract a pg and optionally a property name from fmri & prop_list.
7640Sstevel@tonic-gate * _scf_pg_wait() for the pg, and display_pg(pg) or display_prop(pg, prop)
7650Sstevel@tonic-gate * when it returns.
7660Sstevel@tonic-gate */
7670Sstevel@tonic-gate /* ARGSUSED */
7680Sstevel@tonic-gate static int
do_wait(void * unused,scf_walkinfo_t * wip)7690Sstevel@tonic-gate do_wait(void *unused, scf_walkinfo_t *wip)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate scf_property_t *prop;
7720Sstevel@tonic-gate scf_propertygroup_t *lpg, *pg;
7730Sstevel@tonic-gate const char *propname;
7740Sstevel@tonic-gate svcprop_prop_node_t *p;
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate const char *emsg_not_found = gettext("Not found.\n");
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate if ((lpg = scf_pg_create(hndl)) == NULL ||
7790Sstevel@tonic-gate (prop = scf_property_create(hndl)) == NULL)
7800Sstevel@tonic-gate scfdie();
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate if (wip->prop != NULL) {
7830Sstevel@tonic-gate if (uu_list_numnodes(prop_list) > 0)
7840Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("-p cannot be used with "
7850Sstevel@tonic-gate "property FMRIs.\n"));
7860Sstevel@tonic-gate pg = wip->pg;
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate assert(strrchr(wip->fmri, '/') != NULL);
7890Sstevel@tonic-gate propname = strrchr(wip->fmri, '/') + 1;
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate } else if (wip->pg != NULL) {
7920Sstevel@tonic-gate p = uu_list_first(prop_list);
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate if (p != NULL) {
7950Sstevel@tonic-gate if (p->spn_comp2 != NULL)
7960Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("-p argument "
7970Sstevel@tonic-gate "\"%s/%s\" has too many components for "
7980Sstevel@tonic-gate "property group %s.\n"),
7990Sstevel@tonic-gate p->spn_comp1, p->spn_comp2, wip->fmri);
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate propname = p->spn_comp1;
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate if (scf_pg_get_property(wip->pg, propname, prop) !=
8040Sstevel@tonic-gate SCF_SUCCESS) {
8050Sstevel@tonic-gate switch (scf_error()) {
8060Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
8070Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE,
8080Sstevel@tonic-gate gettext("Invalid property name "
8090Sstevel@tonic-gate "\"%s\".\n"), propname);
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate /* NOTREACHED */
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
8140Sstevel@tonic-gate die(emsg_not_found);
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate /* NOTREACHED */
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate default:
8190Sstevel@tonic-gate scfdie();
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate } else {
8230Sstevel@tonic-gate propname = NULL;
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate pg = wip->pg;
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate } else if (wip->inst != NULL) {
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate p = uu_list_first(prop_list);
8310Sstevel@tonic-gate if (p == NULL)
8320Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE,
8330Sstevel@tonic-gate gettext("Cannot wait for an instance.\n"));
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate if (scf_instance_get_pg(wip->inst, p->spn_comp1, lpg) !=
8360Sstevel@tonic-gate SCF_SUCCESS) {
8370Sstevel@tonic-gate switch (scf_error()) {
8380Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
8390Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("Invalid "
8400Sstevel@tonic-gate "property group name \"%s\".\n"),
8410Sstevel@tonic-gate p->spn_comp1);
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
8440Sstevel@tonic-gate die(emsg_not_found);
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate /* NOTREACHED */
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate default:
8490Sstevel@tonic-gate scfdie();
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate propname = p->spn_comp2;
8540Sstevel@tonic-gate
8550Sstevel@tonic-gate if (propname != NULL) {
8560Sstevel@tonic-gate if (scf_pg_get_property(lpg, propname, prop) !=
8570Sstevel@tonic-gate SCF_SUCCESS) {
8580Sstevel@tonic-gate switch (scf_error()) {
8590Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
8600Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE,
8610Sstevel@tonic-gate gettext("Invalid property name "
8620Sstevel@tonic-gate "\"%s\".\n"), propname);
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
8650Sstevel@tonic-gate die(emsg_not_found);
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate /* NOTREACHED */
8680Sstevel@tonic-gate
8690Sstevel@tonic-gate default:
8700Sstevel@tonic-gate scfdie();
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate
8750Sstevel@tonic-gate pg = lpg;
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate } else if (wip->svc != NULL) {
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate p = uu_list_first(prop_list);
8800Sstevel@tonic-gate if (p == NULL)
8810Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE,
8820Sstevel@tonic-gate gettext("Cannot wait for a service.\n"));
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate if (scf_service_get_pg(wip->svc, p->spn_comp1, lpg) !=
8850Sstevel@tonic-gate SCF_SUCCESS) {
8860Sstevel@tonic-gate switch (scf_error()) {
8870Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
8880Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("Invalid "
8890Sstevel@tonic-gate "property group name \"%s\".\n"),
8900Sstevel@tonic-gate p->spn_comp1);
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
8930Sstevel@tonic-gate die(emsg_not_found);
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate default:
8960Sstevel@tonic-gate scfdie();
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate propname = p->spn_comp2;
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate if (propname != NULL) {
9030Sstevel@tonic-gate if (scf_pg_get_property(lpg, propname, prop) !=
9040Sstevel@tonic-gate SCF_SUCCESS) {
9050Sstevel@tonic-gate switch (scf_error()) {
9060Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
9070Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE,
9080Sstevel@tonic-gate gettext("Invalid property name "
9090Sstevel@tonic-gate "\"%s\".\n"), propname);
9100Sstevel@tonic-gate
9110Sstevel@tonic-gate /* NOTREACHED */
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
9140Sstevel@tonic-gate die(emsg_not_found);
9150Sstevel@tonic-gate
9160Sstevel@tonic-gate /* NOTREACHED */
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate default:
9190Sstevel@tonic-gate scfdie();
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate pg = lpg;
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate } else {
9270Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("FMRI must specify an entity, "
9280Sstevel@tonic-gate "property group, or property.\n"));
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate for (;;) {
9320Sstevel@tonic-gate int ret;
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate ret = _scf_pg_wait(pg, -1);
9350Sstevel@tonic-gate if (ret != SCF_SUCCESS)
9360Sstevel@tonic-gate scfdie();
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate ret = scf_pg_update(pg);
9390Sstevel@tonic-gate if (ret < 0) {
9400Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED)
9410Sstevel@tonic-gate scfdie();
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate die(emsg_not_found);
9440Sstevel@tonic-gate }
9450Sstevel@tonic-gate if (ret == SCF_COMPLETE)
9460Sstevel@tonic-gate break;
9470Sstevel@tonic-gate }
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate if (propname != NULL) {
9500Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) == SCF_SUCCESS) {
9510Sstevel@tonic-gate if (!quiet)
9520Sstevel@tonic-gate display_prop(pg, prop);
9530Sstevel@tonic-gate } else {
9540Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
9550Sstevel@tonic-gate scfdie();
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate if (PRINT_NOPROP_ERRORS)
9580Sstevel@tonic-gate uu_warn(emsg_not_found);
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate return_code = UU_EXIT_FATAL;
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate } else {
9630Sstevel@tonic-gate if (!quiet)
9640Sstevel@tonic-gate display_pg(pg);
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate scf_property_destroy(prop);
9680Sstevel@tonic-gate scf_pg_destroy(lpg);
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate return (0);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate /*
9740Sstevel@tonic-gate * These functions replace uu_warn() and uu_die() when the quiet (-q) option is
9750Sstevel@tonic-gate * used, and silently ignore any output.
9760Sstevel@tonic-gate */
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate /*ARGSUSED*/
9790Sstevel@tonic-gate static void
quiet_warn(const char * fmt,...)9800Sstevel@tonic-gate quiet_warn(const char *fmt, ...)
9810Sstevel@tonic-gate {
9820Sstevel@tonic-gate /* Do nothing */
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate /*ARGSUSED*/
9860Sstevel@tonic-gate static void
quiet_die(const char * fmt,...)9870Sstevel@tonic-gate quiet_die(const char *fmt, ...)
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate exit(UU_EXIT_FATAL);
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate int
main(int argc,char * argv[])9930Sstevel@tonic-gate main(int argc, char *argv[])
9940Sstevel@tonic-gate {
9950Sstevel@tonic-gate int c;
9960Sstevel@tonic-gate scf_walk_callback callback;
9970Sstevel@tonic-gate int flags;
9980Sstevel@tonic-gate int err;
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
10010Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate return_code = UU_EXIT_OK;
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate (void) uu_setpname(argv[0]);
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate prop_pool = uu_list_pool_create("properties",
10080Sstevel@tonic-gate sizeof (svcprop_prop_node_t),
10090Sstevel@tonic-gate offsetof(svcprop_prop_node_t, spn_list_node), NULL, 0);
10100Sstevel@tonic-gate if (prop_pool == NULL)
10110Sstevel@tonic-gate uu_die("%s\n", uu_strerror(uu_error()));
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate prop_list = uu_list_create(prop_pool, NULL, 0);
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate while ((c = getopt(argc, argv, "Ccfp:qs:tvw")) != -1) {
10160Sstevel@tonic-gate switch (c) {
10170Sstevel@tonic-gate case 'C':
10180Sstevel@tonic-gate if (cflag || sflag || wait)
10190Sstevel@tonic-gate usage(); /* Not with -c, -s or -w */
10200Sstevel@tonic-gate Cflag++;
10210Sstevel@tonic-gate snapshot = NULL;
10220Sstevel@tonic-gate break;
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate case 'c':
10250Sstevel@tonic-gate if (Cflag || sflag || wait)
10260Sstevel@tonic-gate usage(); /* Not with -C, -s or -w */
10270Sstevel@tonic-gate cflag++;
10280Sstevel@tonic-gate snapshot = NULL;
10290Sstevel@tonic-gate break;
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate case 'f':
10320Sstevel@tonic-gate types = 1;
10330Sstevel@tonic-gate fmris = 1;
10340Sstevel@tonic-gate break;
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate case 'p':
10370Sstevel@tonic-gate add_prop(optarg);
10380Sstevel@tonic-gate break;
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate case 'q':
10410Sstevel@tonic-gate quiet = 1;
10420Sstevel@tonic-gate warn = quiet_warn;
10430Sstevel@tonic-gate die = quiet_die;
10440Sstevel@tonic-gate break;
10450Sstevel@tonic-gate
10460Sstevel@tonic-gate case 's':
10470Sstevel@tonic-gate if (Cflag || cflag || wait)
10480Sstevel@tonic-gate usage(); /* Not with -C, -c or -w */
10490Sstevel@tonic-gate snapshot = optarg;
10500Sstevel@tonic-gate sflag++;
10510Sstevel@tonic-gate break;
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate case 't':
10540Sstevel@tonic-gate types = 1;
10550Sstevel@tonic-gate break;
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate case 'v':
10580Sstevel@tonic-gate verbose = 1;
10590Sstevel@tonic-gate break;
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate case 'w':
10620Sstevel@tonic-gate if (Cflag || cflag || sflag)
10630Sstevel@tonic-gate usage(); /* Not with -C, -c or -s */
10640Sstevel@tonic-gate wait = 1;
10650Sstevel@tonic-gate break;
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate case '?':
10680Sstevel@tonic-gate switch (optopt) {
10690Sstevel@tonic-gate case 'p':
10700Sstevel@tonic-gate usage();
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate default:
10730Sstevel@tonic-gate break;
10740Sstevel@tonic-gate }
10750Sstevel@tonic-gate
10760Sstevel@tonic-gate /* FALLTHROUGH */
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate default:
10790Sstevel@tonic-gate usage();
10800Sstevel@tonic-gate }
10810Sstevel@tonic-gate }
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate if (optind == argc)
10840Sstevel@tonic-gate usage();
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate max_scf_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
10870Sstevel@tonic-gate max_scf_value_length = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
10880Sstevel@tonic-gate max_scf_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
10890Sstevel@tonic-gate if (max_scf_name_length == -1 || max_scf_value_length == -1 ||
10900Sstevel@tonic-gate max_scf_fmri_length == -1)
10910Sstevel@tonic-gate scfdie();
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate hndl = scf_handle_create(SCF_VERSION);
10940Sstevel@tonic-gate if (hndl == NULL)
10950Sstevel@tonic-gate scfdie();
10960Sstevel@tonic-gate if (scf_handle_bind(hndl) == -1)
10970Sstevel@tonic-gate die(gettext("Could not connect to configuration repository: "
10980Sstevel@tonic-gate "%s.\n"), scf_strerror(scf_error()));
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate flags = SCF_WALK_PROPERTY | SCF_WALK_SERVICE | SCF_WALK_EXPLICIT;
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate if (wait) {
11030Sstevel@tonic-gate if (uu_list_numnodes(prop_list) > 1)
11040Sstevel@tonic-gate usage();
11050Sstevel@tonic-gate
11060Sstevel@tonic-gate if (argc - optind > 1)
11070Sstevel@tonic-gate usage();
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate callback = do_wait;
11100Sstevel@tonic-gate
11110Sstevel@tonic-gate } else {
11120Sstevel@tonic-gate callback = process_fmri;
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate flags |= SCF_WALK_MULTIPLE;
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate if ((err = scf_walk_fmri(hndl, argc - optind, argv + optind, flags,
11180Sstevel@tonic-gate callback, NULL, &return_code, warn)) != 0) {
11190Sstevel@tonic-gate warn(gettext("failed to iterate over instances: %s\n"),
11200Sstevel@tonic-gate scf_strerror(err));
11210Sstevel@tonic-gate return_code = UU_EXIT_FATAL;
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate scf_handle_destroy(hndl);
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate return (return_code);
11270Sstevel@tonic-gate }
1128