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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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