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
57646ae23Slianep * Common Development and Distribution License (the "License").
67646ae23Slianep * 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 */
217c478bd9Sstevel@tonic-gate /*
22eb1a3463STruong Nguyen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
276c7c876cSJerry Jelinek * Copyright 2013, Joyent, Inc. All rights reserved.
28647f8444SBryan Cantrill */
29647f8444SBryan Cantrill
30647f8444SBryan Cantrill /*
317c478bd9Sstevel@tonic-gate * svcadm - request adminstrative actions for service instances
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include <locale.h>
357c478bd9Sstevel@tonic-gate #include <libintl.h>
367c478bd9Sstevel@tonic-gate #include <libscf.h>
377c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
38eb1a3463STruong Nguyen #include <libcontract.h>
39eb1a3463STruong Nguyen #include <libcontract_priv.h>
40eb1a3463STruong Nguyen #include <sys/contract/process.h>
417c478bd9Sstevel@tonic-gate #include <libuutil.h>
427c478bd9Sstevel@tonic-gate #include <stddef.h>
437c478bd9Sstevel@tonic-gate #include <stdio.h>
447c478bd9Sstevel@tonic-gate #include <stdlib.h>
457c478bd9Sstevel@tonic-gate #include <string.h>
467c478bd9Sstevel@tonic-gate #include <unistd.h>
47eb1a3463STruong Nguyen #include <fcntl.h>
48eb1a3463STruong Nguyen #include <procfs.h>
497c478bd9Sstevel@tonic-gate #include <assert.h>
507c478bd9Sstevel@tonic-gate #include <errno.h>
51647f8444SBryan Cantrill #include <zone.h>
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
547c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD"
557c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate /* Must be a power of two */
587c478bd9Sstevel@tonic-gate #define HT_BUCKETS 64
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * Exit codes for enable and disable -s.
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate #define EXIT_SVC_FAILURE 3
647c478bd9Sstevel@tonic-gate #define EXIT_DEP_FAILURE 4
657c478bd9Sstevel@tonic-gate
666c7c876cSJerry Jelinek #define WALK_FLAGS (SCF_WALK_UNIPARTIAL | SCF_WALK_MULTIPLE)
676c7c876cSJerry Jelinek
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate * How long we will wait (in seconds) for a service to change state
707c478bd9Sstevel@tonic-gate * before re-checking its dependencies.
717c478bd9Sstevel@tonic-gate */
727c478bd9Sstevel@tonic-gate #define WAIT_INTERVAL 3
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate #ifndef NDEBUG
757c478bd9Sstevel@tonic-gate #define bad_error(func, err) { \
76702a871aSJerry Jelinek pr_warn("%s:%d: %s() failed with unexpected error %d.\n", \
777c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \
787c478bd9Sstevel@tonic-gate abort(); \
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate #else
817c478bd9Sstevel@tonic-gate #define bad_error(func, err) abort()
827c478bd9Sstevel@tonic-gate #endif
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate struct ht_elt {
867c478bd9Sstevel@tonic-gate struct ht_elt *next;
877c478bd9Sstevel@tonic-gate boolean_t active;
887c478bd9Sstevel@tonic-gate char str[1];
897c478bd9Sstevel@tonic-gate };
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate scf_handle_t *h;
937c478bd9Sstevel@tonic-gate ssize_t max_scf_fmri_sz;
947c478bd9Sstevel@tonic-gate static const char *emsg_permission_denied;
957c478bd9Sstevel@tonic-gate static const char *emsg_nomem;
967c478bd9Sstevel@tonic-gate static const char *emsg_create_pg_perm_denied;
977c478bd9Sstevel@tonic-gate static const char *emsg_pg_perm_denied;
987c478bd9Sstevel@tonic-gate static const char *emsg_prop_perm_denied;
997c478bd9Sstevel@tonic-gate static const char *emsg_no_service;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate static int exit_status = 0;
1027c478bd9Sstevel@tonic-gate static int verbose = 0;
1037c478bd9Sstevel@tonic-gate static char *scratch_fmri;
104702a871aSJerry Jelinek static char *g_zonename = NULL;
10537b40227SJerry Jelinek static char svcstate[80];
10637b40227SJerry Jelinek static boolean_t svcsearch = B_FALSE;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate static struct ht_elt **visited;
1097c478bd9Sstevel@tonic-gate
1100b5c9250Shg115875 void do_scfdie(int lineno) __NORETURN;
1110b5c9250Shg115875 static void usage_milestone(void) __NORETURN;
112eb1a3463STruong Nguyen static void set_astring_prop(const char *, const char *, const char *,
113eb1a3463STruong Nguyen uint32_t, const char *, const char *);
114702a871aSJerry Jelinek static void pr_warn(const char *format, ...);
1150b5c9250Shg115875
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate * Visitors from synch.c, needed for enable -s and disable -s.
1187c478bd9Sstevel@tonic-gate */
1197c478bd9Sstevel@tonic-gate extern int is_enabled(scf_instance_t *);
1207c478bd9Sstevel@tonic-gate extern int has_potential(scf_instance_t *, int);
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate void
do_scfdie(int lineno)1237c478bd9Sstevel@tonic-gate do_scfdie(int lineno)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate scf_error_t err;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate switch (err = scf_error()) {
1287c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
1297c478bd9Sstevel@tonic-gate uu_die(gettext("Connection to repository server broken. "
1307c478bd9Sstevel@tonic-gate "Exiting.\n"));
1317c478bd9Sstevel@tonic-gate /* NOTREACHED */
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
1347c478bd9Sstevel@tonic-gate uu_die(gettext("Repository is read-only. Exiting.\n"));
1357c478bd9Sstevel@tonic-gate /* NOTREACHED */
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate default:
1387c478bd9Sstevel@tonic-gate #ifdef NDEBUG
1397c478bd9Sstevel@tonic-gate uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"),
1407c478bd9Sstevel@tonic-gate scf_strerror(err));
1417c478bd9Sstevel@tonic-gate #else
1427c478bd9Sstevel@tonic-gate uu_die("Unexpected libscf error on line %d: %s.\n", lineno,
1437c478bd9Sstevel@tonic-gate scf_strerror(err));
1447c478bd9Sstevel@tonic-gate #endif
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate #define scfdie() do_scfdie(__LINE__)
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate static void
usage()1517c478bd9Sstevel@tonic-gate usage()
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
15437b40227SJerry Jelinek "Usage: %1$s [-S <state>] [-v] [-Z | -z zone] [cmd [args ... ]]\n\n"
15537b40227SJerry Jelinek "\t%1$s enable [-rst] [<service> ...]\t- enable and online service(s)\n"
15637b40227SJerry Jelinek "\t%1$s disable [-st] [<service> ...]\t- disable and offline "
15737b40227SJerry Jelinek "service(s)\n"
158*ac0324d2SJerry Jelinek "\t%1$s restart [-d] [<service> ...]\t- restart specified service(s)\n"
15937b40227SJerry Jelinek "\t%1$s refresh [<service> ...]\t\t- re-read service configuration\n"
16037b40227SJerry Jelinek "\t%1$s mark [-It] <state> [<service> ...] - set maintenance state\n"
16137b40227SJerry Jelinek "\t%1$s clear [<service> ...]\t\t- clear maintenance state\n"
1627c478bd9Sstevel@tonic-gate "\t%1$s milestone [-d] <milestone>\t- advance to a service milestone\n"
1637c478bd9Sstevel@tonic-gate "\n\t"
1647c478bd9Sstevel@tonic-gate "Services can be specified using an FMRI, abbreviation, or fnmatch(5)\n"
1657c478bd9Sstevel@tonic-gate "\tpattern, as shown in these examples for svc:/network/smtp:sendmail\n"
1667c478bd9Sstevel@tonic-gate "\n"
1677c478bd9Sstevel@tonic-gate "\t%1$s <cmd> svc:/network/smtp:sendmail\n"
1687c478bd9Sstevel@tonic-gate "\t%1$s <cmd> network/smtp:sendmail\n"
1697c478bd9Sstevel@tonic-gate "\t%1$s <cmd> network/*mail\n"
1707c478bd9Sstevel@tonic-gate "\t%1$s <cmd> network/smtp\n"
1717c478bd9Sstevel@tonic-gate "\t%1$s <cmd> smtp:sendmail\n"
1727c478bd9Sstevel@tonic-gate "\t%1$s <cmd> smtp\n"
1737c478bd9Sstevel@tonic-gate "\t%1$s <cmd> sendmail\n"), uu_getpname());
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE);
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * FMRI hash table for recursive enable.
1817c478bd9Sstevel@tonic-gate */
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate static uint32_t
hash_fmri(const char * str)1847c478bd9Sstevel@tonic-gate hash_fmri(const char *str)
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate uint32_t h = 0, g;
1877c478bd9Sstevel@tonic-gate const char *p;
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /* Generic hash function from uts/common/os/modhash.c . */
1907c478bd9Sstevel@tonic-gate for (p = str; *p != '\0'; ++p) {
1917c478bd9Sstevel@tonic-gate h = (h << 4) + *p;
1927c478bd9Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) {
1937c478bd9Sstevel@tonic-gate h ^= (g >> 24);
1947c478bd9Sstevel@tonic-gate h ^= g;
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate return (h);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate * Return 1 if str has been visited, 0 if it has not, and -1 if memory could not
2037c478bd9Sstevel@tonic-gate * be allocated.
2047c478bd9Sstevel@tonic-gate */
2057c478bd9Sstevel@tonic-gate static int
visited_find_or_add(const char * str,struct ht_elt ** hep)2067c478bd9Sstevel@tonic-gate visited_find_or_add(const char *str, struct ht_elt **hep)
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate uint32_t h;
2097c478bd9Sstevel@tonic-gate uint_t i;
2107c478bd9Sstevel@tonic-gate struct ht_elt *he;
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate h = hash_fmri(str);
2137c478bd9Sstevel@tonic-gate i = h & (HT_BUCKETS - 1);
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate for (he = visited[i]; he != NULL; he = he->next) {
2167c478bd9Sstevel@tonic-gate if (strcmp(he->str, str) == 0) {
2177c478bd9Sstevel@tonic-gate if (hep)
2187c478bd9Sstevel@tonic-gate *hep = he;
2197c478bd9Sstevel@tonic-gate return (1);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate he = malloc(offsetof(struct ht_elt, str) + strlen(str) + 1);
2247c478bd9Sstevel@tonic-gate if (he == NULL)
2257c478bd9Sstevel@tonic-gate return (-1);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate (void) strcpy(he->str, str);
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate he->next = visited[i];
2307c478bd9Sstevel@tonic-gate visited[i] = he;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate if (hep)
2337c478bd9Sstevel@tonic-gate *hep = he;
2347c478bd9Sstevel@tonic-gate return (0);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * Returns 0, ECANCELED if pg is deleted, ENOENT if propname doesn't exist,
2407c478bd9Sstevel@tonic-gate * EINVAL if the property is not of boolean type or has no values, and E2BIG
2417c478bd9Sstevel@tonic-gate * if it has more than one value. *bp is set if 0 or E2BIG is returned.
2427c478bd9Sstevel@tonic-gate */
2437c478bd9Sstevel@tonic-gate int
get_bool_prop(scf_propertygroup_t * pg,const char * propname,uint8_t * bp)2447c478bd9Sstevel@tonic-gate get_bool_prop(scf_propertygroup_t *pg, const char *propname, uint8_t *bp)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate scf_property_t *prop;
2477c478bd9Sstevel@tonic-gate scf_value_t *val;
2487c478bd9Sstevel@tonic-gate int ret;
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate if ((prop = scf_property_create(h)) == NULL ||
2517c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL)
2527c478bd9Sstevel@tonic-gate scfdie();
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) != 0) {
2557c478bd9Sstevel@tonic-gate switch (scf_error()) {
2567c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
2577c478bd9Sstevel@tonic-gate ret = ECANCELED;
2587c478bd9Sstevel@tonic-gate goto out;
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
2617c478bd9Sstevel@tonic-gate ret = ENOENT;
2627c478bd9Sstevel@tonic-gate goto out;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
2657c478bd9Sstevel@tonic-gate assert(0);
2667c478bd9Sstevel@tonic-gate abort();
2677c478bd9Sstevel@tonic-gate /* NOTREACHED */
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate default:
2707c478bd9Sstevel@tonic-gate scfdie();
2717c478bd9Sstevel@tonic-gate }
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) == 0) {
2757c478bd9Sstevel@tonic-gate ret = 0;
2767c478bd9Sstevel@tonic-gate } else {
2777c478bd9Sstevel@tonic-gate switch (scf_error()) {
2787c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
2797c478bd9Sstevel@tonic-gate ret = ENOENT;
2807c478bd9Sstevel@tonic-gate goto out;
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
2837c478bd9Sstevel@tonic-gate ret = EINVAL;
2847c478bd9Sstevel@tonic-gate goto out;
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED:
2877c478bd9Sstevel@tonic-gate ret = E2BIG;
2887c478bd9Sstevel@tonic-gate break;
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
2917c478bd9Sstevel@tonic-gate assert(0);
2927c478bd9Sstevel@tonic-gate abort();
2937c478bd9Sstevel@tonic-gate /* NOTREACHED */
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate default:
2967c478bd9Sstevel@tonic-gate scfdie();
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate if (scf_value_get_boolean(val, bp) != 0) {
3017c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH)
3027c478bd9Sstevel@tonic-gate scfdie();
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate ret = EINVAL;
3057c478bd9Sstevel@tonic-gate goto out;
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate out:
3097c478bd9Sstevel@tonic-gate scf_value_destroy(val);
3107c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
3117c478bd9Sstevel@tonic-gate return (ret);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate * Returns 0, EPERM, or EROFS.
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate static int
set_bool_prop(scf_propertygroup_t * pg,const char * propname,boolean_t b)3187c478bd9Sstevel@tonic-gate set_bool_prop(scf_propertygroup_t *pg, const char *propname, boolean_t b)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate scf_value_t *v;
3217c478bd9Sstevel@tonic-gate scf_transaction_t *tx;
3227c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ent;
3237c478bd9Sstevel@tonic-gate int ret = 0, r;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate if ((tx = scf_transaction_create(h)) == NULL ||
3267c478bd9Sstevel@tonic-gate (ent = scf_entry_create(h)) == NULL ||
3277c478bd9Sstevel@tonic-gate (v = scf_value_create(h)) == NULL)
3287c478bd9Sstevel@tonic-gate scfdie();
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate scf_value_set_boolean(v, b);
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate for (;;) {
3337c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) == -1) {
3347c478bd9Sstevel@tonic-gate switch (scf_error()) {
3357c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
3367c478bd9Sstevel@tonic-gate ret = EPERM;
3377c478bd9Sstevel@tonic-gate goto out;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
3407c478bd9Sstevel@tonic-gate ret = EROFS;
3417c478bd9Sstevel@tonic-gate goto out;
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate default:
3447c478bd9Sstevel@tonic-gate scfdie();
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, propname,
3497c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN) != 0) {
3507c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
3517c478bd9Sstevel@tonic-gate scfdie();
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, propname,
3547c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN) != 0)
3557c478bd9Sstevel@tonic-gate scfdie();
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, v);
3597c478bd9Sstevel@tonic-gate assert(r == 0);
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate r = scf_transaction_commit(tx);
3627c478bd9Sstevel@tonic-gate if (r == 1)
3637c478bd9Sstevel@tonic-gate break;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate scf_transaction_reset(tx);
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate if (r != 0) {
3687c478bd9Sstevel@tonic-gate switch (scf_error()) {
3697c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
3707c478bd9Sstevel@tonic-gate ret = EPERM;
3717c478bd9Sstevel@tonic-gate goto out;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
3747c478bd9Sstevel@tonic-gate ret = EROFS;
3757c478bd9Sstevel@tonic-gate goto out;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate default:
3787c478bd9Sstevel@tonic-gate scfdie();
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1)
3837c478bd9Sstevel@tonic-gate scfdie();
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate out:
3877c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx);
3887c478bd9Sstevel@tonic-gate scf_entry_destroy(ent);
3897c478bd9Sstevel@tonic-gate scf_value_destroy(v);
3907c478bd9Sstevel@tonic-gate return (ret);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate /*
3947c478bd9Sstevel@tonic-gate * Gets the single astring value of the propname property of pg. prop & v are
3957c478bd9Sstevel@tonic-gate * scratch space. Returns the length of the string on success or
3967c478bd9Sstevel@tonic-gate * -ENOENT - pg has no property named propname
3977c478bd9Sstevel@tonic-gate * -E2BIG - property has no values or multiple values
3987c478bd9Sstevel@tonic-gate * -EINVAL - property type is not compatible with astring
3997c478bd9Sstevel@tonic-gate */
4007c478bd9Sstevel@tonic-gate ssize_t
get_astring_prop(const scf_propertygroup_t * pg,const char * propname,scf_property_t * prop,scf_value_t * v,char * buf,size_t bufsz)4017c478bd9Sstevel@tonic-gate get_astring_prop(const scf_propertygroup_t *pg, const char *propname,
4027c478bd9Sstevel@tonic-gate scf_property_t *prop, scf_value_t *v, char *buf, size_t bufsz)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate ssize_t sz;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) != 0) {
4077c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
4087c478bd9Sstevel@tonic-gate scfdie();
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate return (-ENOENT);
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, v) != 0) {
4147c478bd9Sstevel@tonic-gate switch (scf_error()) {
4157c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
4167c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED:
4177c478bd9Sstevel@tonic-gate return (-E2BIG);
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate default:
4207c478bd9Sstevel@tonic-gate scfdie();
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate sz = scf_value_get_astring(v, buf, bufsz);
4257c478bd9Sstevel@tonic-gate if (sz < 0) {
4267c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH)
4277c478bd9Sstevel@tonic-gate scfdie();
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate return (-EINVAL);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate return (sz);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate * Returns 0 or EPERM.
4377c478bd9Sstevel@tonic-gate */
4387c478bd9Sstevel@tonic-gate static int
pg_get_or_add(const scf_instance_t * inst,const char * pgname,const char * pgtype,uint32_t pgflags,scf_propertygroup_t * pg)439eb1a3463STruong Nguyen pg_get_or_add(const scf_instance_t *inst, const char *pgname,
440eb1a3463STruong Nguyen const char *pgtype, uint32_t pgflags, scf_propertygroup_t *pg)
4417c478bd9Sstevel@tonic-gate {
4427c478bd9Sstevel@tonic-gate again:
4437c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) == 0)
4447c478bd9Sstevel@tonic-gate return (0);
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
4477c478bd9Sstevel@tonic-gate scfdie();
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, pgname, pgtype, pgflags, pg) == 0)
4507c478bd9Sstevel@tonic-gate return (0);
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate switch (scf_error()) {
4537c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
4547c478bd9Sstevel@tonic-gate goto again;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
4577c478bd9Sstevel@tonic-gate return (EPERM);
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate default:
4607c478bd9Sstevel@tonic-gate scfdie();
4617c478bd9Sstevel@tonic-gate /* NOTREACHED */
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate
465eb1a3463STruong Nguyen static int
my_ct_name(char * out,size_t len)466eb1a3463STruong Nguyen my_ct_name(char *out, size_t len)
467eb1a3463STruong Nguyen {
468eb1a3463STruong Nguyen ct_stathdl_t st;
469eb1a3463STruong Nguyen char *ct_fmri;
470eb1a3463STruong Nguyen ctid_t ct;
471eb1a3463STruong Nguyen int fd, errno, ret;
472eb1a3463STruong Nguyen
473eb1a3463STruong Nguyen if ((ct = getctid()) == -1)
474eb1a3463STruong Nguyen uu_die(gettext("Could not get contract id for process"));
475eb1a3463STruong Nguyen
476eb1a3463STruong Nguyen fd = contract_open(ct, "process", "status", O_RDONLY);
477eb1a3463STruong Nguyen
478eb1a3463STruong Nguyen if ((errno = ct_status_read(fd, CTD_ALL, &st)) != 0)
479eb1a3463STruong Nguyen uu_warn(gettext("Could not read status of contract "
480eb1a3463STruong Nguyen "%ld: %s.\n"), ct, strerror(errno));
481eb1a3463STruong Nguyen
482eb1a3463STruong Nguyen if ((errno = ct_pr_status_get_svc_fmri(st, &ct_fmri)) != 0)
483eb1a3463STruong Nguyen uu_warn(gettext("Could not get svc_fmri for contract "
484eb1a3463STruong Nguyen "%ld: %s.\n"), ct, strerror(errno));
485eb1a3463STruong Nguyen
486eb1a3463STruong Nguyen ret = strlcpy(out, ct_fmri, len);
487eb1a3463STruong Nguyen
488eb1a3463STruong Nguyen ct_status_free(st);
489eb1a3463STruong Nguyen (void) close(fd);
490eb1a3463STruong Nguyen
491eb1a3463STruong Nguyen return (ret);
492eb1a3463STruong Nguyen }
493eb1a3463STruong Nguyen
494eb1a3463STruong Nguyen /*
495eb1a3463STruong Nguyen * Set auxiliary_tty and auxiliary_fmri properties in restarter_actions pg to
496eb1a3463STruong Nguyen * communicate whether the action is requested from a tty and the fmri of the
497eb1a3463STruong Nguyen * responsible process.
498e8f5b3f5STruong Nguyen *
499e8f5b3f5STruong Nguyen * Returns 0, EPERM, or EROFS
500eb1a3463STruong Nguyen */
501eb1a3463STruong Nguyen static int
restarter_setup(const char * fmri,const scf_instance_t * inst)502eb1a3463STruong Nguyen restarter_setup(const char *fmri, const scf_instance_t *inst)
503eb1a3463STruong Nguyen {
504eb1a3463STruong Nguyen boolean_t b = B_FALSE;
505eb1a3463STruong Nguyen scf_propertygroup_t *pg = NULL;
506e8f5b3f5STruong Nguyen int ret = 0;
507eb1a3463STruong Nguyen
508eb1a3463STruong Nguyen if ((pg = scf_pg_create(h)) == NULL)
509eb1a3463STruong Nguyen scfdie();
510eb1a3463STruong Nguyen
511eb1a3463STruong Nguyen if (pg_get_or_add(inst, SCF_PG_RESTARTER_ACTIONS,
512eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
513e8f5b3f5STruong Nguyen pg) == EPERM) {
514e8f5b3f5STruong Nguyen if (!verbose)
515e8f5b3f5STruong Nguyen uu_warn(emsg_permission_denied, fmri);
516e8f5b3f5STruong Nguyen else
517e8f5b3f5STruong Nguyen uu_warn(emsg_create_pg_perm_denied, fmri,
518e8f5b3f5STruong Nguyen SCF_PG_RESTARTER_ACTIONS);
519e8f5b3f5STruong Nguyen
520e8f5b3f5STruong Nguyen ret = EPERM;
521e8f5b3f5STruong Nguyen goto out;
522e8f5b3f5STruong Nguyen }
523eb1a3463STruong Nguyen
524eb1a3463STruong Nguyen /* Set auxiliary_tty property */
525eb1a3463STruong Nguyen if (isatty(STDIN_FILENO))
526eb1a3463STruong Nguyen b = B_TRUE;
527eb1a3463STruong Nguyen
528eb1a3463STruong Nguyen /* Create and set state to disabled */
529eb1a3463STruong Nguyen switch (set_bool_prop(pg, SCF_PROPERTY_AUX_TTY, b) != 0) {
530eb1a3463STruong Nguyen case 0:
531eb1a3463STruong Nguyen break;
532eb1a3463STruong Nguyen
533eb1a3463STruong Nguyen case EPERM:
534e8f5b3f5STruong Nguyen if (!verbose)
535e8f5b3f5STruong Nguyen uu_warn(emsg_permission_denied, fmri);
536e8f5b3f5STruong Nguyen else
537e8f5b3f5STruong Nguyen uu_warn(emsg_prop_perm_denied, fmri,
538e8f5b3f5STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_TTY);
539e8f5b3f5STruong Nguyen
540e8f5b3f5STruong Nguyen ret = EPERM;
541e8f5b3f5STruong Nguyen goto out;
542e8f5b3f5STruong Nguyen /* NOTREACHED */
543eb1a3463STruong Nguyen
544eb1a3463STruong Nguyen case EROFS:
545e8f5b3f5STruong Nguyen /* Shouldn't happen, but it can. */
546e8f5b3f5STruong Nguyen if (!verbose)
547e8f5b3f5STruong Nguyen uu_warn(gettext("%s: Repository read-only.\n"), fmri);
548e8f5b3f5STruong Nguyen else
549eb1a3463STruong Nguyen uu_warn(gettext("%s: Could not set %s/%s "
550eb1a3463STruong Nguyen "(repository read-only).\n"), fmri,
551eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_TTY);
552e8f5b3f5STruong Nguyen
553e8f5b3f5STruong Nguyen ret = EROFS;
554e8f5b3f5STruong Nguyen goto out;
555e8f5b3f5STruong Nguyen /* NOTREACHED */
556eb1a3463STruong Nguyen
557eb1a3463STruong Nguyen default:
558eb1a3463STruong Nguyen scfdie();
559eb1a3463STruong Nguyen }
560eb1a3463STruong Nguyen
561eb1a3463STruong Nguyen if (my_ct_name(scratch_fmri, max_scf_fmri_sz) > 0) {
562eb1a3463STruong Nguyen set_astring_prop(fmri, SCF_PG_RESTARTER_ACTIONS,
563eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE,
564eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_FLAGS,
565eb1a3463STruong Nguyen SCF_PROPERTY_AUX_FMRI, scratch_fmri);
566eb1a3463STruong Nguyen } else {
567eb1a3463STruong Nguyen uu_warn(gettext("%s: Could not set %s/%s: "
568eb1a3463STruong Nguyen "my_ct_name failed.\n"), fmri,
569eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_FMRI);
570eb1a3463STruong Nguyen }
571eb1a3463STruong Nguyen
572e8f5b3f5STruong Nguyen out:
573eb1a3463STruong Nguyen scf_pg_destroy(pg);
574e8f5b3f5STruong Nguyen return (ret);
575eb1a3463STruong Nguyen }
576eb1a3463STruong Nguyen
5777c478bd9Sstevel@tonic-gate /*
5787c478bd9Sstevel@tonic-gate * Enable or disable inst, per enable. If temp is true, set
5797c478bd9Sstevel@tonic-gate * general_ovr/enabled. Otherwise set general/enabled and delete
5807c478bd9Sstevel@tonic-gate * general_ovr/enabled if it exists (order is important here: we don't want the
5817c478bd9Sstevel@tonic-gate * enabled status to glitch).
5827c478bd9Sstevel@tonic-gate */
5837c478bd9Sstevel@tonic-gate static void
set_inst_enabled(const char * fmri,scf_instance_t * inst,boolean_t temp,boolean_t enable)5847c478bd9Sstevel@tonic-gate set_inst_enabled(const char *fmri, scf_instance_t *inst, boolean_t temp,
5857c478bd9Sstevel@tonic-gate boolean_t enable)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg;
5887c478bd9Sstevel@tonic-gate uint8_t b;
5897c478bd9Sstevel@tonic-gate const char *pgname = NULL; /* For emsg_pg_perm_denied */
5907c478bd9Sstevel@tonic-gate int r;
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate pg = scf_pg_create(h);
5937c478bd9Sstevel@tonic-gate if (pg == NULL)
5947c478bd9Sstevel@tonic-gate scfdie();
5957c478bd9Sstevel@tonic-gate
596eb1a3463STruong Nguyen if (restarter_setup(fmri, inst))
597e8f5b3f5STruong Nguyen goto out;
598eb1a3463STruong Nguyen
599fee38f6fStn143363 /*
600fee38f6fStn143363 * An instance's configuration is incomplete if general/enabled
601fee38f6fStn143363 * doesn't exist. Create both the property group and property
602fee38f6fStn143363 * here if they don't exist.
603fee38f6fStn143363 */
604fee38f6fStn143363 pgname = SCF_PG_GENERAL;
605fee38f6fStn143363 if (pg_get_or_add(inst, pgname, SCF_PG_GENERAL_TYPE,
606fee38f6fStn143363 SCF_PG_GENERAL_FLAGS, pg) != 0)
607fee38f6fStn143363 goto eperm;
608fee38f6fStn143363
609fee38f6fStn143363 if (get_bool_prop(pg, SCF_PROPERTY_ENABLED, &b) != 0) {
610fee38f6fStn143363 /* Create and set state to disabled */
611fee38f6fStn143363 switch (set_bool_prop(pg, SCF_PROPERTY_ENABLED, B_FALSE) != 0) {
612fee38f6fStn143363 case 0:
613fee38f6fStn143363 break;
614fee38f6fStn143363
615fee38f6fStn143363 case EPERM:
616fee38f6fStn143363 goto eperm;
617fee38f6fStn143363
618fee38f6fStn143363 case EROFS:
619fee38f6fStn143363 /* Shouldn't happen, but it can. */
620fee38f6fStn143363 if (!verbose)
621fee38f6fStn143363 uu_warn(gettext("%s: Repository read-only.\n"),
622fee38f6fStn143363 fmri);
623fee38f6fStn143363 else
624fee38f6fStn143363 uu_warn(gettext("%s: Could not set %s/%s "
625fee38f6fStn143363 "(repository read-only).\n"), fmri,
626fee38f6fStn143363 SCF_PG_GENERAL, SCF_PROPERTY_ENABLED);
627fee38f6fStn143363 goto out;
628fee38f6fStn143363
629fee38f6fStn143363 default:
630fee38f6fStn143363 assert(0);
631fee38f6fStn143363 abort();
632fee38f6fStn143363 }
633fee38f6fStn143363 }
634fee38f6fStn143363
6357c478bd9Sstevel@tonic-gate if (temp) {
6367c478bd9Sstevel@tonic-gate /* Set general_ovr/enabled */
6377c478bd9Sstevel@tonic-gate pgname = SCF_PG_GENERAL_OVR;
6387c478bd9Sstevel@tonic-gate if (pg_get_or_add(inst, pgname, SCF_PG_GENERAL_OVR_TYPE,
6397c478bd9Sstevel@tonic-gate SCF_PG_GENERAL_OVR_FLAGS, pg) != 0)
6407c478bd9Sstevel@tonic-gate goto eperm;
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate switch (set_bool_prop(pg, SCF_PROPERTY_ENABLED, enable) != 0) {
6437c478bd9Sstevel@tonic-gate case 0:
6447c478bd9Sstevel@tonic-gate break;
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate case EPERM:
6477c478bd9Sstevel@tonic-gate goto eperm;
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate case EROFS:
6507c478bd9Sstevel@tonic-gate /* Shouldn't happen, but it can. */
6517c478bd9Sstevel@tonic-gate if (!verbose)
6527c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Repository read-only.\n"),
6537c478bd9Sstevel@tonic-gate fmri);
6547c478bd9Sstevel@tonic-gate else
6557c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Could not set %s/%s "
6567c478bd9Sstevel@tonic-gate "(repository read-only).\n"), fmri,
6577c478bd9Sstevel@tonic-gate SCF_PG_GENERAL_OVR, SCF_PROPERTY_ENABLED);
6587c478bd9Sstevel@tonic-gate goto out;
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate default:
6617c478bd9Sstevel@tonic-gate assert(0);
6627c478bd9Sstevel@tonic-gate abort();
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate if (verbose)
6667c478bd9Sstevel@tonic-gate (void) printf(enable ?
6677c478bd9Sstevel@tonic-gate gettext("%s temporarily enabled.\n") :
6687c478bd9Sstevel@tonic-gate gettext("%s temporarily disabled.\n"), fmri);
6697c478bd9Sstevel@tonic-gate } else {
6707c478bd9Sstevel@tonic-gate again:
671fee38f6fStn143363 /*
672fee38f6fStn143363 * Both pg and property should exist since we created
673fee38f6fStn143363 * them earlier. However, there's still a chance that
674fee38f6fStn143363 * someone may have deleted the property out from under
675fee38f6fStn143363 * us.
676fee38f6fStn143363 */
6777c478bd9Sstevel@tonic-gate if (pg_get_or_add(inst, pgname, SCF_PG_GENERAL_TYPE,
6787c478bd9Sstevel@tonic-gate SCF_PG_GENERAL_FLAGS, pg) != 0)
6797c478bd9Sstevel@tonic-gate goto eperm;
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate switch (set_bool_prop(pg, SCF_PROPERTY_ENABLED, enable)) {
6827c478bd9Sstevel@tonic-gate case 0:
6837c478bd9Sstevel@tonic-gate break;
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate case EPERM:
6867c478bd9Sstevel@tonic-gate goto eperm;
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate case EROFS:
6897c478bd9Sstevel@tonic-gate /*
6907c478bd9Sstevel@tonic-gate * If general/enabled is already set the way we want,
6917c478bd9Sstevel@tonic-gate * proceed.
6927c478bd9Sstevel@tonic-gate */
6937c478bd9Sstevel@tonic-gate switch (get_bool_prop(pg, SCF_PROPERTY_ENABLED, &b)) {
6947c478bd9Sstevel@tonic-gate case 0:
6957c478bd9Sstevel@tonic-gate if ((b != 0) == (enable != B_FALSE))
6967c478bd9Sstevel@tonic-gate break;
6977c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate case ENOENT:
7007c478bd9Sstevel@tonic-gate case EINVAL:
7017c478bd9Sstevel@tonic-gate case E2BIG:
7027c478bd9Sstevel@tonic-gate if (!verbose)
7037c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Repository "
7047c478bd9Sstevel@tonic-gate "read-only.\n"), fmri);
7057c478bd9Sstevel@tonic-gate else
7067c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Could not set "
7077c478bd9Sstevel@tonic-gate "%s/%s (repository read-only).\n"),
7087c478bd9Sstevel@tonic-gate fmri, SCF_PG_GENERAL,
7097c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENABLED);
7107c478bd9Sstevel@tonic-gate goto out;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate case ECANCELED:
7137c478bd9Sstevel@tonic-gate goto again;
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate default:
7167c478bd9Sstevel@tonic-gate assert(0);
7177c478bd9Sstevel@tonic-gate abort();
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate break;
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate default:
7227c478bd9Sstevel@tonic-gate assert(0);
7237c478bd9Sstevel@tonic-gate abort();
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate pgname = SCF_PG_GENERAL_OVR;
727eb1a3463STruong Nguyen r = scf_instance_delete_prop(inst, pgname,
728eb1a3463STruong Nguyen SCF_PROPERTY_ENABLED);
7297c478bd9Sstevel@tonic-gate switch (r) {
7307c478bd9Sstevel@tonic-gate case 0:
7317c478bd9Sstevel@tonic-gate break;
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate case ECANCELED:
7347c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri);
7357c478bd9Sstevel@tonic-gate goto out;
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate case EPERM:
7387c478bd9Sstevel@tonic-gate goto eperm;
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate case EACCES:
7417c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s "
7427c478bd9Sstevel@tonic-gate "property of %s: backend access denied.\n"),
7437c478bd9Sstevel@tonic-gate pgname, SCF_PROPERTY_ENABLED, fmri);
7447c478bd9Sstevel@tonic-gate goto out;
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate case EROFS:
7477c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s "
7487c478bd9Sstevel@tonic-gate "property of %s: backend is read-only.\n"),
7497c478bd9Sstevel@tonic-gate pgname, SCF_PROPERTY_ENABLED, fmri);
7507c478bd9Sstevel@tonic-gate goto out;
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate default:
753eb1a3463STruong Nguyen bad_error("scf_instance_delete_prop", r);
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate if (verbose)
7577c478bd9Sstevel@tonic-gate (void) printf(enable ? gettext("%s enabled.\n") :
7587c478bd9Sstevel@tonic-gate gettext("%s disabled.\n"), fmri);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
7627c478bd9Sstevel@tonic-gate return;
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate eperm:
7657c478bd9Sstevel@tonic-gate assert(pgname != NULL);
7667c478bd9Sstevel@tonic-gate if (!verbose)
7677c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
7687c478bd9Sstevel@tonic-gate else
7697c478bd9Sstevel@tonic-gate uu_warn(emsg_pg_perm_denied, fmri, pgname);
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate out:
7727c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
7737c478bd9Sstevel@tonic-gate exit_status = 1;
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate /*
7777c478bd9Sstevel@tonic-gate * Set inst to the instance which corresponds to fmri. If fmri identifies
7787c478bd9Sstevel@tonic-gate * a service with a single instance, get that instance.
7797c478bd9Sstevel@tonic-gate *
7807c478bd9Sstevel@tonic-gate * Fails with
7817c478bd9Sstevel@tonic-gate * ENOTSUP - fmri has an unsupported scheme
7827c478bd9Sstevel@tonic-gate * EINVAL - fmri is invalid
7837c478bd9Sstevel@tonic-gate * ENOTDIR - fmri does not identify a service or instance
7847c478bd9Sstevel@tonic-gate * ENOENT - could not locate instance
7857c478bd9Sstevel@tonic-gate * E2BIG - fmri is a service with multiple instances (warning not printed)
7867c478bd9Sstevel@tonic-gate */
7877c478bd9Sstevel@tonic-gate static int
get_inst_mult(const char * fmri,scf_instance_t * inst)7887c478bd9Sstevel@tonic-gate get_inst_mult(const char *fmri, scf_instance_t *inst)
7897c478bd9Sstevel@tonic-gate {
7907c478bd9Sstevel@tonic-gate char *cfmri;
7917c478bd9Sstevel@tonic-gate const char *svc_name, *inst_name, *pg_name;
7927c478bd9Sstevel@tonic-gate scf_service_t *svc;
7937c478bd9Sstevel@tonic-gate scf_instance_t *inst2;
7947c478bd9Sstevel@tonic-gate scf_iter_t *iter;
7957c478bd9Sstevel@tonic-gate int ret;
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate if (strncmp(fmri, "lrc:", sizeof ("lrc:") - 1) == 0) {
7987c478bd9Sstevel@tonic-gate uu_warn(gettext("FMRI \"%s\" is a legacy service.\n"), fmri);
7997c478bd9Sstevel@tonic-gate exit_status = 1;
8007c478bd9Sstevel@tonic-gate return (ENOTSUP);
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate cfmri = strdup(fmri);
8047c478bd9Sstevel@tonic-gate if (cfmri == NULL)
8057c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(cfmri, NULL, &svc_name, &inst_name, &pg_name,
8087c478bd9Sstevel@tonic-gate NULL) != SCF_SUCCESS) {
8097c478bd9Sstevel@tonic-gate free(cfmri);
8107c478bd9Sstevel@tonic-gate uu_warn(gettext("FMRI \"%s\" is invalid.\n"), fmri);
8117c478bd9Sstevel@tonic-gate exit_status = 1;
8127c478bd9Sstevel@tonic-gate return (EINVAL);
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate free(cfmri);
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate if (svc_name == NULL || pg_name != NULL) {
8187c478bd9Sstevel@tonic-gate uu_warn(gettext(
8197c478bd9Sstevel@tonic-gate "FMRI \"%s\" does not designate a service or instance.\n"),
8207c478bd9Sstevel@tonic-gate fmri);
8217c478bd9Sstevel@tonic-gate exit_status = 1;
8227c478bd9Sstevel@tonic-gate return (ENOTDIR);
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate
8257c478bd9Sstevel@tonic-gate if (inst_name != NULL) {
8267c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL,
8277c478bd9Sstevel@tonic-gate NULL, SCF_DECODE_FMRI_EXACT) == 0)
8287c478bd9Sstevel@tonic-gate return (0);
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
8317c478bd9Sstevel@tonic-gate scfdie();
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate uu_warn(gettext("No such instance \"%s\".\n"), fmri);
8347c478bd9Sstevel@tonic-gate exit_status = 1;
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate return (ENOENT);
8377c478bd9Sstevel@tonic-gate }
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate if ((svc = scf_service_create(h)) == NULL ||
8407c478bd9Sstevel@tonic-gate (inst2 = scf_instance_create(h)) == NULL ||
8417c478bd9Sstevel@tonic-gate (iter = scf_iter_create(h)) == NULL)
8427c478bd9Sstevel@tonic-gate scfdie();
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, fmri, NULL, svc, NULL, NULL, NULL,
8457c478bd9Sstevel@tonic-gate SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) {
8467c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
8477c478bd9Sstevel@tonic-gate scfdie();
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri);
8507c478bd9Sstevel@tonic-gate exit_status = 1;
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate ret = ENOENT;
8537c478bd9Sstevel@tonic-gate goto out;
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate /* If the service has only one child, use it. */
8577c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iter, svc) != SCF_SUCCESS)
8587c478bd9Sstevel@tonic-gate scfdie();
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate ret = scf_iter_next_instance(iter, inst);
8617c478bd9Sstevel@tonic-gate if (ret < 0)
8627c478bd9Sstevel@tonic-gate scfdie();
8637c478bd9Sstevel@tonic-gate if (ret != 1) {
8647c478bd9Sstevel@tonic-gate uu_warn(gettext("Service \"%s\" has no instances.\n"),
8657c478bd9Sstevel@tonic-gate fmri);
8667c478bd9Sstevel@tonic-gate exit_status = 1;
8677c478bd9Sstevel@tonic-gate ret = ENOENT;
8687c478bd9Sstevel@tonic-gate goto out;
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate ret = scf_iter_next_instance(iter, inst2);
8727c478bd9Sstevel@tonic-gate if (ret < 0)
8737c478bd9Sstevel@tonic-gate scfdie();
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate if (ret != 0) {
8767c478bd9Sstevel@tonic-gate ret = E2BIG;
8777c478bd9Sstevel@tonic-gate goto out;
8787c478bd9Sstevel@tonic-gate }
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate ret = 0;
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate out:
8837c478bd9Sstevel@tonic-gate scf_iter_destroy(iter);
8847c478bd9Sstevel@tonic-gate scf_instance_destroy(inst2);
8857c478bd9Sstevel@tonic-gate scf_service_destroy(svc);
8867c478bd9Sstevel@tonic-gate return (ret);
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate /*
8907c478bd9Sstevel@tonic-gate * Same as get_inst_mult(), but on E2BIG prints a warning and returns ENOENT.
8917c478bd9Sstevel@tonic-gate */
8927c478bd9Sstevel@tonic-gate static int
get_inst(const char * fmri,scf_instance_t * inst)8937c478bd9Sstevel@tonic-gate get_inst(const char *fmri, scf_instance_t *inst)
8947c478bd9Sstevel@tonic-gate {
8957c478bd9Sstevel@tonic-gate int r;
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate r = get_inst_mult(fmri, inst);
8987c478bd9Sstevel@tonic-gate if (r != E2BIG)
8997c478bd9Sstevel@tonic-gate return (r);
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate uu_warn(gettext("operation on service %s is ambiguous; "
9027c478bd9Sstevel@tonic-gate "instance specification needed.\n"), fmri);
9037c478bd9Sstevel@tonic-gate return (ENOENT);
9047c478bd9Sstevel@tonic-gate }
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate static char *
inst_get_fmri(const scf_instance_t * inst)9077c478bd9Sstevel@tonic-gate inst_get_fmri(const scf_instance_t *inst)
9087c478bd9Sstevel@tonic-gate {
9097c478bd9Sstevel@tonic-gate ssize_t sz;
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate sz = scf_instance_to_fmri(inst, scratch_fmri, max_scf_fmri_sz);
9127c478bd9Sstevel@tonic-gate if (sz < 0)
9137c478bd9Sstevel@tonic-gate scfdie();
9147c478bd9Sstevel@tonic-gate if (sz >= max_scf_fmri_sz)
9157c478bd9Sstevel@tonic-gate uu_die(gettext("scf_instance_to_fmri() returned unexpectedly "
9167c478bd9Sstevel@tonic-gate "long value.\n"));
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate return (scratch_fmri);
9197c478bd9Sstevel@tonic-gate }
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate static ssize_t
dep_get_astring(const char * fmri,const char * pgname,const scf_propertygroup_t * pg,const char * propname,scf_property_t * prop,scf_value_t * v,char * buf,size_t bufsz)9227c478bd9Sstevel@tonic-gate dep_get_astring(const char *fmri, const char *pgname,
9237c478bd9Sstevel@tonic-gate const scf_propertygroup_t *pg, const char *propname, scf_property_t *prop,
9247c478bd9Sstevel@tonic-gate scf_value_t *v, char *buf, size_t bufsz)
9257c478bd9Sstevel@tonic-gate {
9267c478bd9Sstevel@tonic-gate ssize_t sz;
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate sz = get_astring_prop(pg, propname, prop, v, buf, bufsz);
9297c478bd9Sstevel@tonic-gate if (sz >= 0)
9307c478bd9Sstevel@tonic-gate return (sz);
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate switch (-sz) {
9337c478bd9Sstevel@tonic-gate case ENOENT:
9347c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s\" dependency "
9357c478bd9Sstevel@tonic-gate "lacks \"%s\" property.)\n"), fmri, pgname, propname);
9367c478bd9Sstevel@tonic-gate return (-1);
9377c478bd9Sstevel@tonic-gate
9387c478bd9Sstevel@tonic-gate case E2BIG:
9397c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" property "
9407c478bd9Sstevel@tonic-gate "is not single-valued.)\n"), fmri, pgname, propname);
9417c478bd9Sstevel@tonic-gate return (-1);
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate case EINVAL:
9447c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" property "
9457c478bd9Sstevel@tonic-gate "is not of astring type.)\n"), fmri, pgname, propname);
9467c478bd9Sstevel@tonic-gate return (-1);
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate default:
9497c478bd9Sstevel@tonic-gate assert(0);
9507c478bd9Sstevel@tonic-gate abort();
9517c478bd9Sstevel@tonic-gate /* NOTREACHED */
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate }
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate static boolean_t
multiple_instances(scf_iter_t * iter,scf_value_t * v,char * buf)9567c478bd9Sstevel@tonic-gate multiple_instances(scf_iter_t *iter, scf_value_t *v, char *buf)
9577c478bd9Sstevel@tonic-gate {
9587c478bd9Sstevel@tonic-gate int count = 0, r;
9597c478bd9Sstevel@tonic-gate boolean_t ret;
9607c478bd9Sstevel@tonic-gate scf_instance_t *inst;
9617c478bd9Sstevel@tonic-gate
9627c478bd9Sstevel@tonic-gate inst = scf_instance_create(h);
9637c478bd9Sstevel@tonic-gate if (inst == NULL)
9647c478bd9Sstevel@tonic-gate scfdie();
9657c478bd9Sstevel@tonic-gate
9667c478bd9Sstevel@tonic-gate for (;;) {
9677c478bd9Sstevel@tonic-gate r = scf_iter_next_value(iter, v);
9687c478bd9Sstevel@tonic-gate if (r == 0) {
9697c478bd9Sstevel@tonic-gate ret = B_FALSE;
9707c478bd9Sstevel@tonic-gate goto out;
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate if (r != 1)
9737c478bd9Sstevel@tonic-gate scfdie();
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate if (scf_value_get_astring(v, buf, max_scf_fmri_sz) < 0)
9767c478bd9Sstevel@tonic-gate scfdie();
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate switch (get_inst_mult(buf, inst)) {
9797c478bd9Sstevel@tonic-gate case 0:
9807c478bd9Sstevel@tonic-gate ++count;
9817c478bd9Sstevel@tonic-gate if (count > 1) {
9827c478bd9Sstevel@tonic-gate ret = B_TRUE;
9837c478bd9Sstevel@tonic-gate goto out;
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate break;
9867c478bd9Sstevel@tonic-gate
9877c478bd9Sstevel@tonic-gate case ENOTSUP:
9887c478bd9Sstevel@tonic-gate case EINVAL:
9897c478bd9Sstevel@tonic-gate case ENOTDIR:
9907c478bd9Sstevel@tonic-gate case ENOENT:
9917c478bd9Sstevel@tonic-gate continue;
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate case E2BIG:
9947c478bd9Sstevel@tonic-gate ret = B_TRUE;
9957c478bd9Sstevel@tonic-gate goto out;
9967c478bd9Sstevel@tonic-gate
9977c478bd9Sstevel@tonic-gate default:
9987c478bd9Sstevel@tonic-gate assert(0);
9997c478bd9Sstevel@tonic-gate abort();
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate
10037c478bd9Sstevel@tonic-gate out:
10047c478bd9Sstevel@tonic-gate scf_instance_destroy(inst);
10057c478bd9Sstevel@tonic-gate return (ret);
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate /*
10097c478bd9Sstevel@tonic-gate * Enable the service or instance identified by fmri and its dependencies,
10107c478bd9Sstevel@tonic-gate * recursively. Specifically, call get_inst(fmri), enable the result, and
10117c478bd9Sstevel@tonic-gate * recurse on its restarter and the dependencies. To avoid duplication of
10127c478bd9Sstevel@tonic-gate * effort or looping around a dependency cycle, each FMRI is entered into the
10137c478bd9Sstevel@tonic-gate * "visited" hash table. While recursing, the hash table entry is marked
10147c478bd9Sstevel@tonic-gate * "active", so that if we come upon it again, we know we've hit a cycle.
10157c478bd9Sstevel@tonic-gate * exclude_all and optional_all dependencies are ignored. require_any
10167c478bd9Sstevel@tonic-gate * dependencies are followed only if they comprise a single service; otherwise
10177c478bd9Sstevel@tonic-gate * the user is warned.
10187c478bd9Sstevel@tonic-gate *
10197c478bd9Sstevel@tonic-gate * fmri must point to a writable max_scf_fmri_sz buffer. Returns EINVAL if fmri
10207c478bd9Sstevel@tonic-gate * is invalid, E2BIG if fmri identifies a service with multiple instances, ELOOP
10217c478bd9Sstevel@tonic-gate * on cycle detection, or 0 on success.
10227c478bd9Sstevel@tonic-gate */
10237c478bd9Sstevel@tonic-gate static int
enable_fmri_rec(char * fmri,boolean_t temp)10247c478bd9Sstevel@tonic-gate enable_fmri_rec(char *fmri, boolean_t temp)
10257c478bd9Sstevel@tonic-gate {
10267c478bd9Sstevel@tonic-gate scf_instance_t *inst;
10277c478bd9Sstevel@tonic-gate scf_snapshot_t *snap;
10287c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg;
10297c478bd9Sstevel@tonic-gate scf_property_t *prop;
10307c478bd9Sstevel@tonic-gate scf_value_t *v;
10317c478bd9Sstevel@tonic-gate scf_iter_t *pg_iter, *val_iter;
10327c478bd9Sstevel@tonic-gate scf_type_t ty;
10337c478bd9Sstevel@tonic-gate char *buf, *pgname;
10347c478bd9Sstevel@tonic-gate ssize_t name_sz, len, sz;
10357c478bd9Sstevel@tonic-gate int ret;
10367c478bd9Sstevel@tonic-gate struct ht_elt *he;
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate len = scf_canonify_fmri(fmri, fmri, max_scf_fmri_sz);
10397c478bd9Sstevel@tonic-gate if (len < 0) {
10407c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_INVALID_ARGUMENT);
10417c478bd9Sstevel@tonic-gate return (EINVAL);
10427c478bd9Sstevel@tonic-gate }
10437c478bd9Sstevel@tonic-gate assert(len < max_scf_fmri_sz);
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate switch (visited_find_or_add(fmri, &he)) {
10467c478bd9Sstevel@tonic-gate case 0:
10477c478bd9Sstevel@tonic-gate he->active = B_TRUE;
10487c478bd9Sstevel@tonic-gate break;
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate case 1:
10517c478bd9Sstevel@tonic-gate return (he->active ? ELOOP : 0);
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate case -1:
10547c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate default:
10577c478bd9Sstevel@tonic-gate assert(0);
10587c478bd9Sstevel@tonic-gate abort();
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate inst = scf_instance_create(h);
10627c478bd9Sstevel@tonic-gate if (inst == NULL)
10637c478bd9Sstevel@tonic-gate scfdie();
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate switch (get_inst_mult(fmri, inst)) {
10667c478bd9Sstevel@tonic-gate case 0:
10677c478bd9Sstevel@tonic-gate break;
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate case E2BIG:
10707c478bd9Sstevel@tonic-gate he->active = B_FALSE;
10717c478bd9Sstevel@tonic-gate return (E2BIG);
10727c478bd9Sstevel@tonic-gate
10737c478bd9Sstevel@tonic-gate default:
10747c478bd9Sstevel@tonic-gate he->active = B_FALSE;
10757c478bd9Sstevel@tonic-gate return (0);
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate set_inst_enabled(fmri, inst, temp, B_TRUE);
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate if ((snap = scf_snapshot_create(h)) == NULL ||
10817c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL ||
10827c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL ||
10837c478bd9Sstevel@tonic-gate (v = scf_value_create(h)) == NULL ||
10847c478bd9Sstevel@tonic-gate (pg_iter = scf_iter_create(h)) == NULL ||
10857c478bd9Sstevel@tonic-gate (val_iter = scf_iter_create(h)) == NULL)
10867c478bd9Sstevel@tonic-gate scfdie();
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate buf = malloc(max_scf_fmri_sz);
10897c478bd9Sstevel@tonic-gate if (buf == NULL)
10907c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
10917c478bd9Sstevel@tonic-gate
10927c478bd9Sstevel@tonic-gate name_sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
10937c478bd9Sstevel@tonic-gate if (name_sz < 0)
10947c478bd9Sstevel@tonic-gate scfdie();
10957c478bd9Sstevel@tonic-gate ++name_sz;
10967c478bd9Sstevel@tonic-gate pgname = malloc(name_sz);
10977c478bd9Sstevel@tonic-gate if (pgname == NULL)
10987c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", snap) != 0) {
11017c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
11027c478bd9Sstevel@tonic-gate scfdie();
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap);
11057c478bd9Sstevel@tonic-gate snap = NULL;
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate /* Enable restarter */
11097c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_GENERAL, pg) != 0) {
11107c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
11117c478bd9Sstevel@tonic-gate scfdie();
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (lacks \"%s\" "
11147c478bd9Sstevel@tonic-gate "property group).\n"), fmri, SCF_PG_GENERAL);
11157c478bd9Sstevel@tonic-gate ret = 0;
11167c478bd9Sstevel@tonic-gate goto out;
11177c478bd9Sstevel@tonic-gate }
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate sz = get_astring_prop(pg, SCF_PROPERTY_RESTARTER, prop, v, buf,
11207c478bd9Sstevel@tonic-gate max_scf_fmri_sz);
11217c478bd9Sstevel@tonic-gate if (sz > max_scf_fmri_sz) {
11227c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (the value of "
11237c478bd9Sstevel@tonic-gate "\"%s/%s\" is too long).\n"), fmri, SCF_PG_GENERAL,
11247c478bd9Sstevel@tonic-gate SCF_PROPERTY_RESTARTER);
11257c478bd9Sstevel@tonic-gate ret = 0;
11267c478bd9Sstevel@tonic-gate goto out;
11277c478bd9Sstevel@tonic-gate } else if (sz >= 0) {
11287c478bd9Sstevel@tonic-gate switch (enable_fmri_rec(buf, temp)) {
11297c478bd9Sstevel@tonic-gate case 0:
11307c478bd9Sstevel@tonic-gate break;
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate case EINVAL:
11337c478bd9Sstevel@tonic-gate uu_warn(gettext("Restarter FMRI for \"%s\" is "
11347c478bd9Sstevel@tonic-gate "invalid.\n"), fmri);
11357c478bd9Sstevel@tonic-gate break;
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate case E2BIG:
11387c478bd9Sstevel@tonic-gate uu_warn(gettext("Restarter FMRI for \"%s\" identifies "
11397c478bd9Sstevel@tonic-gate "a service with multiple instances.\n"), fmri);
11407c478bd9Sstevel@tonic-gate break;
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate case ELOOP:
11437c478bd9Sstevel@tonic-gate ret = ELOOP;
11447c478bd9Sstevel@tonic-gate goto out;
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate default:
11477c478bd9Sstevel@tonic-gate assert(0);
11487c478bd9Sstevel@tonic-gate abort();
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate } else if (sz < 0) {
11517c478bd9Sstevel@tonic-gate switch (-sz) {
11527c478bd9Sstevel@tonic-gate case ENOENT:
11537c478bd9Sstevel@tonic-gate break;
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate case E2BIG:
11567c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" "
11577c478bd9Sstevel@tonic-gate "property is not single-valued).\n"), fmri,
11587c478bd9Sstevel@tonic-gate SCF_PG_GENERAL, SCF_PROPERTY_RESTARTER);
11597c478bd9Sstevel@tonic-gate ret = 0;
11607c478bd9Sstevel@tonic-gate goto out;
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate case EINVAL:
11637c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" "
11647c478bd9Sstevel@tonic-gate "property is not of astring type).\n"), fmri,
11657c478bd9Sstevel@tonic-gate SCF_PG_GENERAL, SCF_PROPERTY_RESTARTER);
11667c478bd9Sstevel@tonic-gate ret = 0;
11677c478bd9Sstevel@tonic-gate goto out;
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate default:
11707c478bd9Sstevel@tonic-gate assert(0);
11717c478bd9Sstevel@tonic-gate abort();
11727c478bd9Sstevel@tonic-gate }
11737c478bd9Sstevel@tonic-gate }
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(pg_iter, inst, snap,
11767c478bd9Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) == -1)
11777c478bd9Sstevel@tonic-gate scfdie();
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate while (scf_iter_next_pg(pg_iter, pg) > 0) {
11807c478bd9Sstevel@tonic-gate len = scf_pg_get_name(pg, pgname, name_sz);
11817c478bd9Sstevel@tonic-gate if (len < 0)
11827c478bd9Sstevel@tonic-gate scfdie();
11837c478bd9Sstevel@tonic-gate assert(len < name_sz);
11847c478bd9Sstevel@tonic-gate
11857c478bd9Sstevel@tonic-gate if (dep_get_astring(fmri, pgname, pg, SCF_PROPERTY_TYPE, prop,
11867c478bd9Sstevel@tonic-gate v, buf, max_scf_fmri_sz) < 0)
11877c478bd9Sstevel@tonic-gate continue;
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate if (strcmp(buf, "service") != 0)
11907c478bd9Sstevel@tonic-gate continue;
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate if (dep_get_astring(fmri, pgname, pg, SCF_PROPERTY_GROUPING,
11937c478bd9Sstevel@tonic-gate prop, v, buf, max_scf_fmri_sz) < 0)
11947c478bd9Sstevel@tonic-gate continue;
11957c478bd9Sstevel@tonic-gate
11967c478bd9Sstevel@tonic-gate if (strcmp(buf, SCF_DEP_EXCLUDE_ALL) == 0 ||
11977c478bd9Sstevel@tonic-gate strcmp(buf, SCF_DEP_OPTIONAL_ALL) == 0)
11987c478bd9Sstevel@tonic-gate continue;
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate if (strcmp(buf, SCF_DEP_REQUIRE_ALL) != 0 &&
12017c478bd9Sstevel@tonic-gate strcmp(buf, SCF_DEP_REQUIRE_ANY) != 0) {
12027c478bd9Sstevel@tonic-gate uu_warn(gettext("Dependency \"%s\" of \"%s\" has "
12037c478bd9Sstevel@tonic-gate "unknown type \"%s\".\n"), pgname, fmri, buf);
12047c478bd9Sstevel@tonic-gate continue;
12057c478bd9Sstevel@tonic-gate }
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, prop) ==
12087c478bd9Sstevel@tonic-gate -1) {
12097c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
12107c478bd9Sstevel@tonic-gate scfdie();
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s\" "
12137c478bd9Sstevel@tonic-gate "dependency lacks \"%s\" property.)\n"), fmri,
12147c478bd9Sstevel@tonic-gate pgname, SCF_PROPERTY_ENTITIES);
12157c478bd9Sstevel@tonic-gate continue;
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS)
12197c478bd9Sstevel@tonic-gate scfdie();
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_FMRI) {
12227c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (property "
12237c478bd9Sstevel@tonic-gate "\"%s/%s\" is not of fmri type).\n"), fmri, pgname,
12247c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENTITIES);
12257c478bd9Sstevel@tonic-gate continue;
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate if (scf_iter_property_values(val_iter, prop) == -1)
12297c478bd9Sstevel@tonic-gate scfdie();
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate if (strcmp(buf, SCF_DEP_REQUIRE_ANY) == 0) {
12327c478bd9Sstevel@tonic-gate if (multiple_instances(val_iter, v, buf)) {
12337c478bd9Sstevel@tonic-gate (void) printf(gettext("%s requires one of:\n"),
12347c478bd9Sstevel@tonic-gate fmri);
12357c478bd9Sstevel@tonic-gate
12367c478bd9Sstevel@tonic-gate if (scf_iter_property_values(val_iter, prop) !=
12377c478bd9Sstevel@tonic-gate 0)
12387c478bd9Sstevel@tonic-gate scfdie();
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate for (;;) {
12417c478bd9Sstevel@tonic-gate int r;
12427c478bd9Sstevel@tonic-gate
12437c478bd9Sstevel@tonic-gate r = scf_iter_next_value(val_iter, v);
12447c478bd9Sstevel@tonic-gate if (r == 0)
12457c478bd9Sstevel@tonic-gate break;
12467c478bd9Sstevel@tonic-gate if (r != 1)
12477c478bd9Sstevel@tonic-gate scfdie();
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate if (scf_value_get_astring(v, buf,
12507c478bd9Sstevel@tonic-gate max_scf_fmri_sz) < 0)
12517c478bd9Sstevel@tonic-gate scfdie();
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate (void) fputs(" ", stdout);
12547c478bd9Sstevel@tonic-gate (void) puts(buf);
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate continue;
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate /*
12617c478bd9Sstevel@tonic-gate * Since there's only one instance, we can enable it.
12627c478bd9Sstevel@tonic-gate * Reset val_iter and continue.
12637c478bd9Sstevel@tonic-gate */
12647c478bd9Sstevel@tonic-gate if (scf_iter_property_values(val_iter, prop) != 0)
12657c478bd9Sstevel@tonic-gate scfdie();
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate for (;;) {
12697c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(val_iter, v);
12707c478bd9Sstevel@tonic-gate if (ret == 0)
12717c478bd9Sstevel@tonic-gate break;
12727c478bd9Sstevel@tonic-gate if (ret != 1)
12737c478bd9Sstevel@tonic-gate scfdie();
12747c478bd9Sstevel@tonic-gate
12757c478bd9Sstevel@tonic-gate if (scf_value_get_astring(v, buf, max_scf_fmri_sz) ==
12767c478bd9Sstevel@tonic-gate -1)
12777c478bd9Sstevel@tonic-gate scfdie();
12787c478bd9Sstevel@tonic-gate
12797c478bd9Sstevel@tonic-gate switch (enable_fmri_rec(buf, temp)) {
12807c478bd9Sstevel@tonic-gate case 0:
12817c478bd9Sstevel@tonic-gate break;
12827c478bd9Sstevel@tonic-gate
12837c478bd9Sstevel@tonic-gate case EINVAL:
12847c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" dependency of \"%s\" "
12857c478bd9Sstevel@tonic-gate "has invalid FMRI \"%s\".\n"), pgname,
12867c478bd9Sstevel@tonic-gate fmri, buf);
12877c478bd9Sstevel@tonic-gate break;
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate case E2BIG:
12907c478bd9Sstevel@tonic-gate uu_warn(gettext("%s depends on %s, which has "
12917c478bd9Sstevel@tonic-gate "multiple instances.\n"), fmri, buf);
12927c478bd9Sstevel@tonic-gate break;
12937c478bd9Sstevel@tonic-gate
12947c478bd9Sstevel@tonic-gate case ELOOP:
12957c478bd9Sstevel@tonic-gate ret = ELOOP;
12967c478bd9Sstevel@tonic-gate goto out;
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate default:
12997c478bd9Sstevel@tonic-gate assert(0);
13007c478bd9Sstevel@tonic-gate abort();
13017c478bd9Sstevel@tonic-gate }
13027c478bd9Sstevel@tonic-gate }
13037c478bd9Sstevel@tonic-gate }
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate ret = 0;
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate out:
13087c478bd9Sstevel@tonic-gate he->active = B_FALSE;
13097c478bd9Sstevel@tonic-gate
13107c478bd9Sstevel@tonic-gate free(buf);
13117c478bd9Sstevel@tonic-gate free(pgname);
13127c478bd9Sstevel@tonic-gate
13137c478bd9Sstevel@tonic-gate (void) scf_value_destroy(v);
13147c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
13157c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
13167c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap);
13177c478bd9Sstevel@tonic-gate scf_iter_destroy(pg_iter);
13187c478bd9Sstevel@tonic-gate scf_iter_destroy(val_iter);
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate return (ret);
13217c478bd9Sstevel@tonic-gate }
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate /*
13247c478bd9Sstevel@tonic-gate * fmri here is only used for verbose messages.
13257c478bd9Sstevel@tonic-gate */
13267c478bd9Sstevel@tonic-gate static void
set_inst_action(const char * fmri,const scf_instance_t * inst,const char * action)13277c478bd9Sstevel@tonic-gate set_inst_action(const char *fmri, const scf_instance_t *inst,
13287c478bd9Sstevel@tonic-gate const char *action)
13297c478bd9Sstevel@tonic-gate {
13307c478bd9Sstevel@tonic-gate scf_transaction_t *tx;
13317c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ent;
13327c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg;
13337c478bd9Sstevel@tonic-gate scf_property_t *prop;
13347c478bd9Sstevel@tonic-gate scf_value_t *v;
13357c478bd9Sstevel@tonic-gate int ret;
13367c478bd9Sstevel@tonic-gate int64_t t;
13377c478bd9Sstevel@tonic-gate hrtime_t timestamp;
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate const char * const scf_pg_restarter_actions = SCF_PG_RESTARTER_ACTIONS;
13407c478bd9Sstevel@tonic-gate
13417c478bd9Sstevel@tonic-gate if ((pg = scf_pg_create(h)) == NULL ||
13427c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL ||
13437c478bd9Sstevel@tonic-gate (v = scf_value_create(h)) == NULL ||
13447c478bd9Sstevel@tonic-gate (tx = scf_transaction_create(h)) == NULL ||
13457c478bd9Sstevel@tonic-gate (ent = scf_entry_create(h)) == NULL)
13467c478bd9Sstevel@tonic-gate scfdie();
13477c478bd9Sstevel@tonic-gate
1348a97d4a16SDave Eddy if (restarter_setup(fmri, inst)) {
1349a97d4a16SDave Eddy exit_status = 1;
1350e8f5b3f5STruong Nguyen goto out;
1351a97d4a16SDave Eddy }
1352eb1a3463STruong Nguyen
13537c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, scf_pg_restarter_actions, pg) == -1) {
13547c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
13557c478bd9Sstevel@tonic-gate scfdie();
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate /* Try creating the restarter_actions property group. */
13587c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, scf_pg_restarter_actions,
13597c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_ACTIONS_TYPE,
13607c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_ACTIONS_FLAGS, pg) == -1) {
13617c478bd9Sstevel@tonic-gate switch (scf_error()) {
13627c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
13637c478bd9Sstevel@tonic-gate /* Someone must have added it. */
13647c478bd9Sstevel@tonic-gate break;
13657c478bd9Sstevel@tonic-gate
13667c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
13677c478bd9Sstevel@tonic-gate if (!verbose)
13687c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
13697c478bd9Sstevel@tonic-gate else
13707c478bd9Sstevel@tonic-gate uu_warn(emsg_create_pg_perm_denied,
13717c478bd9Sstevel@tonic-gate fmri, scf_pg_restarter_actions);
13727c478bd9Sstevel@tonic-gate goto out;
13737c478bd9Sstevel@tonic-gate
13747c478bd9Sstevel@tonic-gate default:
13757c478bd9Sstevel@tonic-gate scfdie();
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate }
13787c478bd9Sstevel@tonic-gate }
13797c478bd9Sstevel@tonic-gate
13807c478bd9Sstevel@tonic-gate /*
13817c478bd9Sstevel@tonic-gate * If we lose the transaction race and need to retry, there are 2
13827c478bd9Sstevel@tonic-gate * potential other winners:
13837c478bd9Sstevel@tonic-gate * - another process setting actions
13847c478bd9Sstevel@tonic-gate * - the restarter marking the action complete
13857c478bd9Sstevel@tonic-gate * Therefore, re-read the property every time through the loop before
13867c478bd9Sstevel@tonic-gate * making any decisions based on their values.
13877c478bd9Sstevel@tonic-gate */
13887c478bd9Sstevel@tonic-gate do {
13897c478bd9Sstevel@tonic-gate timestamp = gethrtime();
13907c478bd9Sstevel@tonic-gate
13917c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) == -1) {
13927c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
13937c478bd9Sstevel@tonic-gate scfdie();
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate if (!verbose)
13967c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
13977c478bd9Sstevel@tonic-gate else
13987c478bd9Sstevel@tonic-gate uu_warn(emsg_pg_perm_denied, fmri,
13997c478bd9Sstevel@tonic-gate scf_pg_restarter_actions);
14007c478bd9Sstevel@tonic-gate goto out;
14017c478bd9Sstevel@tonic-gate }
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, action, prop) == -1) {
14047c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
14057c478bd9Sstevel@tonic-gate scfdie();
14067c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent,
14077c478bd9Sstevel@tonic-gate action, SCF_TYPE_INTEGER) == -1)
14087c478bd9Sstevel@tonic-gate scfdie();
14097c478bd9Sstevel@tonic-gate goto action_set;
14107c478bd9Sstevel@tonic-gate } else {
14117c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent,
14127c478bd9Sstevel@tonic-gate action, SCF_TYPE_INTEGER) == -1)
14137c478bd9Sstevel@tonic-gate scfdie();
14147c478bd9Sstevel@tonic-gate }
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, v) == -1) {
14177c478bd9Sstevel@tonic-gate switch (scf_error()) {
14187c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED:
14197c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
14207c478bd9Sstevel@tonic-gate /* Misconfigured, so set anyway. */
14217c478bd9Sstevel@tonic-gate goto action_set;
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate default:
14247c478bd9Sstevel@tonic-gate scfdie();
14257c478bd9Sstevel@tonic-gate }
14267c478bd9Sstevel@tonic-gate } else {
14277c478bd9Sstevel@tonic-gate if (scf_value_get_integer(v, &t) == -1) {
14287c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_TYPE_MISMATCH);
14297c478bd9Sstevel@tonic-gate goto action_set;
14307c478bd9Sstevel@tonic-gate }
14317c478bd9Sstevel@tonic-gate if (t > timestamp)
14327c478bd9Sstevel@tonic-gate break;
14337c478bd9Sstevel@tonic-gate }
14347c478bd9Sstevel@tonic-gate
14357c478bd9Sstevel@tonic-gate action_set:
14367c478bd9Sstevel@tonic-gate scf_value_set_integer(v, timestamp);
14377c478bd9Sstevel@tonic-gate if (scf_entry_add_value(ent, v) == -1)
14387c478bd9Sstevel@tonic-gate scfdie();
14397c478bd9Sstevel@tonic-gate
14407c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(tx);
14417c478bd9Sstevel@tonic-gate if (ret == -1) {
14427c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
14437c478bd9Sstevel@tonic-gate scfdie();
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate if (!verbose)
14467c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
14477c478bd9Sstevel@tonic-gate else
14487c478bd9Sstevel@tonic-gate uu_warn(emsg_prop_perm_denied, fmri,
14497c478bd9Sstevel@tonic-gate scf_pg_restarter_actions, action);
14507c478bd9Sstevel@tonic-gate scf_transaction_reset(tx);
14517c478bd9Sstevel@tonic-gate goto out;
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate
14547c478bd9Sstevel@tonic-gate scf_transaction_reset(tx);
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate if (ret == 0) {
14577c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1)
14587c478bd9Sstevel@tonic-gate scfdie();
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate } while (ret == 0);
14617c478bd9Sstevel@tonic-gate
14627c478bd9Sstevel@tonic-gate if (verbose)
14637c478bd9Sstevel@tonic-gate (void) printf(gettext("Action %s set for %s.\n"), action, fmri);
14647c478bd9Sstevel@tonic-gate
14657c478bd9Sstevel@tonic-gate out:
14667c478bd9Sstevel@tonic-gate scf_value_destroy(v);
14677c478bd9Sstevel@tonic-gate scf_entry_destroy(ent);
14687c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx);
14697c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
14707c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
14717c478bd9Sstevel@tonic-gate }
14727c478bd9Sstevel@tonic-gate
14737c478bd9Sstevel@tonic-gate /*
14747c478bd9Sstevel@tonic-gate * Get the state of inst. state should point to a buffer of
14757c478bd9Sstevel@tonic-gate * MAX_SCF_STATE_STRING_SZ bytes. Returns 0 on success or -1 if
14767c478bd9Sstevel@tonic-gate * no restarter property group
14777c478bd9Sstevel@tonic-gate * no state property
14787c478bd9Sstevel@tonic-gate * state property is misconfigured (wrong type, not single-valued)
14797c478bd9Sstevel@tonic-gate * state value is too long
14807c478bd9Sstevel@tonic-gate * In these cases, fmri is used to print a warning.
14817c478bd9Sstevel@tonic-gate *
14827c478bd9Sstevel@tonic-gate * If pgp is non-NULL, a successful call to inst_get_state will store
14837c478bd9Sstevel@tonic-gate * the SCF_PG_RESTARTER property group in *pgp, and the caller will be
14847c478bd9Sstevel@tonic-gate * responsible for calling scf_pg_destroy on the property group.
14857c478bd9Sstevel@tonic-gate */
14867c478bd9Sstevel@tonic-gate int
inst_get_state(scf_instance_t * inst,char * state,const char * fmri,scf_propertygroup_t ** pgp)14877c478bd9Sstevel@tonic-gate inst_get_state(scf_instance_t *inst, char *state, const char *fmri,
14887c478bd9Sstevel@tonic-gate scf_propertygroup_t **pgp)
14897c478bd9Sstevel@tonic-gate {
14907c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg;
14917c478bd9Sstevel@tonic-gate scf_property_t *prop;
14927c478bd9Sstevel@tonic-gate scf_value_t *val;
14937c478bd9Sstevel@tonic-gate int ret = -1;
14947c478bd9Sstevel@tonic-gate ssize_t szret;
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate if ((pg = scf_pg_create(h)) == NULL ||
14977c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL ||
14987c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL)
14997c478bd9Sstevel@tonic-gate scfdie();
15007c478bd9Sstevel@tonic-gate
15017c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, pg) != SCF_SUCCESS) {
15027c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
15037c478bd9Sstevel@tonic-gate scfdie();
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (lacks \"%s\" property "
15067c478bd9Sstevel@tonic-gate "group).\n"), fmri ? fmri : inst_get_fmri(inst),
15077c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER);
15087c478bd9Sstevel@tonic-gate goto out;
15097c478bd9Sstevel@tonic-gate }
15107c478bd9Sstevel@tonic-gate
15117c478bd9Sstevel@tonic-gate szret = get_astring_prop(pg, SCF_PROPERTY_STATE, prop, val, state,
15127c478bd9Sstevel@tonic-gate MAX_SCF_STATE_STRING_SZ);
15137c478bd9Sstevel@tonic-gate if (szret < 0) {
15147c478bd9Sstevel@tonic-gate switch (-szret) {
15157c478bd9Sstevel@tonic-gate case ENOENT:
15167c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s\" property "
15177c478bd9Sstevel@tonic-gate "group lacks \"%s\" property).\n"),
15187c478bd9Sstevel@tonic-gate fmri ? fmri : inst_get_fmri(inst), SCF_PG_RESTARTER,
15197c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE);
15207c478bd9Sstevel@tonic-gate goto out;
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate case E2BIG:
15237c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s/%s\" "
15247c478bd9Sstevel@tonic-gate "property is not single-valued).\n"),
15257c478bd9Sstevel@tonic-gate fmri ? fmri : inst_get_fmri(inst), SCF_PG_RESTARTER,
15267c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE);
15277c478bd9Sstevel@tonic-gate goto out;
15287c478bd9Sstevel@tonic-gate
15297c478bd9Sstevel@tonic-gate case EINVAL:
15307c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s/%s\" "
15317c478bd9Sstevel@tonic-gate "property is not of type astring).\n"),
15327c478bd9Sstevel@tonic-gate fmri ? fmri : inst_get_fmri(inst), SCF_PG_RESTARTER,
15337c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE);
15347c478bd9Sstevel@tonic-gate goto out;
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate default:
15377c478bd9Sstevel@tonic-gate assert(0);
15387c478bd9Sstevel@tonic-gate abort();
15397c478bd9Sstevel@tonic-gate }
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate if (szret >= MAX_SCF_STATE_STRING_SZ) {
15427c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s/%s\" property value "
15437c478bd9Sstevel@tonic-gate "is too long).\n"), fmri ? fmri : inst_get_fmri(inst),
15447c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER, SCF_PROPERTY_STATE);
15457c478bd9Sstevel@tonic-gate goto out;
15467c478bd9Sstevel@tonic-gate }
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate ret = 0;
15497c478bd9Sstevel@tonic-gate if (pgp)
15507c478bd9Sstevel@tonic-gate *pgp = pg;
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate out:
15537c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val);
15547c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
15557c478bd9Sstevel@tonic-gate if (ret || pgp == NULL)
15567c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
15577c478bd9Sstevel@tonic-gate return (ret);
15587c478bd9Sstevel@tonic-gate }
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate static void
set_astring_prop(const char * fmri,const char * pgname,const char * pgtype,uint32_t pgflags,const char * propname,const char * str)15617c478bd9Sstevel@tonic-gate set_astring_prop(const char *fmri, const char *pgname, const char *pgtype,
15627c478bd9Sstevel@tonic-gate uint32_t pgflags, const char *propname, const char *str)
15637c478bd9Sstevel@tonic-gate {
15647c478bd9Sstevel@tonic-gate scf_instance_t *inst;
15657c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg;
15667c478bd9Sstevel@tonic-gate scf_property_t *prop;
15677c478bd9Sstevel@tonic-gate scf_value_t *val;
15687c478bd9Sstevel@tonic-gate scf_transaction_t *tx;
15697c478bd9Sstevel@tonic-gate scf_transaction_entry_t *txent;
15707c478bd9Sstevel@tonic-gate int ret;
15717c478bd9Sstevel@tonic-gate
15727c478bd9Sstevel@tonic-gate inst = scf_instance_create(h);
15737c478bd9Sstevel@tonic-gate if (inst == NULL)
15747c478bd9Sstevel@tonic-gate scfdie();
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate if (get_inst(fmri, inst) != 0)
15777c478bd9Sstevel@tonic-gate return;
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate if ((pg = scf_pg_create(h)) == NULL ||
15807c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL ||
15817c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL ||
15827c478bd9Sstevel@tonic-gate (tx = scf_transaction_create(h)) == NULL ||
15837c478bd9Sstevel@tonic-gate (txent = scf_entry_create(h)) == NULL)
15847c478bd9Sstevel@tonic-gate scfdie();
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) != SCF_SUCCESS) {
15877c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
15887c478bd9Sstevel@tonic-gate scfdie();
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, pgname, pgtype, pgflags, pg) !=
15917c478bd9Sstevel@tonic-gate SCF_SUCCESS) {
15927c478bd9Sstevel@tonic-gate switch (scf_error()) {
15937c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
15947c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) !=
15957c478bd9Sstevel@tonic-gate SCF_SUCCESS) {
15967c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
15977c478bd9Sstevel@tonic-gate scfdie();
15987c478bd9Sstevel@tonic-gate
15997c478bd9Sstevel@tonic-gate uu_warn(gettext("Repository write "
16007c478bd9Sstevel@tonic-gate "contention.\n"));
16017c478bd9Sstevel@tonic-gate goto out;
16027c478bd9Sstevel@tonic-gate }
16037c478bd9Sstevel@tonic-gate break;
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
16067c478bd9Sstevel@tonic-gate if (!verbose)
16077c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
16087c478bd9Sstevel@tonic-gate else
16097c478bd9Sstevel@tonic-gate uu_warn(emsg_create_pg_perm_denied,
16107c478bd9Sstevel@tonic-gate fmri, pgname);
16117c478bd9Sstevel@tonic-gate goto out;
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate default:
16147c478bd9Sstevel@tonic-gate scfdie();
16157c478bd9Sstevel@tonic-gate }
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate }
16187c478bd9Sstevel@tonic-gate
16197c478bd9Sstevel@tonic-gate do {
16207c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) != SCF_SUCCESS) {
16217c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
16227c478bd9Sstevel@tonic-gate scfdie();
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate if (!verbose)
16257c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
16267c478bd9Sstevel@tonic-gate else
16277c478bd9Sstevel@tonic-gate uu_warn(emsg_pg_perm_denied, fmri, pgname);
16287c478bd9Sstevel@tonic-gate goto out;
16297c478bd9Sstevel@tonic-gate }
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, txent, propname,
16327c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING) != 0) {
16337c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND)
16347c478bd9Sstevel@tonic-gate scfdie();
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, txent, propname,
16377c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING) != 0)
16387c478bd9Sstevel@tonic-gate scfdie();
16397c478bd9Sstevel@tonic-gate }
16407c478bd9Sstevel@tonic-gate
16417c478bd9Sstevel@tonic-gate if (scf_value_set_astring(val, str) != SCF_SUCCESS)
16427c478bd9Sstevel@tonic-gate scfdie();
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate if (scf_entry_add_value(txent, val) != SCF_SUCCESS)
16457c478bd9Sstevel@tonic-gate scfdie();
16467c478bd9Sstevel@tonic-gate
16477c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(tx);
16487c478bd9Sstevel@tonic-gate if (ret == -1) {
16497c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
16507c478bd9Sstevel@tonic-gate scfdie();
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate if (!verbose)
16537c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri);
16547c478bd9Sstevel@tonic-gate else
16557c478bd9Sstevel@tonic-gate uu_warn(emsg_prop_perm_denied, fmri, pgname,
16567c478bd9Sstevel@tonic-gate propname);
16577c478bd9Sstevel@tonic-gate goto out;
16587c478bd9Sstevel@tonic-gate }
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate if (ret == 0) {
16617c478bd9Sstevel@tonic-gate scf_transaction_reset(tx);
16627c478bd9Sstevel@tonic-gate
1663bc9767f9Stn143363 if (scf_pg_update(pg) == -1)
16647c478bd9Sstevel@tonic-gate scfdie();
16657c478bd9Sstevel@tonic-gate }
16667c478bd9Sstevel@tonic-gate } while (ret == 0);
16677c478bd9Sstevel@tonic-gate
16687c478bd9Sstevel@tonic-gate out:
16697c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx);
16707c478bd9Sstevel@tonic-gate scf_entry_destroy(txent);
16717c478bd9Sstevel@tonic-gate scf_value_destroy(val);
16727c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
16737c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
16747c478bd9Sstevel@tonic-gate scf_instance_destroy(inst);
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate
16787c478bd9Sstevel@tonic-gate /*
16797c478bd9Sstevel@tonic-gate * Flags to control enable and disable actions.
16807c478bd9Sstevel@tonic-gate */
16817c478bd9Sstevel@tonic-gate #define SET_ENABLED 0x1
16827c478bd9Sstevel@tonic-gate #define SET_TEMPORARY 0x2
16837c478bd9Sstevel@tonic-gate #define SET_RECURSIVE 0x4
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate static int
set_fmri_enabled(void * data,scf_walkinfo_t * wip)16867c478bd9Sstevel@tonic-gate set_fmri_enabled(void *data, scf_walkinfo_t *wip)
16877c478bd9Sstevel@tonic-gate {
16887c478bd9Sstevel@tonic-gate int flags = (int)data;
16897c478bd9Sstevel@tonic-gate
16907c478bd9Sstevel@tonic-gate assert(wip->inst != NULL);
16917c478bd9Sstevel@tonic-gate assert(wip->pg == NULL);
16927c478bd9Sstevel@tonic-gate
169337b40227SJerry Jelinek if (svcsearch) {
169437b40227SJerry Jelinek char state[MAX_SCF_STATE_STRING_SZ];
169537b40227SJerry Jelinek
169637b40227SJerry Jelinek if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0)
169737b40227SJerry Jelinek return (0);
169837b40227SJerry Jelinek if (strcmp(state, svcstate) != 0)
169937b40227SJerry Jelinek return (0);
170037b40227SJerry Jelinek }
170137b40227SJerry Jelinek
17027c478bd9Sstevel@tonic-gate if (flags & SET_RECURSIVE) {
17037c478bd9Sstevel@tonic-gate char *fmri_buf = malloc(max_scf_fmri_sz);
17047c478bd9Sstevel@tonic-gate if (fmri_buf == NULL)
17057c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate visited = calloc(HT_BUCKETS, sizeof (*visited));
17087c478bd9Sstevel@tonic-gate if (visited == NULL)
17097c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate /* scf_walk_fmri() guarantees that fmri isn't too long */
17127c478bd9Sstevel@tonic-gate assert(strlen(wip->fmri) <= max_scf_fmri_sz);
17137c478bd9Sstevel@tonic-gate (void) strlcpy(fmri_buf, wip->fmri, max_scf_fmri_sz);
17147c478bd9Sstevel@tonic-gate
17157c478bd9Sstevel@tonic-gate switch (enable_fmri_rec(fmri_buf, (flags & SET_TEMPORARY))) {
17167c478bd9Sstevel@tonic-gate case E2BIG:
17177c478bd9Sstevel@tonic-gate uu_warn(gettext("operation on service %s is ambiguous; "
17187c478bd9Sstevel@tonic-gate "instance specification needed.\n"), fmri_buf);
17197c478bd9Sstevel@tonic-gate break;
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate case ELOOP:
17227c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Dependency cycle detected.\n"),
17237c478bd9Sstevel@tonic-gate fmri_buf);
17247c478bd9Sstevel@tonic-gate }
17257c478bd9Sstevel@tonic-gate
17267c478bd9Sstevel@tonic-gate free(visited);
17277c478bd9Sstevel@tonic-gate free(fmri_buf);
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate } else {
17307c478bd9Sstevel@tonic-gate set_inst_enabled(wip->fmri, wip->inst,
17317c478bd9Sstevel@tonic-gate (flags & SET_TEMPORARY) != 0, (flags & SET_ENABLED) != 0);
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate
17347c478bd9Sstevel@tonic-gate return (0);
17357c478bd9Sstevel@tonic-gate }
17367c478bd9Sstevel@tonic-gate
17377c478bd9Sstevel@tonic-gate /* ARGSUSED */
17387c478bd9Sstevel@tonic-gate static int
wait_fmri_enabled(void * data,scf_walkinfo_t * wip)17397c478bd9Sstevel@tonic-gate wait_fmri_enabled(void *data, scf_walkinfo_t *wip)
17407c478bd9Sstevel@tonic-gate {
17417c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL;
17427c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ];
17437c478bd9Sstevel@tonic-gate
17447c478bd9Sstevel@tonic-gate assert(wip->inst != NULL);
17457c478bd9Sstevel@tonic-gate assert(wip->pg == NULL);
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate do {
17487c478bd9Sstevel@tonic-gate if (pg)
17497c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
17507c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, &pg) != 0) {
17517c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE;
17527c478bd9Sstevel@tonic-gate return (0);
17537c478bd9Sstevel@tonic-gate }
17547c478bd9Sstevel@tonic-gate
17557c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 ||
17567c478bd9Sstevel@tonic-gate strcmp(state, SCF_STATE_STRING_DEGRADED) == 0) {
17577c478bd9Sstevel@tonic-gate /*
17587c478bd9Sstevel@tonic-gate * We're done.
17597c478bd9Sstevel@tonic-gate */
17607c478bd9Sstevel@tonic-gate goto out;
17617c478bd9Sstevel@tonic-gate }
17627c478bd9Sstevel@tonic-gate
17637c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) {
17647c478bd9Sstevel@tonic-gate /*
17657c478bd9Sstevel@tonic-gate * The service is ill.
17667c478bd9Sstevel@tonic-gate */
17677c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is in maintenance"
17687c478bd9Sstevel@tonic-gate " state.\n"), wip->fmri);
17697c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE;
17707c478bd9Sstevel@tonic-gate goto out;
17717c478bd9Sstevel@tonic-gate }
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate if (!is_enabled(wip->inst)) {
17747c478bd9Sstevel@tonic-gate /*
17757c478bd9Sstevel@tonic-gate * Someone stepped in and disabled the service.
17767c478bd9Sstevel@tonic-gate */
17777c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" has been disabled"
17787c478bd9Sstevel@tonic-gate " by another entity.\n"), wip->fmri);
17797c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE;
17807c478bd9Sstevel@tonic-gate goto out;
17817c478bd9Sstevel@tonic-gate }
17827c478bd9Sstevel@tonic-gate
17837c478bd9Sstevel@tonic-gate if (!has_potential(wip->inst, B_FALSE)) {
17847c478bd9Sstevel@tonic-gate /*
17857c478bd9Sstevel@tonic-gate * Our dependencies aren't met. We'll never
17867c478bd9Sstevel@tonic-gate * amount to anything.
17877c478bd9Sstevel@tonic-gate */
17887c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" has unsatisfied"
17897c478bd9Sstevel@tonic-gate " dependencies.\n"), wip->fmri);
17907c478bd9Sstevel@tonic-gate /*
17917c478bd9Sstevel@tonic-gate * EXIT_SVC_FAILURE takes precedence over
17927c478bd9Sstevel@tonic-gate * EXIT_DEP_FAILURE
17937c478bd9Sstevel@tonic-gate */
17947c478bd9Sstevel@tonic-gate if (exit_status == 0)
17957c478bd9Sstevel@tonic-gate exit_status = EXIT_DEP_FAILURE;
17967c478bd9Sstevel@tonic-gate goto out;
17977c478bd9Sstevel@tonic-gate }
17987c478bd9Sstevel@tonic-gate } while (_scf_pg_wait(pg, WAIT_INTERVAL) >= 0);
17997c478bd9Sstevel@tonic-gate scfdie();
18007c478bd9Sstevel@tonic-gate /* NOTREACHED */
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate out:
18037c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
18047c478bd9Sstevel@tonic-gate return (0);
18057c478bd9Sstevel@tonic-gate }
18067c478bd9Sstevel@tonic-gate
18077c478bd9Sstevel@tonic-gate /* ARGSUSED */
18087c478bd9Sstevel@tonic-gate static int
wait_fmri_disabled(void * data,scf_walkinfo_t * wip)18097c478bd9Sstevel@tonic-gate wait_fmri_disabled(void *data, scf_walkinfo_t *wip)
18107c478bd9Sstevel@tonic-gate {
18117c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL;
18127c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ];
18137c478bd9Sstevel@tonic-gate
18147c478bd9Sstevel@tonic-gate assert(wip->inst != NULL);
18157c478bd9Sstevel@tonic-gate assert(wip->pg == NULL);
18167c478bd9Sstevel@tonic-gate
18177c478bd9Sstevel@tonic-gate do {
18187c478bd9Sstevel@tonic-gate if (pg)
18197c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
18207c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, &pg) != 0) {
18217c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE;
18227c478bd9Sstevel@tonic-gate return (0);
18237c478bd9Sstevel@tonic-gate }
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0) {
18267c478bd9Sstevel@tonic-gate /*
18277c478bd9Sstevel@tonic-gate * We're done.
18287c478bd9Sstevel@tonic-gate */
18297c478bd9Sstevel@tonic-gate goto out;
18307c478bd9Sstevel@tonic-gate }
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate if (is_enabled(wip->inst)) {
18337c478bd9Sstevel@tonic-gate /*
18347c478bd9Sstevel@tonic-gate * Someone stepped in and enabled the service.
18357c478bd9Sstevel@tonic-gate */
18367c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" has been enabled"
18377c478bd9Sstevel@tonic-gate " by another entity.\n"), wip->fmri);
18387c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE;
18397c478bd9Sstevel@tonic-gate goto out;
18407c478bd9Sstevel@tonic-gate }
18417c478bd9Sstevel@tonic-gate
18427c478bd9Sstevel@tonic-gate if (!has_potential(wip->inst, B_TRUE)) {
18437c478bd9Sstevel@tonic-gate /*
18447c478bd9Sstevel@tonic-gate * Our restarter is hopeless.
18457c478bd9Sstevel@tonic-gate */
18467c478bd9Sstevel@tonic-gate uu_warn(gettext("Restarter for instance \"%s\" is"
18477c478bd9Sstevel@tonic-gate " unavailable.\n"), wip->fmri);
18487c478bd9Sstevel@tonic-gate /*
18497c478bd9Sstevel@tonic-gate * EXIT_SVC_FAILURE takes precedence over
18507c478bd9Sstevel@tonic-gate * EXIT_DEP_FAILURE
18517c478bd9Sstevel@tonic-gate */
18527c478bd9Sstevel@tonic-gate if (exit_status == 0)
18537c478bd9Sstevel@tonic-gate exit_status = EXIT_DEP_FAILURE;
18547c478bd9Sstevel@tonic-gate goto out;
18557c478bd9Sstevel@tonic-gate }
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate } while (_scf_pg_wait(pg, WAIT_INTERVAL) >= 0);
18587c478bd9Sstevel@tonic-gate scfdie();
18597c478bd9Sstevel@tonic-gate /* NOTREACHED */
18607c478bd9Sstevel@tonic-gate
18617c478bd9Sstevel@tonic-gate out:
18627c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
18637c478bd9Sstevel@tonic-gate return (0);
18647c478bd9Sstevel@tonic-gate }
18657c478bd9Sstevel@tonic-gate
18667c478bd9Sstevel@tonic-gate /* ARGSUSED */
18677c478bd9Sstevel@tonic-gate static int
clear_instance(void * data,scf_walkinfo_t * wip)18687c478bd9Sstevel@tonic-gate clear_instance(void *data, scf_walkinfo_t *wip)
18697c478bd9Sstevel@tonic-gate {
18707c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ];
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate assert(wip->inst != NULL);
18737c478bd9Sstevel@tonic-gate assert(wip->pg == NULL);
18747c478bd9Sstevel@tonic-gate
18757c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0)
18767c478bd9Sstevel@tonic-gate return (0);
18777c478bd9Sstevel@tonic-gate
187837b40227SJerry Jelinek if (svcsearch && strcmp(state, svcstate) != 0)
187937b40227SJerry Jelinek return (0);
188037b40227SJerry Jelinek
18817c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) {
18827c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, SCF_PROPERTY_MAINT_OFF);
18837c478bd9Sstevel@tonic-gate } else if (strcmp(state, SCF_STATE_STRING_DEGRADED) ==
18847c478bd9Sstevel@tonic-gate 0) {
18857c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, SCF_PROPERTY_RESTORE);
18867c478bd9Sstevel@tonic-gate } else {
18877c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is not in a "
18887c478bd9Sstevel@tonic-gate "maintenance or degraded state.\n"), wip->fmri);
18897c478bd9Sstevel@tonic-gate
18907c478bd9Sstevel@tonic-gate exit_status = 1;
18917c478bd9Sstevel@tonic-gate }
18927c478bd9Sstevel@tonic-gate
18937c478bd9Sstevel@tonic-gate return (0);
18947c478bd9Sstevel@tonic-gate }
18957c478bd9Sstevel@tonic-gate
18967c478bd9Sstevel@tonic-gate static int
set_fmri_action(void * action,scf_walkinfo_t * wip)18977c478bd9Sstevel@tonic-gate set_fmri_action(void *action, scf_walkinfo_t *wip)
18987c478bd9Sstevel@tonic-gate {
18997c478bd9Sstevel@tonic-gate assert(wip->inst != NULL && wip->pg == NULL);
19007c478bd9Sstevel@tonic-gate
190137b40227SJerry Jelinek if (svcsearch) {
190237b40227SJerry Jelinek char state[MAX_SCF_STATE_STRING_SZ];
190337b40227SJerry Jelinek
190437b40227SJerry Jelinek if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0)
190537b40227SJerry Jelinek return (0);
190637b40227SJerry Jelinek if (strcmp(state, svcstate) != 0)
190737b40227SJerry Jelinek return (0);
190837b40227SJerry Jelinek }
190937b40227SJerry Jelinek
19107c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, action);
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate return (0);
19137c478bd9Sstevel@tonic-gate }
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gate /*
19167c478bd9Sstevel@tonic-gate * Flags to control 'mark' action.
19177c478bd9Sstevel@tonic-gate */
19187c478bd9Sstevel@tonic-gate #define MARK_IMMEDIATE 0x1
19197c478bd9Sstevel@tonic-gate #define MARK_TEMPORARY 0x2
19207c478bd9Sstevel@tonic-gate
19217c478bd9Sstevel@tonic-gate static int
force_degraded(void * data,scf_walkinfo_t * wip)19227c478bd9Sstevel@tonic-gate force_degraded(void *data, scf_walkinfo_t *wip)
19237c478bd9Sstevel@tonic-gate {
19247c478bd9Sstevel@tonic-gate int flags = (int)data;
19257c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ];
19267c478bd9Sstevel@tonic-gate
19277c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0) {
19287c478bd9Sstevel@tonic-gate exit_status = 1;
19297c478bd9Sstevel@tonic-gate return (0);
19307c478bd9Sstevel@tonic-gate }
19317c478bd9Sstevel@tonic-gate
193237b40227SJerry Jelinek if (svcsearch && strcmp(state, svcstate) != 0)
193337b40227SJerry Jelinek return (0);
193437b40227SJerry Jelinek
19357c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_ONLINE) != 0) {
19367c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is not online.\n"), wip->fmri);
19377c478bd9Sstevel@tonic-gate exit_status = 1;
19387c478bd9Sstevel@tonic-gate return (0);
19397c478bd9Sstevel@tonic-gate }
19407c478bd9Sstevel@tonic-gate
19417c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, (flags & MARK_IMMEDIATE) ?
19427c478bd9Sstevel@tonic-gate SCF_PROPERTY_DEGRADE_IMMEDIATE : SCF_PROPERTY_DEGRADED);
19437c478bd9Sstevel@tonic-gate
19447c478bd9Sstevel@tonic-gate return (0);
19457c478bd9Sstevel@tonic-gate }
19467c478bd9Sstevel@tonic-gate
19477c478bd9Sstevel@tonic-gate static int
force_maintenance(void * data,scf_walkinfo_t * wip)19487c478bd9Sstevel@tonic-gate force_maintenance(void *data, scf_walkinfo_t *wip)
19497c478bd9Sstevel@tonic-gate {
19507c478bd9Sstevel@tonic-gate int flags = (int)data;
19517c478bd9Sstevel@tonic-gate const char *prop;
19527c478bd9Sstevel@tonic-gate
195337b40227SJerry Jelinek if (svcsearch) {
195437b40227SJerry Jelinek char state[MAX_SCF_STATE_STRING_SZ];
195537b40227SJerry Jelinek
195637b40227SJerry Jelinek if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0)
195737b40227SJerry Jelinek return (0);
195837b40227SJerry Jelinek if (strcmp(state, svcstate) != 0)
195937b40227SJerry Jelinek return (0);
196037b40227SJerry Jelinek }
196137b40227SJerry Jelinek
19627c478bd9Sstevel@tonic-gate if (flags & MARK_IMMEDIATE) {
19637c478bd9Sstevel@tonic-gate prop = (flags & MARK_TEMPORARY) ?
19647c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON_IMMTEMP :
19657c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON_IMMEDIATE;
19667c478bd9Sstevel@tonic-gate } else {
19677c478bd9Sstevel@tonic-gate prop = (flags & MARK_TEMPORARY) ?
19687c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON_TEMPORARY :
19697c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON;
19707c478bd9Sstevel@tonic-gate }
19717c478bd9Sstevel@tonic-gate
19727c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, prop);
19737c478bd9Sstevel@tonic-gate
19747c478bd9Sstevel@tonic-gate return (0);
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate
19777c478bd9Sstevel@tonic-gate static void
set_milestone(const char * fmri,boolean_t temporary)19787c478bd9Sstevel@tonic-gate set_milestone(const char *fmri, boolean_t temporary)
19797c478bd9Sstevel@tonic-gate {
19807c478bd9Sstevel@tonic-gate scf_instance_t *inst;
19817c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg;
19827c478bd9Sstevel@tonic-gate int r;
19837c478bd9Sstevel@tonic-gate
19847c478bd9Sstevel@tonic-gate if (temporary) {
19857c478bd9Sstevel@tonic-gate set_astring_prop(SCF_SERVICE_STARTD, SCF_PG_OPTIONS_OVR,
19867c478bd9Sstevel@tonic-gate SCF_PG_OPTIONS_OVR_TYPE, SCF_PG_OPTIONS_OVR_FLAGS,
19877c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, fmri);
19887c478bd9Sstevel@tonic-gate return;
19897c478bd9Sstevel@tonic-gate }
19907c478bd9Sstevel@tonic-gate
19917c478bd9Sstevel@tonic-gate if ((inst = scf_instance_create(h)) == NULL ||
19927c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL)
19937c478bd9Sstevel@tonic-gate scfdie();
19947c478bd9Sstevel@tonic-gate
19957c478bd9Sstevel@tonic-gate if (get_inst(SCF_SERVICE_STARTD, inst) != 0) {
19967c478bd9Sstevel@tonic-gate scf_instance_destroy(inst);
19977c478bd9Sstevel@tonic-gate return;
19987c478bd9Sstevel@tonic-gate }
19997c478bd9Sstevel@tonic-gate
20007c478bd9Sstevel@tonic-gate /*
20017c478bd9Sstevel@tonic-gate * Set the persistent milestone before deleting the override so we don't
20027c478bd9Sstevel@tonic-gate * glitch.
20037c478bd9Sstevel@tonic-gate */
20047c478bd9Sstevel@tonic-gate set_astring_prop(SCF_SERVICE_STARTD, SCF_PG_OPTIONS,
20057c478bd9Sstevel@tonic-gate SCF_PG_OPTIONS_TYPE, SCF_PG_OPTIONS_FLAGS, SCF_PROPERTY_MILESTONE,
20067c478bd9Sstevel@tonic-gate fmri);
20077c478bd9Sstevel@tonic-gate
2008eb1a3463STruong Nguyen r = scf_instance_delete_prop(inst, SCF_PG_OPTIONS_OVR,
2009eb1a3463STruong Nguyen SCF_PROPERTY_MILESTONE);
20107c478bd9Sstevel@tonic-gate switch (r) {
20117c478bd9Sstevel@tonic-gate case 0:
20127c478bd9Sstevel@tonic-gate break;
20137c478bd9Sstevel@tonic-gate
20147c478bd9Sstevel@tonic-gate case ECANCELED:
20157c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri);
20167c478bd9Sstevel@tonic-gate exit_status = 1;
20177c478bd9Sstevel@tonic-gate goto out;
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate case EPERM:
20207c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s property of "
20217c478bd9Sstevel@tonic-gate "%s: permission denied.\n"), SCF_PG_OPTIONS_OVR,
20227c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_SERVICE_STARTD);
20237c478bd9Sstevel@tonic-gate exit_status = 1;
20247c478bd9Sstevel@tonic-gate goto out;
20257c478bd9Sstevel@tonic-gate
20267c478bd9Sstevel@tonic-gate case EACCES:
20277c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s property of "
20287c478bd9Sstevel@tonic-gate "%s: access denied.\n"), SCF_PG_OPTIONS_OVR,
20297c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_SERVICE_STARTD);
20307c478bd9Sstevel@tonic-gate exit_status = 1;
20317c478bd9Sstevel@tonic-gate goto out;
20327c478bd9Sstevel@tonic-gate
20337c478bd9Sstevel@tonic-gate case EROFS:
20347c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s property of "
20357c478bd9Sstevel@tonic-gate "%s: backend read-only.\n"), SCF_PG_OPTIONS_OVR,
20367c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_SERVICE_STARTD);
20377c478bd9Sstevel@tonic-gate exit_status = 1;
20387c478bd9Sstevel@tonic-gate goto out;
20397c478bd9Sstevel@tonic-gate
20407c478bd9Sstevel@tonic-gate default:
2041eb1a3463STruong Nguyen bad_error("scf_instance_delete_prop", r);
20427c478bd9Sstevel@tonic-gate }
20437c478bd9Sstevel@tonic-gate
20447c478bd9Sstevel@tonic-gate out:
20457c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
20467c478bd9Sstevel@tonic-gate scf_instance_destroy(inst);
20477c478bd9Sstevel@tonic-gate }
20487c478bd9Sstevel@tonic-gate
20497c478bd9Sstevel@tonic-gate static char const *milestones[] = {
20507c478bd9Sstevel@tonic-gate SCF_MILESTONE_SINGLE_USER,
20517c478bd9Sstevel@tonic-gate SCF_MILESTONE_MULTI_USER,
20527c478bd9Sstevel@tonic-gate SCF_MILESTONE_MULTI_USER_SERVER,
20537c478bd9Sstevel@tonic-gate NULL
20547c478bd9Sstevel@tonic-gate };
20557c478bd9Sstevel@tonic-gate
20567c478bd9Sstevel@tonic-gate static void
usage_milestone(void)20570b5c9250Shg115875 usage_milestone(void)
20587c478bd9Sstevel@tonic-gate {
20597c478bd9Sstevel@tonic-gate const char **ms;
20607c478bd9Sstevel@tonic-gate
20617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
20627c478bd9Sstevel@tonic-gate "Usage: svcadm milestone [-d] <milestone>\n\n"
20637c478bd9Sstevel@tonic-gate "\t-d\tmake the specified milestone the default for system boot\n\n"
20647c478bd9Sstevel@tonic-gate "\tMilestones can be specified using an FMRI or abbreviation.\n"
20657c478bd9Sstevel@tonic-gate "\tThe major milestones are as follows:\n\n"
20667c478bd9Sstevel@tonic-gate "\tall\n"
20677c478bd9Sstevel@tonic-gate "\tnone\n"));
20687c478bd9Sstevel@tonic-gate
20697c478bd9Sstevel@tonic-gate for (ms = milestones; *ms != NULL; ms++)
20707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\t%s\n", *ms);
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE);
20737c478bd9Sstevel@tonic-gate }
20747c478bd9Sstevel@tonic-gate
20757c478bd9Sstevel@tonic-gate static const char *
validate_milestone(const char * milestone)20767c478bd9Sstevel@tonic-gate validate_milestone(const char *milestone)
20777c478bd9Sstevel@tonic-gate {
20787c478bd9Sstevel@tonic-gate const char **ms;
20797c478bd9Sstevel@tonic-gate const char *tmp;
20807c478bd9Sstevel@tonic-gate size_t len;
20817c478bd9Sstevel@tonic-gate
20827c478bd9Sstevel@tonic-gate if (strcmp(milestone, "all") == 0)
20837c478bd9Sstevel@tonic-gate return (milestone);
20847c478bd9Sstevel@tonic-gate
20857c478bd9Sstevel@tonic-gate if (strcmp(milestone, "none") == 0)
20867c478bd9Sstevel@tonic-gate return (milestone);
20877c478bd9Sstevel@tonic-gate
20887c478bd9Sstevel@tonic-gate /*
20897c478bd9Sstevel@tonic-gate * Determine if this is a full or partial milestone
20907c478bd9Sstevel@tonic-gate */
20917c478bd9Sstevel@tonic-gate for (ms = milestones; *ms != NULL; ms++) {
20927c478bd9Sstevel@tonic-gate if ((tmp = strstr(*ms, milestone)) != NULL) {
20937c478bd9Sstevel@tonic-gate len = strlen(milestone);
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate /*
20967c478bd9Sstevel@tonic-gate * The beginning of the string must align with the start
20977c478bd9Sstevel@tonic-gate * of a milestone fmri, or on the boundary between
20987c478bd9Sstevel@tonic-gate * elements. The end of the string must align with the
20997c478bd9Sstevel@tonic-gate * end of the milestone, or at the instance boundary.
21007c478bd9Sstevel@tonic-gate */
21017c478bd9Sstevel@tonic-gate if ((tmp == *ms || tmp[-1] == '/') &&
21027c478bd9Sstevel@tonic-gate (tmp[len] == '\0' || tmp[len] == ':'))
21037c478bd9Sstevel@tonic-gate return (*ms);
21047c478bd9Sstevel@tonic-gate }
21057c478bd9Sstevel@tonic-gate }
21067c478bd9Sstevel@tonic-gate
21077c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
21087c478bd9Sstevel@tonic-gate gettext("\"%s\" is not a valid major milestone.\n"), milestone);
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gate usage_milestone();
21117c478bd9Sstevel@tonic-gate /* NOTREACHED */
21127c478bd9Sstevel@tonic-gate }
21137c478bd9Sstevel@tonic-gate
2114702a871aSJerry Jelinek /*PRINTFLIKE1*/
2115702a871aSJerry Jelinek static void
pr_warn(const char * format,...)2116702a871aSJerry Jelinek pr_warn(const char *format, ...)
2117702a871aSJerry Jelinek {
2118702a871aSJerry Jelinek const char *pname = uu_getpname();
2119702a871aSJerry Jelinek va_list alist;
2120702a871aSJerry Jelinek
2121702a871aSJerry Jelinek va_start(alist, format);
2122702a871aSJerry Jelinek
2123702a871aSJerry Jelinek if (pname != NULL)
2124702a871aSJerry Jelinek (void) fprintf(stderr, "%s", pname);
2125702a871aSJerry Jelinek
2126702a871aSJerry Jelinek if (g_zonename != NULL)
2127702a871aSJerry Jelinek (void) fprintf(stderr, " (%s)", g_zonename);
2128702a871aSJerry Jelinek
2129702a871aSJerry Jelinek (void) fprintf(stderr, ": ");
2130702a871aSJerry Jelinek
2131702a871aSJerry Jelinek (void) vfprintf(stderr, format, alist);
2132702a871aSJerry Jelinek
2133702a871aSJerry Jelinek if (strrchr(format, '\n') == NULL)
2134702a871aSJerry Jelinek (void) fprintf(stderr, ": %s\n", strerror(errno));
2135702a871aSJerry Jelinek
2136702a871aSJerry Jelinek va_end(alist);
2137702a871aSJerry Jelinek }
2138702a871aSJerry Jelinek
21397c478bd9Sstevel@tonic-gate /*ARGSUSED*/
21407c478bd9Sstevel@tonic-gate static void
quiet(const char * fmt,...)21417c478bd9Sstevel@tonic-gate quiet(const char *fmt, ...)
21427c478bd9Sstevel@tonic-gate {
21437c478bd9Sstevel@tonic-gate /* Do nothing */
21447c478bd9Sstevel@tonic-gate }
21457c478bd9Sstevel@tonic-gate
21467c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])21477c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
21487c478bd9Sstevel@tonic-gate {
21497c478bd9Sstevel@tonic-gate int o;
21507c478bd9Sstevel@tonic-gate int err;
2151c0889d7aSstevep int sw_back;
2152702a871aSJerry Jelinek boolean_t do_zones = B_FALSE;
2153702a871aSJerry Jelinek boolean_t do_a_zone = B_FALSE;
2154702a871aSJerry Jelinek char zonename[ZONENAME_MAX];
2155702a871aSJerry Jelinek uint_t nzents = 0, zent = 0;
2156702a871aSJerry Jelinek zoneid_t *zids = NULL;
2157702a871aSJerry Jelinek int orig_optind, orig_argc;
2158702a871aSJerry Jelinek char **orig_argv;
21597c478bd9Sstevel@tonic-gate
21607c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
21617c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
21627c478bd9Sstevel@tonic-gate
21637c478bd9Sstevel@tonic-gate (void) uu_setpname(argv[0]);
21647c478bd9Sstevel@tonic-gate
21657c478bd9Sstevel@tonic-gate if (argc < 2)
21667c478bd9Sstevel@tonic-gate usage();
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate max_scf_fmri_sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
21697c478bd9Sstevel@tonic-gate if (max_scf_fmri_sz < 0)
21707c478bd9Sstevel@tonic-gate scfdie();
21717c478bd9Sstevel@tonic-gate ++max_scf_fmri_sz;
21727c478bd9Sstevel@tonic-gate
21737c478bd9Sstevel@tonic-gate scratch_fmri = malloc(max_scf_fmri_sz);
21747c478bd9Sstevel@tonic-gate if (scratch_fmri == NULL)
21757c478bd9Sstevel@tonic-gate uu_die(emsg_nomem);
21767c478bd9Sstevel@tonic-gate
217737b40227SJerry Jelinek while ((o = getopt(argc, argv, "S:vZz:")) != -1) {
2178647f8444SBryan Cantrill switch (o) {
217937b40227SJerry Jelinek case 'S':
218037b40227SJerry Jelinek (void) strlcpy(svcstate, optarg, sizeof (svcstate));
218137b40227SJerry Jelinek svcsearch = B_TRUE;
218237b40227SJerry Jelinek break;
218337b40227SJerry Jelinek
2184647f8444SBryan Cantrill case 'v':
21857c478bd9Sstevel@tonic-gate verbose = 1;
2186647f8444SBryan Cantrill break;
2187647f8444SBryan Cantrill
2188702a871aSJerry Jelinek case 'z':
2189647f8444SBryan Cantrill if (getzoneid() != GLOBAL_ZONEID)
2190647f8444SBryan Cantrill uu_die(gettext("svcadm -z may only be used "
2191647f8444SBryan Cantrill "from the global zone\n"));
2192702a871aSJerry Jelinek if (do_zones)
2193702a871aSJerry Jelinek usage();
2194647f8444SBryan Cantrill
2195702a871aSJerry Jelinek (void) strlcpy(zonename, optarg, sizeof (zonename));
2196702a871aSJerry Jelinek do_a_zone = B_TRUE;
2197647f8444SBryan Cantrill break;
2198702a871aSJerry Jelinek
2199702a871aSJerry Jelinek case 'Z':
2200702a871aSJerry Jelinek if (getzoneid() != GLOBAL_ZONEID)
2201702a871aSJerry Jelinek uu_die(gettext("svcadm -Z may only be used "
2202702a871aSJerry Jelinek "from the global zone\n"));
2203702a871aSJerry Jelinek if (do_a_zone)
2204702a871aSJerry Jelinek usage();
2205702a871aSJerry Jelinek
2206702a871aSJerry Jelinek do_zones = B_TRUE;
2207702a871aSJerry Jelinek break;
2208647f8444SBryan Cantrill
2209647f8444SBryan Cantrill default:
22107c478bd9Sstevel@tonic-gate usage();
22117c478bd9Sstevel@tonic-gate }
2212647f8444SBryan Cantrill }
2213647f8444SBryan Cantrill
2214702a871aSJerry Jelinek while (do_zones) {
2215702a871aSJerry Jelinek uint_t found;
22167c478bd9Sstevel@tonic-gate
2217702a871aSJerry Jelinek if (zone_list(NULL, &nzents) != 0)
2218702a871aSJerry Jelinek uu_die(gettext("could not get number of zones"));
2219702a871aSJerry Jelinek
2220702a871aSJerry Jelinek if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL) {
2221702a871aSJerry Jelinek uu_die(gettext("could not allocate array for "
2222702a871aSJerry Jelinek "%d zone IDs"), nzents);
2223702a871aSJerry Jelinek }
2224702a871aSJerry Jelinek
2225702a871aSJerry Jelinek found = nzents;
2226702a871aSJerry Jelinek
2227702a871aSJerry Jelinek if (zone_list(zids, &found) != 0)
2228702a871aSJerry Jelinek uu_die(gettext("could not get zone list"));
2229702a871aSJerry Jelinek
2230702a871aSJerry Jelinek /*
2231702a871aSJerry Jelinek * If the number of zones has not changed between our calls to
2232702a871aSJerry Jelinek * zone_list(), we're done -- otherwise, we must free our array
2233702a871aSJerry Jelinek * of zone IDs and take another lap.
2234702a871aSJerry Jelinek */
2235702a871aSJerry Jelinek if (found == nzents)
2236702a871aSJerry Jelinek break;
2237702a871aSJerry Jelinek
2238702a871aSJerry Jelinek free(zids);
2239702a871aSJerry Jelinek }
22407c478bd9Sstevel@tonic-gate
22417c478bd9Sstevel@tonic-gate emsg_permission_denied = gettext("%s: Permission denied.\n");
22427c478bd9Sstevel@tonic-gate emsg_nomem = gettext("Out of memory.\n");
22437c478bd9Sstevel@tonic-gate emsg_create_pg_perm_denied = gettext("%s: Couldn't create \"%s\" "
22447c478bd9Sstevel@tonic-gate "property group (permission denied).\n");
22457c478bd9Sstevel@tonic-gate emsg_pg_perm_denied = gettext("%s: Couldn't modify \"%s\" property "
22467c478bd9Sstevel@tonic-gate "group (permission denied).\n");
22477c478bd9Sstevel@tonic-gate emsg_prop_perm_denied = gettext("%s: Couldn't modify \"%s/%s\" "
22487c478bd9Sstevel@tonic-gate "property (permission denied).\n");
22497c478bd9Sstevel@tonic-gate emsg_no_service = gettext("No such service \"%s\".\n");
22507c478bd9Sstevel@tonic-gate
2251702a871aSJerry Jelinek orig_optind = optind;
2252702a871aSJerry Jelinek orig_argc = argc;
2253702a871aSJerry Jelinek orig_argv = argv;
2254702a871aSJerry Jelinek
2255702a871aSJerry Jelinek again:
2256702a871aSJerry Jelinek h = scf_handle_create(SCF_VERSION);
2257702a871aSJerry Jelinek if (h == NULL)
2258702a871aSJerry Jelinek scfdie();
2259702a871aSJerry Jelinek
2260702a871aSJerry Jelinek if (do_zones) {
2261702a871aSJerry Jelinek zone_status_t status;
2262702a871aSJerry Jelinek
2263702a871aSJerry Jelinek if (zone_getattr(zids[zent], ZONE_ATTR_STATUS, &status,
2264702a871aSJerry Jelinek sizeof (status)) < 0 || status != ZONE_IS_RUNNING) {
2265702a871aSJerry Jelinek /*
2266702a871aSJerry Jelinek * If this zone is not running or we cannot
2267702a871aSJerry Jelinek * get its status, we do not want to attempt
2268702a871aSJerry Jelinek * to bind an SCF handle to it, lest we
2269702a871aSJerry Jelinek * accidentally interfere with a zone that
2270702a871aSJerry Jelinek * is not yet running by looking up a door
2271702a871aSJerry Jelinek * to its svc.configd (which could potentially
2272702a871aSJerry Jelinek * block a mount with an EBUSY).
2273702a871aSJerry Jelinek */
2274702a871aSJerry Jelinek zent++;
2275702a871aSJerry Jelinek goto nextzone;
2276702a871aSJerry Jelinek }
2277702a871aSJerry Jelinek
2278702a871aSJerry Jelinek if (getzonenamebyid(zids[zent++], zonename,
2279702a871aSJerry Jelinek sizeof (zonename)) < 0) {
2280702a871aSJerry Jelinek uu_warn(gettext("could not get name for "
2281702a871aSJerry Jelinek "zone %d; ignoring"), zids[zent - 1]);
2282702a871aSJerry Jelinek goto nextzone;
2283702a871aSJerry Jelinek }
2284702a871aSJerry Jelinek
2285702a871aSJerry Jelinek g_zonename = zonename;
2286702a871aSJerry Jelinek }
2287702a871aSJerry Jelinek
2288702a871aSJerry Jelinek if (do_a_zone || do_zones) {
2289702a871aSJerry Jelinek scf_value_t *zone;
2290702a871aSJerry Jelinek
2291702a871aSJerry Jelinek if ((zone = scf_value_create(h)) == NULL)
2292702a871aSJerry Jelinek scfdie();
2293702a871aSJerry Jelinek
2294702a871aSJerry Jelinek if (scf_value_set_astring(zone, zonename) != SCF_SUCCESS)
2295702a871aSJerry Jelinek scfdie();
2296702a871aSJerry Jelinek
2297702a871aSJerry Jelinek if (scf_handle_decorate(h, "zone", zone) != SCF_SUCCESS) {
2298702a871aSJerry Jelinek if (do_a_zone) {
2299702a871aSJerry Jelinek uu_die(gettext("invalid zone '%s'\n"), optarg);
2300702a871aSJerry Jelinek } else {
2301702a871aSJerry Jelinek scf_value_destroy(zone);
2302702a871aSJerry Jelinek goto nextzone;
2303702a871aSJerry Jelinek }
2304702a871aSJerry Jelinek }
2305702a871aSJerry Jelinek
2306702a871aSJerry Jelinek scf_value_destroy(zone);
2307702a871aSJerry Jelinek }
2308702a871aSJerry Jelinek
2309702a871aSJerry Jelinek if (scf_handle_bind(h) == -1) {
2310702a871aSJerry Jelinek if (do_zones)
2311702a871aSJerry Jelinek goto nextzone;
2312702a871aSJerry Jelinek
2313702a871aSJerry Jelinek uu_die(gettext("Couldn't bind to configuration repository: "
2314702a871aSJerry Jelinek "%s.\n"), scf_strerror(scf_error()));
2315702a871aSJerry Jelinek }
2316702a871aSJerry Jelinek
2317702a871aSJerry Jelinek optind = orig_optind;
2318702a871aSJerry Jelinek argc = orig_argc;
2319702a871aSJerry Jelinek argv = orig_argv;
2320702a871aSJerry Jelinek
2321702a871aSJerry Jelinek if (optind >= argc)
2322702a871aSJerry Jelinek usage();
2323702a871aSJerry Jelinek
23247c478bd9Sstevel@tonic-gate if (strcmp(argv[optind], "enable") == 0) {
23257c478bd9Sstevel@tonic-gate int flags = SET_ENABLED;
23267c478bd9Sstevel@tonic-gate int wait = 0;
23277c478bd9Sstevel@tonic-gate int error = 0;
23287c478bd9Sstevel@tonic-gate
23297c478bd9Sstevel@tonic-gate ++optind;
23307c478bd9Sstevel@tonic-gate
23317c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "rst")) != -1) {
23327c478bd9Sstevel@tonic-gate if (o == 'r')
23337c478bd9Sstevel@tonic-gate flags |= SET_RECURSIVE;
23347c478bd9Sstevel@tonic-gate else if (o == 't')
23357c478bd9Sstevel@tonic-gate flags |= SET_TEMPORARY;
23367c478bd9Sstevel@tonic-gate else if (o == 's')
23377c478bd9Sstevel@tonic-gate wait = 1;
23387c478bd9Sstevel@tonic-gate else if (o == '?')
23397c478bd9Sstevel@tonic-gate usage();
23407c478bd9Sstevel@tonic-gate else {
23417c478bd9Sstevel@tonic-gate assert(0);
23427c478bd9Sstevel@tonic-gate abort();
23437c478bd9Sstevel@tonic-gate }
23447c478bd9Sstevel@tonic-gate }
23457c478bd9Sstevel@tonic-gate argc -= optind;
23467c478bd9Sstevel@tonic-gate argv += optind;
23477c478bd9Sstevel@tonic-gate
234837b40227SJerry Jelinek if (argc == 0 && !svcsearch)
234937b40227SJerry Jelinek usage();
235037b40227SJerry Jelinek
235137b40227SJerry Jelinek if (argc > 0 && svcsearch)
23527c478bd9Sstevel@tonic-gate usage();
23537c478bd9Sstevel@tonic-gate
23547c478bd9Sstevel@tonic-gate /*
23557c478bd9Sstevel@tonic-gate * We want to continue with -s processing if we had
23567c478bd9Sstevel@tonic-gate * invalid options, but not if an enable failed. We
23577c478bd9Sstevel@tonic-gate * squelch output the second time we walk fmris; we saw
23587c478bd9Sstevel@tonic-gate * the errors the first time.
23597c478bd9Sstevel@tonic-gate */
23606c7c876cSJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
2361702a871aSJerry Jelinek set_fmri_enabled, (void *)flags, &error, pr_warn)) != 0) {
23627c478bd9Sstevel@tonic-gate
2363702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
23647c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err));
23657c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
23667c478bd9Sstevel@tonic-gate
23677c478bd9Sstevel@tonic-gate } else if (wait && exit_status == 0 &&
23686c7c876cSJerry Jelinek (err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
23696c7c876cSJerry Jelinek wait_fmri_enabled, (void *)flags, &error, quiet)) != 0) {
23707c478bd9Sstevel@tonic-gate
2371702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
23727c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err));
23737c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
23747c478bd9Sstevel@tonic-gate }
23757c478bd9Sstevel@tonic-gate
23767c478bd9Sstevel@tonic-gate if (error > 0)
23777c478bd9Sstevel@tonic-gate exit_status = error;
23787c478bd9Sstevel@tonic-gate
23797c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "disable") == 0) {
23807c478bd9Sstevel@tonic-gate int flags = 0;
23817c478bd9Sstevel@tonic-gate int wait = 0;
23827c478bd9Sstevel@tonic-gate int error = 0;
23837c478bd9Sstevel@tonic-gate
23847c478bd9Sstevel@tonic-gate ++optind;
23857c478bd9Sstevel@tonic-gate
23867c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "st")) != -1) {
23877c478bd9Sstevel@tonic-gate if (o == 't')
23887c478bd9Sstevel@tonic-gate flags |= SET_TEMPORARY;
23897c478bd9Sstevel@tonic-gate else if (o == 's')
23907c478bd9Sstevel@tonic-gate wait = 1;
23917c478bd9Sstevel@tonic-gate else if (o == '?')
23927c478bd9Sstevel@tonic-gate usage();
23937c478bd9Sstevel@tonic-gate else {
23947c478bd9Sstevel@tonic-gate assert(0);
23957c478bd9Sstevel@tonic-gate abort();
23967c478bd9Sstevel@tonic-gate }
23977c478bd9Sstevel@tonic-gate }
23987c478bd9Sstevel@tonic-gate argc -= optind;
23997c478bd9Sstevel@tonic-gate argv += optind;
24007c478bd9Sstevel@tonic-gate
240137b40227SJerry Jelinek if (argc == 0 && !svcsearch)
240237b40227SJerry Jelinek usage();
240337b40227SJerry Jelinek
240437b40227SJerry Jelinek if (argc > 0 && svcsearch)
24057c478bd9Sstevel@tonic-gate usage();
24067c478bd9Sstevel@tonic-gate
24077c478bd9Sstevel@tonic-gate /*
24087c478bd9Sstevel@tonic-gate * We want to continue with -s processing if we had
24097c478bd9Sstevel@tonic-gate * invalid options, but not if a disable failed. We
24107c478bd9Sstevel@tonic-gate * squelch output the second time we walk fmris; we saw
24117c478bd9Sstevel@tonic-gate * the errors the first time.
24127c478bd9Sstevel@tonic-gate */
24136c7c876cSJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
24146c7c876cSJerry Jelinek set_fmri_enabled, (void *)flags, &exit_status,
2415702a871aSJerry Jelinek pr_warn)) != 0) {
24167c478bd9Sstevel@tonic-gate
2417702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
24187c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err));
24197c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
24207c478bd9Sstevel@tonic-gate
24217c478bd9Sstevel@tonic-gate } else if (wait && exit_status == 0 &&
24226c7c876cSJerry Jelinek (err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
24236c7c876cSJerry Jelinek wait_fmri_disabled, (void *)flags, &error, quiet)) != 0) {
24247c478bd9Sstevel@tonic-gate
2425702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
24267c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err));
24277c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
24287c478bd9Sstevel@tonic-gate }
24297c478bd9Sstevel@tonic-gate
24307c478bd9Sstevel@tonic-gate if (error > 0)
24317c478bd9Sstevel@tonic-gate exit_status = error;
24327c478bd9Sstevel@tonic-gate
24337c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "restart") == 0) {
2434*ac0324d2SJerry Jelinek boolean_t do_dump = B_FALSE;
2435*ac0324d2SJerry Jelinek
24367c478bd9Sstevel@tonic-gate ++optind;
2437*ac0324d2SJerry Jelinek
2438*ac0324d2SJerry Jelinek while ((o = getopt(argc, argv, "d")) != -1) {
2439*ac0324d2SJerry Jelinek if (o == 'd')
2440*ac0324d2SJerry Jelinek do_dump = B_TRUE;
2441*ac0324d2SJerry Jelinek else if (o == '?')
2442*ac0324d2SJerry Jelinek usage();
2443*ac0324d2SJerry Jelinek else {
2444*ac0324d2SJerry Jelinek assert(0);
2445*ac0324d2SJerry Jelinek abort();
2446*ac0324d2SJerry Jelinek }
2447*ac0324d2SJerry Jelinek }
244837b40227SJerry Jelinek argc -= optind;
244937b40227SJerry Jelinek argv += optind;
24507c478bd9Sstevel@tonic-gate
245137b40227SJerry Jelinek if (argc == 0 && !svcsearch)
24527c478bd9Sstevel@tonic-gate usage();
24537c478bd9Sstevel@tonic-gate
245437b40227SJerry Jelinek if (argc > 0 && svcsearch)
245537b40227SJerry Jelinek usage();
245637b40227SJerry Jelinek
2457*ac0324d2SJerry Jelinek if (do_dump) {
2458*ac0324d2SJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
2459*ac0324d2SJerry Jelinek set_fmri_action, (void *)SCF_PROPERTY_DODUMP,
2460*ac0324d2SJerry Jelinek &exit_status, pr_warn)) != 0) {
2461*ac0324d2SJerry Jelinek pr_warn(gettext("failed to iterate over "
2462*ac0324d2SJerry Jelinek "instances: %s\n"), scf_strerror(err));
2463*ac0324d2SJerry Jelinek exit_status = UU_EXIT_FATAL;
2464*ac0324d2SJerry Jelinek }
2465*ac0324d2SJerry Jelinek }
2466*ac0324d2SJerry Jelinek
246737b40227SJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
246837b40227SJerry Jelinek set_fmri_action, (void *)SCF_PROPERTY_RESTART, &exit_status,
2469702a871aSJerry Jelinek pr_warn)) != 0) {
2470702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
24717c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err));
24727c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
24737c478bd9Sstevel@tonic-gate }
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "refresh") == 0) {
24767c478bd9Sstevel@tonic-gate ++optind;
247737b40227SJerry Jelinek argc -= optind;
247837b40227SJerry Jelinek argv += optind;
24797c478bd9Sstevel@tonic-gate
248037b40227SJerry Jelinek if (argc == 0 && !svcsearch)
24817c478bd9Sstevel@tonic-gate usage();
24827c478bd9Sstevel@tonic-gate
248337b40227SJerry Jelinek if (argc > 0 && svcsearch)
248437b40227SJerry Jelinek usage();
248537b40227SJerry Jelinek
248637b40227SJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
248737b40227SJerry Jelinek set_fmri_action, (void *)SCF_PROPERTY_REFRESH, &exit_status,
2488702a871aSJerry Jelinek pr_warn)) != 0) {
2489702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
24907c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(scf_error()));
24917c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
24927c478bd9Sstevel@tonic-gate }
24937c478bd9Sstevel@tonic-gate
24947c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "mark") == 0) {
24957c478bd9Sstevel@tonic-gate int flags = 0;
24967c478bd9Sstevel@tonic-gate scf_walk_callback callback;
24977c478bd9Sstevel@tonic-gate
24987c478bd9Sstevel@tonic-gate ++optind;
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "It")) != -1) {
25017c478bd9Sstevel@tonic-gate if (o == 'I')
25027c478bd9Sstevel@tonic-gate flags |= MARK_IMMEDIATE;
25037c478bd9Sstevel@tonic-gate else if (o == 't')
25047c478bd9Sstevel@tonic-gate flags |= MARK_TEMPORARY;
25057c478bd9Sstevel@tonic-gate else if (o == '?')
25067c478bd9Sstevel@tonic-gate usage();
25077c478bd9Sstevel@tonic-gate else {
25087c478bd9Sstevel@tonic-gate assert(0);
25097c478bd9Sstevel@tonic-gate abort();
25107c478bd9Sstevel@tonic-gate }
25117c478bd9Sstevel@tonic-gate }
25127c478bd9Sstevel@tonic-gate
25137c478bd9Sstevel@tonic-gate if (argc - optind < 2)
25147c478bd9Sstevel@tonic-gate usage();
25157c478bd9Sstevel@tonic-gate
25167c478bd9Sstevel@tonic-gate if (strcmp(argv[optind], "degraded") == 0) {
25177c478bd9Sstevel@tonic-gate if (flags & MARK_TEMPORARY)
25187c478bd9Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("-t may not be "
25197c478bd9Sstevel@tonic-gate "used with degraded.\n"));
25207c478bd9Sstevel@tonic-gate callback = force_degraded;
25217c478bd9Sstevel@tonic-gate
25227c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "maintenance") == 0) {
25237c478bd9Sstevel@tonic-gate callback = force_maintenance;
25247c478bd9Sstevel@tonic-gate } else {
25257c478bd9Sstevel@tonic-gate usage();
25267c478bd9Sstevel@tonic-gate }
25277c478bd9Sstevel@tonic-gate
252837b40227SJerry Jelinek optind++;
252937b40227SJerry Jelinek argc -= optind;
253037b40227SJerry Jelinek argv += optind;
253137b40227SJerry Jelinek
253237b40227SJerry Jelinek if (argc == 0 && !svcsearch)
253337b40227SJerry Jelinek usage();
253437b40227SJerry Jelinek
253537b40227SJerry Jelinek if (argc > 0 && svcsearch)
253637b40227SJerry Jelinek usage();
253737b40227SJerry Jelinek
253837b40227SJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS, callback,
253937b40227SJerry Jelinek NULL, &exit_status, pr_warn)) != 0) {
2540702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
25417c478bd9Sstevel@tonic-gate "instances: %s\n"),
25427c478bd9Sstevel@tonic-gate scf_strerror(err));
25437c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
25447c478bd9Sstevel@tonic-gate }
25457c478bd9Sstevel@tonic-gate
25467c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "clear") == 0) {
25477c478bd9Sstevel@tonic-gate ++optind;
254837b40227SJerry Jelinek argc -= optind;
254937b40227SJerry Jelinek argv += optind;
25507c478bd9Sstevel@tonic-gate
255137b40227SJerry Jelinek if (argc == 0 && !svcsearch)
25527c478bd9Sstevel@tonic-gate usage();
25537c478bd9Sstevel@tonic-gate
255437b40227SJerry Jelinek if (svcsearch) {
255537b40227SJerry Jelinek if (argc > 0)
255637b40227SJerry Jelinek usage();
255737b40227SJerry Jelinek if (strcmp(svcstate, SCF_STATE_STRING_MAINT) != 0 &&
255837b40227SJerry Jelinek strcmp(svcstate, SCF_STATE_STRING_DEGRADED) != 0)
255937b40227SJerry Jelinek uu_die(gettext("State must be '%s' or '%s'\n"),
256037b40227SJerry Jelinek SCF_STATE_STRING_MAINT,
256137b40227SJerry Jelinek SCF_STATE_STRING_DEGRADED);
256237b40227SJerry Jelinek }
256337b40227SJerry Jelinek
256437b40227SJerry Jelinek if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS,
256537b40227SJerry Jelinek clear_instance, NULL, &exit_status, pr_warn)) != 0) {
2566702a871aSJerry Jelinek pr_warn(gettext("failed to iterate over "
25677c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err));
25687c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
25697c478bd9Sstevel@tonic-gate }
25707c478bd9Sstevel@tonic-gate
25717c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "milestone") == 0) {
25727c478bd9Sstevel@tonic-gate boolean_t temporary = B_TRUE;
25737c478bd9Sstevel@tonic-gate const char *milestone;
25747c478bd9Sstevel@tonic-gate
25757c478bd9Sstevel@tonic-gate ++optind;
25767c478bd9Sstevel@tonic-gate
25777c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "d")) != -1) {
25787c478bd9Sstevel@tonic-gate if (o == 'd')
25797c478bd9Sstevel@tonic-gate temporary = B_FALSE;
25807c478bd9Sstevel@tonic-gate else if (o == '?')
25817c478bd9Sstevel@tonic-gate usage_milestone();
25827c478bd9Sstevel@tonic-gate else {
25837c478bd9Sstevel@tonic-gate assert(0);
25847c478bd9Sstevel@tonic-gate abort();
25857c478bd9Sstevel@tonic-gate }
25867c478bd9Sstevel@tonic-gate }
25877c478bd9Sstevel@tonic-gate
25887c478bd9Sstevel@tonic-gate if (optind >= argc)
25897c478bd9Sstevel@tonic-gate usage_milestone();
25907c478bd9Sstevel@tonic-gate
25917c478bd9Sstevel@tonic-gate milestone = validate_milestone(argv[optind]);
25927c478bd9Sstevel@tonic-gate
25937c478bd9Sstevel@tonic-gate set_milestone(milestone, temporary);
25947c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "_smf_backup") == 0) {
25957c478bd9Sstevel@tonic-gate const char *reason = NULL;
25967c478bd9Sstevel@tonic-gate
25977c478bd9Sstevel@tonic-gate ++optind;
25987c478bd9Sstevel@tonic-gate
25997c478bd9Sstevel@tonic-gate if (optind != argc - 1)
26007c478bd9Sstevel@tonic-gate usage();
26017c478bd9Sstevel@tonic-gate
26027c478bd9Sstevel@tonic-gate if ((err = _scf_request_backup(h, argv[optind])) !=
26037c478bd9Sstevel@tonic-gate SCF_SUCCESS) {
26047c478bd9Sstevel@tonic-gate switch (scf_error()) {
26057c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND:
26067c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
26077c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
26087c478bd9Sstevel@tonic-gate scfdie();
26097c478bd9Sstevel@tonic-gate break;
26107c478bd9Sstevel@tonic-gate
26117c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
26127c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
26137c478bd9Sstevel@tonic-gate reason = scf_strerror(scf_error());
26147c478bd9Sstevel@tonic-gate break;
26157c478bd9Sstevel@tonic-gate
26167c478bd9Sstevel@tonic-gate case SCF_ERROR_INTERNAL:
26177c478bd9Sstevel@tonic-gate reason =
26187c478bd9Sstevel@tonic-gate "unknown error (see console for details)";
26197c478bd9Sstevel@tonic-gate break;
26207c478bd9Sstevel@tonic-gate }
2621c0889d7aSstevep
2622702a871aSJerry Jelinek pr_warn("failed to backup repository: %s\n", reason);
26237c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL;
26247c478bd9Sstevel@tonic-gate }
2625c0889d7aSstevep } else if (strcmp(argv[optind], "_smf_repository_switch") == 0) {
2626c0889d7aSstevep const char *reason = NULL;
2627c0889d7aSstevep
2628c0889d7aSstevep ++optind;
2629c0889d7aSstevep
2630c0889d7aSstevep /*
2631c0889d7aSstevep * Check argument and setup scf_switch structure
2632c0889d7aSstevep */
2633c0889d7aSstevep if (optind != argc - 1)
2634c0889d7aSstevep exit(1);
2635c0889d7aSstevep
2636c0889d7aSstevep if (strcmp(argv[optind], "fast") == 0) {
2637c0889d7aSstevep sw_back = 0;
2638c0889d7aSstevep } else if (strcmp(argv[optind], "perm") == 0) {
2639c0889d7aSstevep sw_back = 1;
2640c0889d7aSstevep } else {
2641c0889d7aSstevep exit(UU_EXIT_USAGE);
2642c0889d7aSstevep }
2643c0889d7aSstevep
2644c0889d7aSstevep /*
2645c0889d7aSstevep * Call into switch primitive
2646c0889d7aSstevep */
2647c0889d7aSstevep if ((err = _scf_repository_switch(h, sw_back)) !=
2648c0889d7aSstevep SCF_SUCCESS) {
2649c0889d7aSstevep /*
2650c0889d7aSstevep * Retrieve per thread SCF error code
2651c0889d7aSstevep */
2652c0889d7aSstevep switch (scf_error()) {
2653c0889d7aSstevep case SCF_ERROR_NOT_BOUND:
2654c0889d7aSstevep abort();
2655c0889d7aSstevep /* NOTREACHED */
2656c0889d7aSstevep
2657c0889d7aSstevep case SCF_ERROR_CONNECTION_BROKEN:
2658c0889d7aSstevep case SCF_ERROR_BACKEND_READONLY:
2659c0889d7aSstevep scfdie();
2660c0889d7aSstevep /* NOTREACHED */
2661c0889d7aSstevep
2662c0889d7aSstevep case SCF_ERROR_PERMISSION_DENIED:
2663c0889d7aSstevep case SCF_ERROR_INVALID_ARGUMENT:
2664c0889d7aSstevep reason = scf_strerror(scf_error());
2665c0889d7aSstevep break;
2666c0889d7aSstevep
2667c0889d7aSstevep case SCF_ERROR_INTERNAL:
2668c0889d7aSstevep reason = "File operation error: (see console)";
2669c0889d7aSstevep break;
2670c0889d7aSstevep
2671c0889d7aSstevep default:
2672c0889d7aSstevep abort();
2673c0889d7aSstevep /* NOTREACHED */
2674c0889d7aSstevep }
2675c0889d7aSstevep
2676702a871aSJerry Jelinek pr_warn("failed to switch repository: %s\n", reason);
2677c0889d7aSstevep exit_status = UU_EXIT_FATAL;
2678c0889d7aSstevep }
26797c478bd9Sstevel@tonic-gate } else {
26807c478bd9Sstevel@tonic-gate usage();
26817c478bd9Sstevel@tonic-gate }
26827c478bd9Sstevel@tonic-gate
26837c478bd9Sstevel@tonic-gate if (scf_handle_unbind(h) == -1)
26847c478bd9Sstevel@tonic-gate scfdie();
2685702a871aSJerry Jelinek nextzone:
26867c478bd9Sstevel@tonic-gate scf_handle_destroy(h);
2687702a871aSJerry Jelinek if (do_zones && zent < nzents)
2688702a871aSJerry Jelinek goto again;
26897c478bd9Sstevel@tonic-gate
26907c478bd9Sstevel@tonic-gate return (exit_status);
26917c478bd9Sstevel@tonic-gate }
2692