1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * svcadm - request adminstrative actions for service instances 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <locale.h> 34*7c478bd9Sstevel@tonic-gate #include <libintl.h> 35*7c478bd9Sstevel@tonic-gate #include <libscf.h> 36*7c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 37*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 38*7c478bd9Sstevel@tonic-gate #include <stddef.h> 39*7c478bd9Sstevel@tonic-gate #include <stdio.h> 40*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 41*7c478bd9Sstevel@tonic-gate #include <string.h> 42*7c478bd9Sstevel@tonic-gate #include <unistd.h> 43*7c478bd9Sstevel@tonic-gate #include <assert.h> 44*7c478bd9Sstevel@tonic-gate #include <errno.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN 47*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD" 48*7c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* Must be a power of two */ 51*7c478bd9Sstevel@tonic-gate #define HT_BUCKETS 64 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* 54*7c478bd9Sstevel@tonic-gate * Exit codes for enable and disable -s. 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate #define EXIT_SVC_FAILURE 3 57*7c478bd9Sstevel@tonic-gate #define EXIT_DEP_FAILURE 4 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * How long we will wait (in seconds) for a service to change state 61*7c478bd9Sstevel@tonic-gate * before re-checking its dependencies. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate #define WAIT_INTERVAL 3 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 66*7c478bd9Sstevel@tonic-gate #define bad_error(func, err) { \ 67*7c478bd9Sstevel@tonic-gate uu_warn("%s:%d: %s() failed with unexpected error %d.\n", \ 68*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \ 69*7c478bd9Sstevel@tonic-gate abort(); \ 70*7c478bd9Sstevel@tonic-gate } 71*7c478bd9Sstevel@tonic-gate #else 72*7c478bd9Sstevel@tonic-gate #define bad_error(func, err) abort() 73*7c478bd9Sstevel@tonic-gate #endif 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate struct ht_elt { 77*7c478bd9Sstevel@tonic-gate struct ht_elt *next; 78*7c478bd9Sstevel@tonic-gate boolean_t active; 79*7c478bd9Sstevel@tonic-gate char str[1]; 80*7c478bd9Sstevel@tonic-gate }; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 84*7c478bd9Sstevel@tonic-gate ssize_t max_scf_fmri_sz; 85*7c478bd9Sstevel@tonic-gate static const char *emsg_permission_denied; 86*7c478bd9Sstevel@tonic-gate static const char *emsg_nomem; 87*7c478bd9Sstevel@tonic-gate static const char *emsg_create_pg_perm_denied; 88*7c478bd9Sstevel@tonic-gate static const char *emsg_pg_perm_denied; 89*7c478bd9Sstevel@tonic-gate static const char *emsg_prop_perm_denied; 90*7c478bd9Sstevel@tonic-gate static const char *emsg_no_service; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static int exit_status = 0; 93*7c478bd9Sstevel@tonic-gate static int verbose = 0; 94*7c478bd9Sstevel@tonic-gate static char *scratch_fmri; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate static struct ht_elt **visited; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * Visitors from synch.c, needed for enable -s and disable -s. 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate extern int is_enabled(scf_instance_t *); 102*7c478bd9Sstevel@tonic-gate extern int has_potential(scf_instance_t *, int); 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate void 105*7c478bd9Sstevel@tonic-gate do_scfdie(int lineno) 106*7c478bd9Sstevel@tonic-gate { 107*7c478bd9Sstevel@tonic-gate scf_error_t err; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate switch (err = scf_error()) { 110*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 111*7c478bd9Sstevel@tonic-gate uu_die(gettext("Connection to repository server broken. " 112*7c478bd9Sstevel@tonic-gate "Exiting.\n")); 113*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 116*7c478bd9Sstevel@tonic-gate uu_die(gettext("Repository is read-only. Exiting.\n")); 117*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate default: 120*7c478bd9Sstevel@tonic-gate #ifdef NDEBUG 121*7c478bd9Sstevel@tonic-gate uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"), 122*7c478bd9Sstevel@tonic-gate scf_strerror(err)); 123*7c478bd9Sstevel@tonic-gate #else 124*7c478bd9Sstevel@tonic-gate uu_die("Unexpected libscf error on line %d: %s.\n", lineno, 125*7c478bd9Sstevel@tonic-gate scf_strerror(err)); 126*7c478bd9Sstevel@tonic-gate #endif 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate #define scfdie() do_scfdie(__LINE__) 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate static void 133*7c478bd9Sstevel@tonic-gate usage() 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 136*7c478bd9Sstevel@tonic-gate "Usage: %1$s [-v] [cmd [args ... ]]\n\n" 137*7c478bd9Sstevel@tonic-gate "\t%1$s enable [-rst] <service> ...\t- enable and online service(s)\n" 138*7c478bd9Sstevel@tonic-gate "\t%1$s disable [-st] <service> ...\t- disable and offline service(s)\n" 139*7c478bd9Sstevel@tonic-gate "\t%1$s restart <service> ...\t\t- restart specified service(s)\n" 140*7c478bd9Sstevel@tonic-gate "\t%1$s refresh <service> ...\t\t- re-read service configuration\n" 141*7c478bd9Sstevel@tonic-gate "\t%1$s mark [-It] <state> <service> ...\t- set maintenance state\n" 142*7c478bd9Sstevel@tonic-gate "\t%1$s clear <service> ...\t\t- clear maintenance state\n" 143*7c478bd9Sstevel@tonic-gate "\t%1$s milestone [-d] <milestone>\t- advance to a service milestone\n" 144*7c478bd9Sstevel@tonic-gate "\n\t" 145*7c478bd9Sstevel@tonic-gate "Services can be specified using an FMRI, abbreviation, or fnmatch(5)\n" 146*7c478bd9Sstevel@tonic-gate "\tpattern, as shown in these examples for svc:/network/smtp:sendmail\n" 147*7c478bd9Sstevel@tonic-gate "\n" 148*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> svc:/network/smtp:sendmail\n" 149*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> network/smtp:sendmail\n" 150*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> network/*mail\n" 151*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> network/smtp\n" 152*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> smtp:sendmail\n" 153*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> smtp\n" 154*7c478bd9Sstevel@tonic-gate "\t%1$s <cmd> sendmail\n"), uu_getpname()); 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* 161*7c478bd9Sstevel@tonic-gate * FMRI hash table for recursive enable. 162*7c478bd9Sstevel@tonic-gate */ 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate static uint32_t 165*7c478bd9Sstevel@tonic-gate hash_fmri(const char *str) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate uint32_t h = 0, g; 168*7c478bd9Sstevel@tonic-gate const char *p; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* Generic hash function from uts/common/os/modhash.c . */ 171*7c478bd9Sstevel@tonic-gate for (p = str; *p != '\0'; ++p) { 172*7c478bd9Sstevel@tonic-gate h = (h << 4) + *p; 173*7c478bd9Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) { 174*7c478bd9Sstevel@tonic-gate h ^= (g >> 24); 175*7c478bd9Sstevel@tonic-gate h ^= g; 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate return (h); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* 183*7c478bd9Sstevel@tonic-gate * Return 1 if str has been visited, 0 if it has not, and -1 if memory could not 184*7c478bd9Sstevel@tonic-gate * be allocated. 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate static int 187*7c478bd9Sstevel@tonic-gate visited_find_or_add(const char *str, struct ht_elt **hep) 188*7c478bd9Sstevel@tonic-gate { 189*7c478bd9Sstevel@tonic-gate uint32_t h; 190*7c478bd9Sstevel@tonic-gate uint_t i; 191*7c478bd9Sstevel@tonic-gate struct ht_elt *he; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate h = hash_fmri(str); 194*7c478bd9Sstevel@tonic-gate i = h & (HT_BUCKETS - 1); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate for (he = visited[i]; he != NULL; he = he->next) { 197*7c478bd9Sstevel@tonic-gate if (strcmp(he->str, str) == 0) { 198*7c478bd9Sstevel@tonic-gate if (hep) 199*7c478bd9Sstevel@tonic-gate *hep = he; 200*7c478bd9Sstevel@tonic-gate return (1); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate he = malloc(offsetof(struct ht_elt, str) + strlen(str) + 1); 205*7c478bd9Sstevel@tonic-gate if (he == NULL) 206*7c478bd9Sstevel@tonic-gate return (-1); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate (void) strcpy(he->str, str); 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate he->next = visited[i]; 211*7c478bd9Sstevel@tonic-gate visited[i] = he; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (hep) 214*7c478bd9Sstevel@tonic-gate *hep = he; 215*7c478bd9Sstevel@tonic-gate return (0); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* 220*7c478bd9Sstevel@tonic-gate * Returns 0, ECANCELED if pg is deleted, ENOENT if propname doesn't exist, 221*7c478bd9Sstevel@tonic-gate * EINVAL if the property is not of boolean type or has no values, and E2BIG 222*7c478bd9Sstevel@tonic-gate * if it has more than one value. *bp is set if 0 or E2BIG is returned. 223*7c478bd9Sstevel@tonic-gate */ 224*7c478bd9Sstevel@tonic-gate int 225*7c478bd9Sstevel@tonic-gate get_bool_prop(scf_propertygroup_t *pg, const char *propname, uint8_t *bp) 226*7c478bd9Sstevel@tonic-gate { 227*7c478bd9Sstevel@tonic-gate scf_property_t *prop; 228*7c478bd9Sstevel@tonic-gate scf_value_t *val; 229*7c478bd9Sstevel@tonic-gate int ret; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if ((prop = scf_property_create(h)) == NULL || 232*7c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) 233*7c478bd9Sstevel@tonic-gate scfdie(); 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) != 0) { 236*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 237*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 238*7c478bd9Sstevel@tonic-gate ret = ECANCELED; 239*7c478bd9Sstevel@tonic-gate goto out; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 242*7c478bd9Sstevel@tonic-gate ret = ENOENT; 243*7c478bd9Sstevel@tonic-gate goto out; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 246*7c478bd9Sstevel@tonic-gate assert(0); 247*7c478bd9Sstevel@tonic-gate abort(); 248*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate default: 251*7c478bd9Sstevel@tonic-gate scfdie(); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) == 0) { 256*7c478bd9Sstevel@tonic-gate ret = 0; 257*7c478bd9Sstevel@tonic-gate } else { 258*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 259*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 260*7c478bd9Sstevel@tonic-gate ret = ENOENT; 261*7c478bd9Sstevel@tonic-gate goto out; 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 264*7c478bd9Sstevel@tonic-gate ret = EINVAL; 265*7c478bd9Sstevel@tonic-gate goto out; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 268*7c478bd9Sstevel@tonic-gate ret = E2BIG; 269*7c478bd9Sstevel@tonic-gate break; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 272*7c478bd9Sstevel@tonic-gate assert(0); 273*7c478bd9Sstevel@tonic-gate abort(); 274*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate default: 277*7c478bd9Sstevel@tonic-gate scfdie(); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate if (scf_value_get_boolean(val, bp) != 0) { 282*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH) 283*7c478bd9Sstevel@tonic-gate scfdie(); 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate ret = EINVAL; 286*7c478bd9Sstevel@tonic-gate goto out; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate out: 290*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 291*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 292*7c478bd9Sstevel@tonic-gate return (ret); 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * Returns 0, EPERM, or EROFS. 297*7c478bd9Sstevel@tonic-gate */ 298*7c478bd9Sstevel@tonic-gate static int 299*7c478bd9Sstevel@tonic-gate set_bool_prop(scf_propertygroup_t *pg, const char *propname, boolean_t b) 300*7c478bd9Sstevel@tonic-gate { 301*7c478bd9Sstevel@tonic-gate scf_value_t *v; 302*7c478bd9Sstevel@tonic-gate scf_transaction_t *tx; 303*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ent; 304*7c478bd9Sstevel@tonic-gate int ret = 0, r; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if ((tx = scf_transaction_create(h)) == NULL || 307*7c478bd9Sstevel@tonic-gate (ent = scf_entry_create(h)) == NULL || 308*7c478bd9Sstevel@tonic-gate (v = scf_value_create(h)) == NULL) 309*7c478bd9Sstevel@tonic-gate scfdie(); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate scf_value_set_boolean(v, b); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate for (;;) { 314*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) == -1) { 315*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 316*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 317*7c478bd9Sstevel@tonic-gate ret = EPERM; 318*7c478bd9Sstevel@tonic-gate goto out; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 321*7c478bd9Sstevel@tonic-gate ret = EROFS; 322*7c478bd9Sstevel@tonic-gate goto out; 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate default: 325*7c478bd9Sstevel@tonic-gate scfdie(); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, propname, 330*7c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN) != 0) { 331*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 332*7c478bd9Sstevel@tonic-gate scfdie(); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, propname, 335*7c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN) != 0) 336*7c478bd9Sstevel@tonic-gate scfdie(); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, v); 340*7c478bd9Sstevel@tonic-gate assert(r == 0); 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate r = scf_transaction_commit(tx); 343*7c478bd9Sstevel@tonic-gate if (r == 1) 344*7c478bd9Sstevel@tonic-gate break; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate scf_transaction_reset(tx); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate if (r != 0) { 349*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 350*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 351*7c478bd9Sstevel@tonic-gate ret = EPERM; 352*7c478bd9Sstevel@tonic-gate goto out; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 355*7c478bd9Sstevel@tonic-gate ret = EROFS; 356*7c478bd9Sstevel@tonic-gate goto out; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate default: 359*7c478bd9Sstevel@tonic-gate scfdie(); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) 364*7c478bd9Sstevel@tonic-gate scfdie(); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate out: 368*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx); 369*7c478bd9Sstevel@tonic-gate scf_entry_destroy(ent); 370*7c478bd9Sstevel@tonic-gate scf_value_destroy(v); 371*7c478bd9Sstevel@tonic-gate return (ret); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate /* 375*7c478bd9Sstevel@tonic-gate * Gets the single astring value of the propname property of pg. prop & v are 376*7c478bd9Sstevel@tonic-gate * scratch space. Returns the length of the string on success or 377*7c478bd9Sstevel@tonic-gate * -ENOENT - pg has no property named propname 378*7c478bd9Sstevel@tonic-gate * -E2BIG - property has no values or multiple values 379*7c478bd9Sstevel@tonic-gate * -EINVAL - property type is not compatible with astring 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate ssize_t 382*7c478bd9Sstevel@tonic-gate get_astring_prop(const scf_propertygroup_t *pg, const char *propname, 383*7c478bd9Sstevel@tonic-gate scf_property_t *prop, scf_value_t *v, char *buf, size_t bufsz) 384*7c478bd9Sstevel@tonic-gate { 385*7c478bd9Sstevel@tonic-gate ssize_t sz; 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, prop) != 0) { 388*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 389*7c478bd9Sstevel@tonic-gate scfdie(); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate return (-ENOENT); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, v) != 0) { 395*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 396*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 397*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 398*7c478bd9Sstevel@tonic-gate return (-E2BIG); 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate default: 401*7c478bd9Sstevel@tonic-gate scfdie(); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate sz = scf_value_get_astring(v, buf, bufsz); 406*7c478bd9Sstevel@tonic-gate if (sz < 0) { 407*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH) 408*7c478bd9Sstevel@tonic-gate scfdie(); 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate return (-EINVAL); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate return (sz); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* 417*7c478bd9Sstevel@tonic-gate * Returns 418*7c478bd9Sstevel@tonic-gate * 0 - success 419*7c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted 420*7c478bd9Sstevel@tonic-gate * EPERM - permission denied 421*7c478bd9Sstevel@tonic-gate * EACCES - access denied 422*7c478bd9Sstevel@tonic-gate * EROFS - readonly 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate static int 425*7c478bd9Sstevel@tonic-gate delete_prop(scf_propertygroup_t *pg, const char *propname) 426*7c478bd9Sstevel@tonic-gate { 427*7c478bd9Sstevel@tonic-gate scf_transaction_t *tx; 428*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ent; 429*7c478bd9Sstevel@tonic-gate int ret = 0, r; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate if ((tx = scf_transaction_create(h)) == NULL || 432*7c478bd9Sstevel@tonic-gate (ent = scf_entry_create(h)) == NULL) 433*7c478bd9Sstevel@tonic-gate scfdie(); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate for (;;) { 436*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) == -1) { 437*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 438*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 439*7c478bd9Sstevel@tonic-gate ret = ECANCELED; 440*7c478bd9Sstevel@tonic-gate goto out; 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 443*7c478bd9Sstevel@tonic-gate ret = EPERM; 444*7c478bd9Sstevel@tonic-gate goto out; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 447*7c478bd9Sstevel@tonic-gate ret = EACCES; 448*7c478bd9Sstevel@tonic-gate goto out; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 451*7c478bd9Sstevel@tonic-gate ret = EROFS; 452*7c478bd9Sstevel@tonic-gate goto out; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 455*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 456*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 457*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 458*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 459*7c478bd9Sstevel@tonic-gate default: 460*7c478bd9Sstevel@tonic-gate scfdie(); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_delete(tx, ent, propname) == -1) 465*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 466*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 467*7c478bd9Sstevel@tonic-gate ret = ECANCELED; 468*7c478bd9Sstevel@tonic-gate goto out; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 471*7c478bd9Sstevel@tonic-gate ret = 0; 472*7c478bd9Sstevel@tonic-gate goto out; 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 475*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 476*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 477*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 478*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 479*7c478bd9Sstevel@tonic-gate default: 480*7c478bd9Sstevel@tonic-gate scfdie(); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate r = scf_transaction_commit(tx); 484*7c478bd9Sstevel@tonic-gate if (r == 1) 485*7c478bd9Sstevel@tonic-gate break; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate scf_transaction_reset(tx); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if (r != 0) { 490*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 491*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 492*7c478bd9Sstevel@tonic-gate ret = ECANCELED; 493*7c478bd9Sstevel@tonic-gate goto out; 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 496*7c478bd9Sstevel@tonic-gate ret = EPERM; 497*7c478bd9Sstevel@tonic-gate goto out; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 500*7c478bd9Sstevel@tonic-gate ret = EACCES; 501*7c478bd9Sstevel@tonic-gate goto out; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 504*7c478bd9Sstevel@tonic-gate ret = EROFS; 505*7c478bd9Sstevel@tonic-gate goto out; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 508*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 509*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 510*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 511*7c478bd9Sstevel@tonic-gate default: 512*7c478bd9Sstevel@tonic-gate scfdie(); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 517*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 518*7c478bd9Sstevel@tonic-gate scfdie(); 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate ret = ECANCELED; 521*7c478bd9Sstevel@tonic-gate goto out; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate out: 526*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx); 527*7c478bd9Sstevel@tonic-gate scf_entry_destroy(ent); 528*7c478bd9Sstevel@tonic-gate return (ret); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate /* 532*7c478bd9Sstevel@tonic-gate * Returns 0 or EPERM. 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate static int 535*7c478bd9Sstevel@tonic-gate pg_get_or_add(scf_instance_t *inst, const char *pgname, const char *pgtype, 536*7c478bd9Sstevel@tonic-gate uint32_t pgflags, scf_propertygroup_t *pg) 537*7c478bd9Sstevel@tonic-gate { 538*7c478bd9Sstevel@tonic-gate again: 539*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) == 0) 540*7c478bd9Sstevel@tonic-gate return (0); 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 543*7c478bd9Sstevel@tonic-gate scfdie(); 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, pgname, pgtype, pgflags, pg) == 0) 546*7c478bd9Sstevel@tonic-gate return (0); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 549*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 550*7c478bd9Sstevel@tonic-gate goto again; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 553*7c478bd9Sstevel@tonic-gate return (EPERM); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate default: 556*7c478bd9Sstevel@tonic-gate scfdie(); 557*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate /* 562*7c478bd9Sstevel@tonic-gate * Enable or disable inst, per enable. If temp is true, set 563*7c478bd9Sstevel@tonic-gate * general_ovr/enabled. Otherwise set general/enabled and delete 564*7c478bd9Sstevel@tonic-gate * general_ovr/enabled if it exists (order is important here: we don't want the 565*7c478bd9Sstevel@tonic-gate * enabled status to glitch). 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate static void 568*7c478bd9Sstevel@tonic-gate set_inst_enabled(const char *fmri, scf_instance_t *inst, boolean_t temp, 569*7c478bd9Sstevel@tonic-gate boolean_t enable) 570*7c478bd9Sstevel@tonic-gate { 571*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 572*7c478bd9Sstevel@tonic-gate uint8_t b; 573*7c478bd9Sstevel@tonic-gate const char *pgname = NULL; /* For emsg_pg_perm_denied */ 574*7c478bd9Sstevel@tonic-gate int r; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 577*7c478bd9Sstevel@tonic-gate if (pg == NULL) 578*7c478bd9Sstevel@tonic-gate scfdie(); 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate if (temp) { 581*7c478bd9Sstevel@tonic-gate /* Set general_ovr/enabled */ 582*7c478bd9Sstevel@tonic-gate pgname = SCF_PG_GENERAL_OVR; 583*7c478bd9Sstevel@tonic-gate if (pg_get_or_add(inst, pgname, SCF_PG_GENERAL_OVR_TYPE, 584*7c478bd9Sstevel@tonic-gate SCF_PG_GENERAL_OVR_FLAGS, pg) != 0) 585*7c478bd9Sstevel@tonic-gate goto eperm; 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate switch (set_bool_prop(pg, SCF_PROPERTY_ENABLED, enable) != 0) { 588*7c478bd9Sstevel@tonic-gate case 0: 589*7c478bd9Sstevel@tonic-gate break; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate case EPERM: 592*7c478bd9Sstevel@tonic-gate goto eperm; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate case EROFS: 595*7c478bd9Sstevel@tonic-gate /* Shouldn't happen, but it can. */ 596*7c478bd9Sstevel@tonic-gate if (!verbose) 597*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Repository read-only.\n"), 598*7c478bd9Sstevel@tonic-gate fmri); 599*7c478bd9Sstevel@tonic-gate else 600*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Could not set %s/%s " 601*7c478bd9Sstevel@tonic-gate "(repository read-only).\n"), fmri, 602*7c478bd9Sstevel@tonic-gate SCF_PG_GENERAL_OVR, SCF_PROPERTY_ENABLED); 603*7c478bd9Sstevel@tonic-gate goto out; 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate default: 606*7c478bd9Sstevel@tonic-gate assert(0); 607*7c478bd9Sstevel@tonic-gate abort(); 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate if (verbose) 611*7c478bd9Sstevel@tonic-gate (void) printf(enable ? 612*7c478bd9Sstevel@tonic-gate gettext("%s temporarily enabled.\n") : 613*7c478bd9Sstevel@tonic-gate gettext("%s temporarily disabled.\n"), fmri); 614*7c478bd9Sstevel@tonic-gate } else { 615*7c478bd9Sstevel@tonic-gate again: 616*7c478bd9Sstevel@tonic-gate pgname = SCF_PG_GENERAL; 617*7c478bd9Sstevel@tonic-gate if (pg_get_or_add(inst, pgname, SCF_PG_GENERAL_TYPE, 618*7c478bd9Sstevel@tonic-gate SCF_PG_GENERAL_FLAGS, pg) != 0) 619*7c478bd9Sstevel@tonic-gate goto eperm; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate switch (set_bool_prop(pg, SCF_PROPERTY_ENABLED, enable)) { 622*7c478bd9Sstevel@tonic-gate case 0: 623*7c478bd9Sstevel@tonic-gate break; 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate case EPERM: 626*7c478bd9Sstevel@tonic-gate goto eperm; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate case EROFS: 629*7c478bd9Sstevel@tonic-gate /* 630*7c478bd9Sstevel@tonic-gate * If general/enabled is already set the way we want, 631*7c478bd9Sstevel@tonic-gate * proceed. 632*7c478bd9Sstevel@tonic-gate */ 633*7c478bd9Sstevel@tonic-gate switch (get_bool_prop(pg, SCF_PROPERTY_ENABLED, &b)) { 634*7c478bd9Sstevel@tonic-gate case 0: 635*7c478bd9Sstevel@tonic-gate if ((b != 0) == (enable != B_FALSE)) 636*7c478bd9Sstevel@tonic-gate break; 637*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate case ENOENT: 640*7c478bd9Sstevel@tonic-gate case EINVAL: 641*7c478bd9Sstevel@tonic-gate case E2BIG: 642*7c478bd9Sstevel@tonic-gate if (!verbose) 643*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Repository " 644*7c478bd9Sstevel@tonic-gate "read-only.\n"), fmri); 645*7c478bd9Sstevel@tonic-gate else 646*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Could not set " 647*7c478bd9Sstevel@tonic-gate "%s/%s (repository read-only).\n"), 648*7c478bd9Sstevel@tonic-gate fmri, SCF_PG_GENERAL, 649*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENABLED); 650*7c478bd9Sstevel@tonic-gate goto out; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate case ECANCELED: 653*7c478bd9Sstevel@tonic-gate goto again; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate default: 656*7c478bd9Sstevel@tonic-gate assert(0); 657*7c478bd9Sstevel@tonic-gate abort(); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate break; 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate default: 662*7c478bd9Sstevel@tonic-gate assert(0); 663*7c478bd9Sstevel@tonic-gate abort(); 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate pgname = SCF_PG_GENERAL_OVR; 667*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) == 0) { 668*7c478bd9Sstevel@tonic-gate r = delete_prop(pg, SCF_PROPERTY_ENABLED); 669*7c478bd9Sstevel@tonic-gate switch (r) { 670*7c478bd9Sstevel@tonic-gate case 0: 671*7c478bd9Sstevel@tonic-gate break; 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate case ECANCELED: 674*7c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri); 675*7c478bd9Sstevel@tonic-gate goto out; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate case EPERM: 678*7c478bd9Sstevel@tonic-gate goto eperm; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate case EACCES: 681*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s " 682*7c478bd9Sstevel@tonic-gate "property of %s: backend access denied.\n"), 683*7c478bd9Sstevel@tonic-gate pgname, SCF_PROPERTY_ENABLED, fmri); 684*7c478bd9Sstevel@tonic-gate goto out; 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate case EROFS: 687*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s " 688*7c478bd9Sstevel@tonic-gate "property of %s: backend is read-only.\n"), 689*7c478bd9Sstevel@tonic-gate pgname, SCF_PROPERTY_ENABLED, fmri); 690*7c478bd9Sstevel@tonic-gate goto out; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate default: 693*7c478bd9Sstevel@tonic-gate bad_error("delete_prop", r); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate } else { 696*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 697*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 698*7c478bd9Sstevel@tonic-gate /* Print something? */ 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 701*7c478bd9Sstevel@tonic-gate break; 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 704*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 705*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 706*7c478bd9Sstevel@tonic-gate assert(0); 707*7c478bd9Sstevel@tonic-gate abort(); 708*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 711*7c478bd9Sstevel@tonic-gate default: 712*7c478bd9Sstevel@tonic-gate scfdie(); 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if (verbose) 717*7c478bd9Sstevel@tonic-gate (void) printf(enable ? gettext("%s enabled.\n") : 718*7c478bd9Sstevel@tonic-gate gettext("%s disabled.\n"), fmri); 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 722*7c478bd9Sstevel@tonic-gate return; 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate eperm: 725*7c478bd9Sstevel@tonic-gate assert(pgname != NULL); 726*7c478bd9Sstevel@tonic-gate if (!verbose) 727*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 728*7c478bd9Sstevel@tonic-gate else 729*7c478bd9Sstevel@tonic-gate uu_warn(emsg_pg_perm_denied, fmri, pgname); 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate out: 732*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 733*7c478bd9Sstevel@tonic-gate exit_status = 1; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate /* 737*7c478bd9Sstevel@tonic-gate * Set inst to the instance which corresponds to fmri. If fmri identifies 738*7c478bd9Sstevel@tonic-gate * a service with a single instance, get that instance. 739*7c478bd9Sstevel@tonic-gate * 740*7c478bd9Sstevel@tonic-gate * Fails with 741*7c478bd9Sstevel@tonic-gate * ENOTSUP - fmri has an unsupported scheme 742*7c478bd9Sstevel@tonic-gate * EINVAL - fmri is invalid 743*7c478bd9Sstevel@tonic-gate * ENOTDIR - fmri does not identify a service or instance 744*7c478bd9Sstevel@tonic-gate * ENOENT - could not locate instance 745*7c478bd9Sstevel@tonic-gate * E2BIG - fmri is a service with multiple instances (warning not printed) 746*7c478bd9Sstevel@tonic-gate */ 747*7c478bd9Sstevel@tonic-gate static int 748*7c478bd9Sstevel@tonic-gate get_inst_mult(const char *fmri, scf_instance_t *inst) 749*7c478bd9Sstevel@tonic-gate { 750*7c478bd9Sstevel@tonic-gate char *cfmri; 751*7c478bd9Sstevel@tonic-gate const char *svc_name, *inst_name, *pg_name; 752*7c478bd9Sstevel@tonic-gate scf_service_t *svc; 753*7c478bd9Sstevel@tonic-gate scf_instance_t *inst2; 754*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 755*7c478bd9Sstevel@tonic-gate int ret; 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate if (strncmp(fmri, "lrc:", sizeof ("lrc:") - 1) == 0) { 758*7c478bd9Sstevel@tonic-gate uu_warn(gettext("FMRI \"%s\" is a legacy service.\n"), fmri); 759*7c478bd9Sstevel@tonic-gate exit_status = 1; 760*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate cfmri = strdup(fmri); 764*7c478bd9Sstevel@tonic-gate if (cfmri == NULL) 765*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(cfmri, NULL, &svc_name, &inst_name, &pg_name, 768*7c478bd9Sstevel@tonic-gate NULL) != SCF_SUCCESS) { 769*7c478bd9Sstevel@tonic-gate free(cfmri); 770*7c478bd9Sstevel@tonic-gate uu_warn(gettext("FMRI \"%s\" is invalid.\n"), fmri); 771*7c478bd9Sstevel@tonic-gate exit_status = 1; 772*7c478bd9Sstevel@tonic-gate return (EINVAL); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate free(cfmri); 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate if (svc_name == NULL || pg_name != NULL) { 778*7c478bd9Sstevel@tonic-gate uu_warn(gettext( 779*7c478bd9Sstevel@tonic-gate "FMRI \"%s\" does not designate a service or instance.\n"), 780*7c478bd9Sstevel@tonic-gate fmri); 781*7c478bd9Sstevel@tonic-gate exit_status = 1; 782*7c478bd9Sstevel@tonic-gate return (ENOTDIR); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate if (inst_name != NULL) { 786*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, 787*7c478bd9Sstevel@tonic-gate NULL, SCF_DECODE_FMRI_EXACT) == 0) 788*7c478bd9Sstevel@tonic-gate return (0); 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 791*7c478bd9Sstevel@tonic-gate scfdie(); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate uu_warn(gettext("No such instance \"%s\".\n"), fmri); 794*7c478bd9Sstevel@tonic-gate exit_status = 1; 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate return (ENOENT); 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate if ((svc = scf_service_create(h)) == NULL || 800*7c478bd9Sstevel@tonic-gate (inst2 = scf_instance_create(h)) == NULL || 801*7c478bd9Sstevel@tonic-gate (iter = scf_iter_create(h)) == NULL) 802*7c478bd9Sstevel@tonic-gate scfdie(); 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, fmri, NULL, svc, NULL, NULL, NULL, 805*7c478bd9Sstevel@tonic-gate SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) { 806*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 807*7c478bd9Sstevel@tonic-gate scfdie(); 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri); 810*7c478bd9Sstevel@tonic-gate exit_status = 1; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate ret = ENOENT; 813*7c478bd9Sstevel@tonic-gate goto out; 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate /* If the service has only one child, use it. */ 817*7c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iter, svc) != SCF_SUCCESS) 818*7c478bd9Sstevel@tonic-gate scfdie(); 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_instance(iter, inst); 821*7c478bd9Sstevel@tonic-gate if (ret < 0) 822*7c478bd9Sstevel@tonic-gate scfdie(); 823*7c478bd9Sstevel@tonic-gate if (ret != 1) { 824*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Service \"%s\" has no instances.\n"), 825*7c478bd9Sstevel@tonic-gate fmri); 826*7c478bd9Sstevel@tonic-gate exit_status = 1; 827*7c478bd9Sstevel@tonic-gate ret = ENOENT; 828*7c478bd9Sstevel@tonic-gate goto out; 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_instance(iter, inst2); 832*7c478bd9Sstevel@tonic-gate if (ret < 0) 833*7c478bd9Sstevel@tonic-gate scfdie(); 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate if (ret != 0) { 836*7c478bd9Sstevel@tonic-gate ret = E2BIG; 837*7c478bd9Sstevel@tonic-gate goto out; 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate ret = 0; 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate out: 843*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 844*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst2); 845*7c478bd9Sstevel@tonic-gate scf_service_destroy(svc); 846*7c478bd9Sstevel@tonic-gate return (ret); 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /* 850*7c478bd9Sstevel@tonic-gate * Same as get_inst_mult(), but on E2BIG prints a warning and returns ENOENT. 851*7c478bd9Sstevel@tonic-gate */ 852*7c478bd9Sstevel@tonic-gate static int 853*7c478bd9Sstevel@tonic-gate get_inst(const char *fmri, scf_instance_t *inst) 854*7c478bd9Sstevel@tonic-gate { 855*7c478bd9Sstevel@tonic-gate int r; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate r = get_inst_mult(fmri, inst); 858*7c478bd9Sstevel@tonic-gate if (r != E2BIG) 859*7c478bd9Sstevel@tonic-gate return (r); 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate uu_warn(gettext("operation on service %s is ambiguous; " 862*7c478bd9Sstevel@tonic-gate "instance specification needed.\n"), fmri); 863*7c478bd9Sstevel@tonic-gate return (ENOENT); 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate static char * 867*7c478bd9Sstevel@tonic-gate inst_get_fmri(const scf_instance_t *inst) 868*7c478bd9Sstevel@tonic-gate { 869*7c478bd9Sstevel@tonic-gate ssize_t sz; 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate sz = scf_instance_to_fmri(inst, scratch_fmri, max_scf_fmri_sz); 872*7c478bd9Sstevel@tonic-gate if (sz < 0) 873*7c478bd9Sstevel@tonic-gate scfdie(); 874*7c478bd9Sstevel@tonic-gate if (sz >= max_scf_fmri_sz) 875*7c478bd9Sstevel@tonic-gate uu_die(gettext("scf_instance_to_fmri() returned unexpectedly " 876*7c478bd9Sstevel@tonic-gate "long value.\n")); 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate return (scratch_fmri); 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate static ssize_t 882*7c478bd9Sstevel@tonic-gate dep_get_astring(const char *fmri, const char *pgname, 883*7c478bd9Sstevel@tonic-gate const scf_propertygroup_t *pg, const char *propname, scf_property_t *prop, 884*7c478bd9Sstevel@tonic-gate scf_value_t *v, char *buf, size_t bufsz) 885*7c478bd9Sstevel@tonic-gate { 886*7c478bd9Sstevel@tonic-gate ssize_t sz; 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate sz = get_astring_prop(pg, propname, prop, v, buf, bufsz); 889*7c478bd9Sstevel@tonic-gate if (sz >= 0) 890*7c478bd9Sstevel@tonic-gate return (sz); 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate switch (-sz) { 893*7c478bd9Sstevel@tonic-gate case ENOENT: 894*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s\" dependency " 895*7c478bd9Sstevel@tonic-gate "lacks \"%s\" property.)\n"), fmri, pgname, propname); 896*7c478bd9Sstevel@tonic-gate return (-1); 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate case E2BIG: 899*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" property " 900*7c478bd9Sstevel@tonic-gate "is not single-valued.)\n"), fmri, pgname, propname); 901*7c478bd9Sstevel@tonic-gate return (-1); 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate case EINVAL: 904*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" property " 905*7c478bd9Sstevel@tonic-gate "is not of astring type.)\n"), fmri, pgname, propname); 906*7c478bd9Sstevel@tonic-gate return (-1); 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate default: 909*7c478bd9Sstevel@tonic-gate assert(0); 910*7c478bd9Sstevel@tonic-gate abort(); 911*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate static boolean_t 916*7c478bd9Sstevel@tonic-gate multiple_instances(scf_iter_t *iter, scf_value_t *v, char *buf) 917*7c478bd9Sstevel@tonic-gate { 918*7c478bd9Sstevel@tonic-gate int count = 0, r; 919*7c478bd9Sstevel@tonic-gate boolean_t ret; 920*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate inst = scf_instance_create(h); 923*7c478bd9Sstevel@tonic-gate if (inst == NULL) 924*7c478bd9Sstevel@tonic-gate scfdie(); 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate for (;;) { 927*7c478bd9Sstevel@tonic-gate r = scf_iter_next_value(iter, v); 928*7c478bd9Sstevel@tonic-gate if (r == 0) { 929*7c478bd9Sstevel@tonic-gate ret = B_FALSE; 930*7c478bd9Sstevel@tonic-gate goto out; 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate if (r != 1) 933*7c478bd9Sstevel@tonic-gate scfdie(); 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(v, buf, max_scf_fmri_sz) < 0) 936*7c478bd9Sstevel@tonic-gate scfdie(); 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate switch (get_inst_mult(buf, inst)) { 939*7c478bd9Sstevel@tonic-gate case 0: 940*7c478bd9Sstevel@tonic-gate ++count; 941*7c478bd9Sstevel@tonic-gate if (count > 1) { 942*7c478bd9Sstevel@tonic-gate ret = B_TRUE; 943*7c478bd9Sstevel@tonic-gate goto out; 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate break; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate case ENOTSUP: 948*7c478bd9Sstevel@tonic-gate case EINVAL: 949*7c478bd9Sstevel@tonic-gate case ENOTDIR: 950*7c478bd9Sstevel@tonic-gate case ENOENT: 951*7c478bd9Sstevel@tonic-gate continue; 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate case E2BIG: 954*7c478bd9Sstevel@tonic-gate ret = B_TRUE; 955*7c478bd9Sstevel@tonic-gate goto out; 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate default: 958*7c478bd9Sstevel@tonic-gate assert(0); 959*7c478bd9Sstevel@tonic-gate abort(); 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate out: 964*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 965*7c478bd9Sstevel@tonic-gate return (ret); 966*7c478bd9Sstevel@tonic-gate } 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate /* 969*7c478bd9Sstevel@tonic-gate * Enable the service or instance identified by fmri and its dependencies, 970*7c478bd9Sstevel@tonic-gate * recursively. Specifically, call get_inst(fmri), enable the result, and 971*7c478bd9Sstevel@tonic-gate * recurse on its restarter and the dependencies. To avoid duplication of 972*7c478bd9Sstevel@tonic-gate * effort or looping around a dependency cycle, each FMRI is entered into the 973*7c478bd9Sstevel@tonic-gate * "visited" hash table. While recursing, the hash table entry is marked 974*7c478bd9Sstevel@tonic-gate * "active", so that if we come upon it again, we know we've hit a cycle. 975*7c478bd9Sstevel@tonic-gate * exclude_all and optional_all dependencies are ignored. require_any 976*7c478bd9Sstevel@tonic-gate * dependencies are followed only if they comprise a single service; otherwise 977*7c478bd9Sstevel@tonic-gate * the user is warned. 978*7c478bd9Sstevel@tonic-gate * 979*7c478bd9Sstevel@tonic-gate * fmri must point to a writable max_scf_fmri_sz buffer. Returns EINVAL if fmri 980*7c478bd9Sstevel@tonic-gate * is invalid, E2BIG if fmri identifies a service with multiple instances, ELOOP 981*7c478bd9Sstevel@tonic-gate * on cycle detection, or 0 on success. 982*7c478bd9Sstevel@tonic-gate */ 983*7c478bd9Sstevel@tonic-gate static int 984*7c478bd9Sstevel@tonic-gate enable_fmri_rec(char *fmri, boolean_t temp) 985*7c478bd9Sstevel@tonic-gate { 986*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 987*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 988*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 989*7c478bd9Sstevel@tonic-gate scf_property_t *prop; 990*7c478bd9Sstevel@tonic-gate scf_value_t *v; 991*7c478bd9Sstevel@tonic-gate scf_iter_t *pg_iter, *val_iter; 992*7c478bd9Sstevel@tonic-gate scf_type_t ty; 993*7c478bd9Sstevel@tonic-gate char *buf, *pgname; 994*7c478bd9Sstevel@tonic-gate ssize_t name_sz, len, sz; 995*7c478bd9Sstevel@tonic-gate int ret; 996*7c478bd9Sstevel@tonic-gate struct ht_elt *he; 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate len = scf_canonify_fmri(fmri, fmri, max_scf_fmri_sz); 999*7c478bd9Sstevel@tonic-gate if (len < 0) { 1000*7c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_INVALID_ARGUMENT); 1001*7c478bd9Sstevel@tonic-gate return (EINVAL); 1002*7c478bd9Sstevel@tonic-gate } 1003*7c478bd9Sstevel@tonic-gate assert(len < max_scf_fmri_sz); 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate switch (visited_find_or_add(fmri, &he)) { 1006*7c478bd9Sstevel@tonic-gate case 0: 1007*7c478bd9Sstevel@tonic-gate he->active = B_TRUE; 1008*7c478bd9Sstevel@tonic-gate break; 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate case 1: 1011*7c478bd9Sstevel@tonic-gate return (he->active ? ELOOP : 0); 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate case -1: 1014*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate default: 1017*7c478bd9Sstevel@tonic-gate assert(0); 1018*7c478bd9Sstevel@tonic-gate abort(); 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate inst = scf_instance_create(h); 1022*7c478bd9Sstevel@tonic-gate if (inst == NULL) 1023*7c478bd9Sstevel@tonic-gate scfdie(); 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate switch (get_inst_mult(fmri, inst)) { 1026*7c478bd9Sstevel@tonic-gate case 0: 1027*7c478bd9Sstevel@tonic-gate break; 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate case E2BIG: 1030*7c478bd9Sstevel@tonic-gate he->active = B_FALSE; 1031*7c478bd9Sstevel@tonic-gate return (E2BIG); 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate default: 1034*7c478bd9Sstevel@tonic-gate he->active = B_FALSE; 1035*7c478bd9Sstevel@tonic-gate return (0); 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate set_inst_enabled(fmri, inst, temp, B_TRUE); 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate if ((snap = scf_snapshot_create(h)) == NULL || 1041*7c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 1042*7c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 1043*7c478bd9Sstevel@tonic-gate (v = scf_value_create(h)) == NULL || 1044*7c478bd9Sstevel@tonic-gate (pg_iter = scf_iter_create(h)) == NULL || 1045*7c478bd9Sstevel@tonic-gate (val_iter = scf_iter_create(h)) == NULL) 1046*7c478bd9Sstevel@tonic-gate scfdie(); 1047*7c478bd9Sstevel@tonic-gate 1048*7c478bd9Sstevel@tonic-gate buf = malloc(max_scf_fmri_sz); 1049*7c478bd9Sstevel@tonic-gate if (buf == NULL) 1050*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate name_sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH); 1053*7c478bd9Sstevel@tonic-gate if (name_sz < 0) 1054*7c478bd9Sstevel@tonic-gate scfdie(); 1055*7c478bd9Sstevel@tonic-gate ++name_sz; 1056*7c478bd9Sstevel@tonic-gate pgname = malloc(name_sz); 1057*7c478bd9Sstevel@tonic-gate if (pgname == NULL) 1058*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", snap) != 0) { 1061*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1062*7c478bd9Sstevel@tonic-gate scfdie(); 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 1065*7c478bd9Sstevel@tonic-gate snap = NULL; 1066*7c478bd9Sstevel@tonic-gate } 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate /* Enable restarter */ 1069*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_GENERAL, pg) != 0) { 1070*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1071*7c478bd9Sstevel@tonic-gate scfdie(); 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (lacks \"%s\" " 1074*7c478bd9Sstevel@tonic-gate "property group).\n"), fmri, SCF_PG_GENERAL); 1075*7c478bd9Sstevel@tonic-gate ret = 0; 1076*7c478bd9Sstevel@tonic-gate goto out; 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate sz = get_astring_prop(pg, SCF_PROPERTY_RESTARTER, prop, v, buf, 1080*7c478bd9Sstevel@tonic-gate max_scf_fmri_sz); 1081*7c478bd9Sstevel@tonic-gate if (sz > max_scf_fmri_sz) { 1082*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (the value of " 1083*7c478bd9Sstevel@tonic-gate "\"%s/%s\" is too long).\n"), fmri, SCF_PG_GENERAL, 1084*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_RESTARTER); 1085*7c478bd9Sstevel@tonic-gate ret = 0; 1086*7c478bd9Sstevel@tonic-gate goto out; 1087*7c478bd9Sstevel@tonic-gate } else if (sz >= 0) { 1088*7c478bd9Sstevel@tonic-gate switch (enable_fmri_rec(buf, temp)) { 1089*7c478bd9Sstevel@tonic-gate case 0: 1090*7c478bd9Sstevel@tonic-gate break; 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate case EINVAL: 1093*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Restarter FMRI for \"%s\" is " 1094*7c478bd9Sstevel@tonic-gate "invalid.\n"), fmri); 1095*7c478bd9Sstevel@tonic-gate break; 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate case E2BIG: 1098*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Restarter FMRI for \"%s\" identifies " 1099*7c478bd9Sstevel@tonic-gate "a service with multiple instances.\n"), fmri); 1100*7c478bd9Sstevel@tonic-gate break; 1101*7c478bd9Sstevel@tonic-gate 1102*7c478bd9Sstevel@tonic-gate case ELOOP: 1103*7c478bd9Sstevel@tonic-gate ret = ELOOP; 1104*7c478bd9Sstevel@tonic-gate goto out; 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate default: 1107*7c478bd9Sstevel@tonic-gate assert(0); 1108*7c478bd9Sstevel@tonic-gate abort(); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate } else if (sz < 0) { 1111*7c478bd9Sstevel@tonic-gate switch (-sz) { 1112*7c478bd9Sstevel@tonic-gate case ENOENT: 1113*7c478bd9Sstevel@tonic-gate break; 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate case E2BIG: 1116*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" " 1117*7c478bd9Sstevel@tonic-gate "property is not single-valued).\n"), fmri, 1118*7c478bd9Sstevel@tonic-gate SCF_PG_GENERAL, SCF_PROPERTY_RESTARTER); 1119*7c478bd9Sstevel@tonic-gate ret = 0; 1120*7c478bd9Sstevel@tonic-gate goto out; 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate case EINVAL: 1123*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s/%s\" " 1124*7c478bd9Sstevel@tonic-gate "property is not of astring type).\n"), fmri, 1125*7c478bd9Sstevel@tonic-gate SCF_PG_GENERAL, SCF_PROPERTY_RESTARTER); 1126*7c478bd9Sstevel@tonic-gate ret = 0; 1127*7c478bd9Sstevel@tonic-gate goto out; 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate default: 1130*7c478bd9Sstevel@tonic-gate assert(0); 1131*7c478bd9Sstevel@tonic-gate abort(); 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(pg_iter, inst, snap, 1136*7c478bd9Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) == -1) 1137*7c478bd9Sstevel@tonic-gate scfdie(); 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate while (scf_iter_next_pg(pg_iter, pg) > 0) { 1140*7c478bd9Sstevel@tonic-gate len = scf_pg_get_name(pg, pgname, name_sz); 1141*7c478bd9Sstevel@tonic-gate if (len < 0) 1142*7c478bd9Sstevel@tonic-gate scfdie(); 1143*7c478bd9Sstevel@tonic-gate assert(len < name_sz); 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate if (dep_get_astring(fmri, pgname, pg, SCF_PROPERTY_TYPE, prop, 1146*7c478bd9Sstevel@tonic-gate v, buf, max_scf_fmri_sz) < 0) 1147*7c478bd9Sstevel@tonic-gate continue; 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate if (strcmp(buf, "service") != 0) 1150*7c478bd9Sstevel@tonic-gate continue; 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate if (dep_get_astring(fmri, pgname, pg, SCF_PROPERTY_GROUPING, 1153*7c478bd9Sstevel@tonic-gate prop, v, buf, max_scf_fmri_sz) < 0) 1154*7c478bd9Sstevel@tonic-gate continue; 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate if (strcmp(buf, SCF_DEP_EXCLUDE_ALL) == 0 || 1157*7c478bd9Sstevel@tonic-gate strcmp(buf, SCF_DEP_OPTIONAL_ALL) == 0) 1158*7c478bd9Sstevel@tonic-gate continue; 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate if (strcmp(buf, SCF_DEP_REQUIRE_ALL) != 0 && 1161*7c478bd9Sstevel@tonic-gate strcmp(buf, SCF_DEP_REQUIRE_ANY) != 0) { 1162*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Dependency \"%s\" of \"%s\" has " 1163*7c478bd9Sstevel@tonic-gate "unknown type \"%s\".\n"), pgname, fmri, buf); 1164*7c478bd9Sstevel@tonic-gate continue; 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, prop) == 1168*7c478bd9Sstevel@tonic-gate -1) { 1169*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1170*7c478bd9Sstevel@tonic-gate scfdie(); 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (\"%s\" " 1173*7c478bd9Sstevel@tonic-gate "dependency lacks \"%s\" property.)\n"), fmri, 1174*7c478bd9Sstevel@tonic-gate pgname, SCF_PROPERTY_ENTITIES); 1175*7c478bd9Sstevel@tonic-gate continue; 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS) 1179*7c478bd9Sstevel@tonic-gate scfdie(); 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_FMRI) { 1182*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" is misconfigured (property " 1183*7c478bd9Sstevel@tonic-gate "\"%s/%s\" is not of fmri type).\n"), fmri, pgname, 1184*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENTITIES); 1185*7c478bd9Sstevel@tonic-gate continue; 1186*7c478bd9Sstevel@tonic-gate } 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(val_iter, prop) == -1) 1189*7c478bd9Sstevel@tonic-gate scfdie(); 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate if (strcmp(buf, SCF_DEP_REQUIRE_ANY) == 0) { 1192*7c478bd9Sstevel@tonic-gate if (multiple_instances(val_iter, v, buf)) { 1193*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%s requires one of:\n"), 1194*7c478bd9Sstevel@tonic-gate fmri); 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(val_iter, prop) != 1197*7c478bd9Sstevel@tonic-gate 0) 1198*7c478bd9Sstevel@tonic-gate scfdie(); 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate for (;;) { 1201*7c478bd9Sstevel@tonic-gate int r; 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate r = scf_iter_next_value(val_iter, v); 1204*7c478bd9Sstevel@tonic-gate if (r == 0) 1205*7c478bd9Sstevel@tonic-gate break; 1206*7c478bd9Sstevel@tonic-gate if (r != 1) 1207*7c478bd9Sstevel@tonic-gate scfdie(); 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(v, buf, 1210*7c478bd9Sstevel@tonic-gate max_scf_fmri_sz) < 0) 1211*7c478bd9Sstevel@tonic-gate scfdie(); 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate (void) fputs(" ", stdout); 1214*7c478bd9Sstevel@tonic-gate (void) puts(buf); 1215*7c478bd9Sstevel@tonic-gate } 1216*7c478bd9Sstevel@tonic-gate 1217*7c478bd9Sstevel@tonic-gate continue; 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate /* 1221*7c478bd9Sstevel@tonic-gate * Since there's only one instance, we can enable it. 1222*7c478bd9Sstevel@tonic-gate * Reset val_iter and continue. 1223*7c478bd9Sstevel@tonic-gate */ 1224*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(val_iter, prop) != 0) 1225*7c478bd9Sstevel@tonic-gate scfdie(); 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate for (;;) { 1229*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(val_iter, v); 1230*7c478bd9Sstevel@tonic-gate if (ret == 0) 1231*7c478bd9Sstevel@tonic-gate break; 1232*7c478bd9Sstevel@tonic-gate if (ret != 1) 1233*7c478bd9Sstevel@tonic-gate scfdie(); 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(v, buf, max_scf_fmri_sz) == 1236*7c478bd9Sstevel@tonic-gate -1) 1237*7c478bd9Sstevel@tonic-gate scfdie(); 1238*7c478bd9Sstevel@tonic-gate 1239*7c478bd9Sstevel@tonic-gate switch (enable_fmri_rec(buf, temp)) { 1240*7c478bd9Sstevel@tonic-gate case 0: 1241*7c478bd9Sstevel@tonic-gate break; 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate case EINVAL: 1244*7c478bd9Sstevel@tonic-gate uu_warn(gettext("\"%s\" dependency of \"%s\" " 1245*7c478bd9Sstevel@tonic-gate "has invalid FMRI \"%s\".\n"), pgname, 1246*7c478bd9Sstevel@tonic-gate fmri, buf); 1247*7c478bd9Sstevel@tonic-gate break; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate case E2BIG: 1250*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s depends on %s, which has " 1251*7c478bd9Sstevel@tonic-gate "multiple instances.\n"), fmri, buf); 1252*7c478bd9Sstevel@tonic-gate break; 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate case ELOOP: 1255*7c478bd9Sstevel@tonic-gate ret = ELOOP; 1256*7c478bd9Sstevel@tonic-gate goto out; 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate default: 1259*7c478bd9Sstevel@tonic-gate assert(0); 1260*7c478bd9Sstevel@tonic-gate abort(); 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate } 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate ret = 0; 1266*7c478bd9Sstevel@tonic-gate 1267*7c478bd9Sstevel@tonic-gate out: 1268*7c478bd9Sstevel@tonic-gate he->active = B_FALSE; 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate free(buf); 1271*7c478bd9Sstevel@tonic-gate free(pgname); 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate (void) scf_value_destroy(v); 1274*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1275*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1276*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 1277*7c478bd9Sstevel@tonic-gate scf_iter_destroy(pg_iter); 1278*7c478bd9Sstevel@tonic-gate scf_iter_destroy(val_iter); 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate return (ret); 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate /* 1284*7c478bd9Sstevel@tonic-gate * fmri here is only used for verbose messages. 1285*7c478bd9Sstevel@tonic-gate */ 1286*7c478bd9Sstevel@tonic-gate static void 1287*7c478bd9Sstevel@tonic-gate set_inst_action(const char *fmri, const scf_instance_t *inst, 1288*7c478bd9Sstevel@tonic-gate const char *action) 1289*7c478bd9Sstevel@tonic-gate { 1290*7c478bd9Sstevel@tonic-gate scf_transaction_t *tx; 1291*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ent; 1292*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 1293*7c478bd9Sstevel@tonic-gate scf_property_t *prop; 1294*7c478bd9Sstevel@tonic-gate scf_value_t *v; 1295*7c478bd9Sstevel@tonic-gate int ret; 1296*7c478bd9Sstevel@tonic-gate int64_t t; 1297*7c478bd9Sstevel@tonic-gate hrtime_t timestamp; 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate const char * const scf_pg_restarter_actions = SCF_PG_RESTARTER_ACTIONS; 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate if ((pg = scf_pg_create(h)) == NULL || 1302*7c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 1303*7c478bd9Sstevel@tonic-gate (v = scf_value_create(h)) == NULL || 1304*7c478bd9Sstevel@tonic-gate (tx = scf_transaction_create(h)) == NULL || 1305*7c478bd9Sstevel@tonic-gate (ent = scf_entry_create(h)) == NULL) 1306*7c478bd9Sstevel@tonic-gate scfdie(); 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, scf_pg_restarter_actions, pg) == -1) { 1309*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1310*7c478bd9Sstevel@tonic-gate scfdie(); 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate /* Try creating the restarter_actions property group. */ 1313*7c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, scf_pg_restarter_actions, 1314*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_ACTIONS_TYPE, 1315*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_ACTIONS_FLAGS, pg) == -1) { 1316*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1317*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 1318*7c478bd9Sstevel@tonic-gate /* Someone must have added it. */ 1319*7c478bd9Sstevel@tonic-gate break; 1320*7c478bd9Sstevel@tonic-gate 1321*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1322*7c478bd9Sstevel@tonic-gate if (!verbose) 1323*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 1324*7c478bd9Sstevel@tonic-gate else 1325*7c478bd9Sstevel@tonic-gate uu_warn(emsg_create_pg_perm_denied, 1326*7c478bd9Sstevel@tonic-gate fmri, scf_pg_restarter_actions); 1327*7c478bd9Sstevel@tonic-gate goto out; 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate default: 1330*7c478bd9Sstevel@tonic-gate scfdie(); 1331*7c478bd9Sstevel@tonic-gate } 1332*7c478bd9Sstevel@tonic-gate } 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate /* 1336*7c478bd9Sstevel@tonic-gate * If we lose the transaction race and need to retry, there are 2 1337*7c478bd9Sstevel@tonic-gate * potential other winners: 1338*7c478bd9Sstevel@tonic-gate * - another process setting actions 1339*7c478bd9Sstevel@tonic-gate * - the restarter marking the action complete 1340*7c478bd9Sstevel@tonic-gate * Therefore, re-read the property every time through the loop before 1341*7c478bd9Sstevel@tonic-gate * making any decisions based on their values. 1342*7c478bd9Sstevel@tonic-gate */ 1343*7c478bd9Sstevel@tonic-gate do { 1344*7c478bd9Sstevel@tonic-gate timestamp = gethrtime(); 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) == -1) { 1347*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED) 1348*7c478bd9Sstevel@tonic-gate scfdie(); 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate if (!verbose) 1351*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 1352*7c478bd9Sstevel@tonic-gate else 1353*7c478bd9Sstevel@tonic-gate uu_warn(emsg_pg_perm_denied, fmri, 1354*7c478bd9Sstevel@tonic-gate scf_pg_restarter_actions); 1355*7c478bd9Sstevel@tonic-gate goto out; 1356*7c478bd9Sstevel@tonic-gate } 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, action, prop) == -1) { 1359*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1360*7c478bd9Sstevel@tonic-gate scfdie(); 1361*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, 1362*7c478bd9Sstevel@tonic-gate action, SCF_TYPE_INTEGER) == -1) 1363*7c478bd9Sstevel@tonic-gate scfdie(); 1364*7c478bd9Sstevel@tonic-gate goto action_set; 1365*7c478bd9Sstevel@tonic-gate } else { 1366*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, 1367*7c478bd9Sstevel@tonic-gate action, SCF_TYPE_INTEGER) == -1) 1368*7c478bd9Sstevel@tonic-gate scfdie(); 1369*7c478bd9Sstevel@tonic-gate } 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, v) == -1) { 1372*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1373*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 1374*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1375*7c478bd9Sstevel@tonic-gate /* Misconfigured, so set anyway. */ 1376*7c478bd9Sstevel@tonic-gate goto action_set; 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate default: 1379*7c478bd9Sstevel@tonic-gate scfdie(); 1380*7c478bd9Sstevel@tonic-gate } 1381*7c478bd9Sstevel@tonic-gate } else { 1382*7c478bd9Sstevel@tonic-gate if (scf_value_get_integer(v, &t) == -1) { 1383*7c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_TYPE_MISMATCH); 1384*7c478bd9Sstevel@tonic-gate goto action_set; 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate if (t > timestamp) 1387*7c478bd9Sstevel@tonic-gate break; 1388*7c478bd9Sstevel@tonic-gate } 1389*7c478bd9Sstevel@tonic-gate 1390*7c478bd9Sstevel@tonic-gate action_set: 1391*7c478bd9Sstevel@tonic-gate scf_value_set_integer(v, timestamp); 1392*7c478bd9Sstevel@tonic-gate if (scf_entry_add_value(ent, v) == -1) 1393*7c478bd9Sstevel@tonic-gate scfdie(); 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(tx); 1396*7c478bd9Sstevel@tonic-gate if (ret == -1) { 1397*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED) 1398*7c478bd9Sstevel@tonic-gate scfdie(); 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate if (!verbose) 1401*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 1402*7c478bd9Sstevel@tonic-gate else 1403*7c478bd9Sstevel@tonic-gate uu_warn(emsg_prop_perm_denied, fmri, 1404*7c478bd9Sstevel@tonic-gate scf_pg_restarter_actions, action); 1405*7c478bd9Sstevel@tonic-gate scf_transaction_reset(tx); 1406*7c478bd9Sstevel@tonic-gate goto out; 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate scf_transaction_reset(tx); 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate if (ret == 0) { 1412*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) 1413*7c478bd9Sstevel@tonic-gate scfdie(); 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate } while (ret == 0); 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate if (verbose) 1418*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Action %s set for %s.\n"), action, fmri); 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate out: 1421*7c478bd9Sstevel@tonic-gate scf_value_destroy(v); 1422*7c478bd9Sstevel@tonic-gate scf_entry_destroy(ent); 1423*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx); 1424*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1425*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1426*7c478bd9Sstevel@tonic-gate } 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate /* 1429*7c478bd9Sstevel@tonic-gate * Get the state of inst. state should point to a buffer of 1430*7c478bd9Sstevel@tonic-gate * MAX_SCF_STATE_STRING_SZ bytes. Returns 0 on success or -1 if 1431*7c478bd9Sstevel@tonic-gate * no restarter property group 1432*7c478bd9Sstevel@tonic-gate * no state property 1433*7c478bd9Sstevel@tonic-gate * state property is misconfigured (wrong type, not single-valued) 1434*7c478bd9Sstevel@tonic-gate * state value is too long 1435*7c478bd9Sstevel@tonic-gate * In these cases, fmri is used to print a warning. 1436*7c478bd9Sstevel@tonic-gate * 1437*7c478bd9Sstevel@tonic-gate * If pgp is non-NULL, a successful call to inst_get_state will store 1438*7c478bd9Sstevel@tonic-gate * the SCF_PG_RESTARTER property group in *pgp, and the caller will be 1439*7c478bd9Sstevel@tonic-gate * responsible for calling scf_pg_destroy on the property group. 1440*7c478bd9Sstevel@tonic-gate */ 1441*7c478bd9Sstevel@tonic-gate int 1442*7c478bd9Sstevel@tonic-gate inst_get_state(scf_instance_t *inst, char *state, const char *fmri, 1443*7c478bd9Sstevel@tonic-gate scf_propertygroup_t **pgp) 1444*7c478bd9Sstevel@tonic-gate { 1445*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 1446*7c478bd9Sstevel@tonic-gate scf_property_t *prop; 1447*7c478bd9Sstevel@tonic-gate scf_value_t *val; 1448*7c478bd9Sstevel@tonic-gate int ret = -1; 1449*7c478bd9Sstevel@tonic-gate ssize_t szret; 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate if ((pg = scf_pg_create(h)) == NULL || 1452*7c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 1453*7c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) 1454*7c478bd9Sstevel@tonic-gate scfdie(); 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, pg) != SCF_SUCCESS) { 1457*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1458*7c478bd9Sstevel@tonic-gate scfdie(); 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (lacks \"%s\" property " 1461*7c478bd9Sstevel@tonic-gate "group).\n"), fmri ? fmri : inst_get_fmri(inst), 1462*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER); 1463*7c478bd9Sstevel@tonic-gate goto out; 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate szret = get_astring_prop(pg, SCF_PROPERTY_STATE, prop, val, state, 1467*7c478bd9Sstevel@tonic-gate MAX_SCF_STATE_STRING_SZ); 1468*7c478bd9Sstevel@tonic-gate if (szret < 0) { 1469*7c478bd9Sstevel@tonic-gate switch (-szret) { 1470*7c478bd9Sstevel@tonic-gate case ENOENT: 1471*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s\" property " 1472*7c478bd9Sstevel@tonic-gate "group lacks \"%s\" property).\n"), 1473*7c478bd9Sstevel@tonic-gate fmri ? fmri : inst_get_fmri(inst), SCF_PG_RESTARTER, 1474*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE); 1475*7c478bd9Sstevel@tonic-gate goto out; 1476*7c478bd9Sstevel@tonic-gate 1477*7c478bd9Sstevel@tonic-gate case E2BIG: 1478*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s/%s\" " 1479*7c478bd9Sstevel@tonic-gate "property is not single-valued).\n"), 1480*7c478bd9Sstevel@tonic-gate fmri ? fmri : inst_get_fmri(inst), SCF_PG_RESTARTER, 1481*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE); 1482*7c478bd9Sstevel@tonic-gate goto out; 1483*7c478bd9Sstevel@tonic-gate 1484*7c478bd9Sstevel@tonic-gate case EINVAL: 1485*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s/%s\" " 1486*7c478bd9Sstevel@tonic-gate "property is not of type astring).\n"), 1487*7c478bd9Sstevel@tonic-gate fmri ? fmri : inst_get_fmri(inst), SCF_PG_RESTARTER, 1488*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE); 1489*7c478bd9Sstevel@tonic-gate goto out; 1490*7c478bd9Sstevel@tonic-gate 1491*7c478bd9Sstevel@tonic-gate default: 1492*7c478bd9Sstevel@tonic-gate assert(0); 1493*7c478bd9Sstevel@tonic-gate abort(); 1494*7c478bd9Sstevel@tonic-gate } 1495*7c478bd9Sstevel@tonic-gate } 1496*7c478bd9Sstevel@tonic-gate if (szret >= MAX_SCF_STATE_STRING_SZ) { 1497*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s is misconfigured (\"%s/%s\" property value " 1498*7c478bd9Sstevel@tonic-gate "is too long).\n"), fmri ? fmri : inst_get_fmri(inst), 1499*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER, SCF_PROPERTY_STATE); 1500*7c478bd9Sstevel@tonic-gate goto out; 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate ret = 0; 1504*7c478bd9Sstevel@tonic-gate if (pgp) 1505*7c478bd9Sstevel@tonic-gate *pgp = pg; 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate out: 1508*7c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val); 1509*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1510*7c478bd9Sstevel@tonic-gate if (ret || pgp == NULL) 1511*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1512*7c478bd9Sstevel@tonic-gate return (ret); 1513*7c478bd9Sstevel@tonic-gate } 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate static void 1516*7c478bd9Sstevel@tonic-gate set_astring_prop(const char *fmri, const char *pgname, const char *pgtype, 1517*7c478bd9Sstevel@tonic-gate uint32_t pgflags, const char *propname, const char *str) 1518*7c478bd9Sstevel@tonic-gate { 1519*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 1520*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 1521*7c478bd9Sstevel@tonic-gate scf_property_t *prop; 1522*7c478bd9Sstevel@tonic-gate scf_value_t *val; 1523*7c478bd9Sstevel@tonic-gate scf_transaction_t *tx; 1524*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *txent; 1525*7c478bd9Sstevel@tonic-gate int ret; 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate inst = scf_instance_create(h); 1528*7c478bd9Sstevel@tonic-gate if (inst == NULL) 1529*7c478bd9Sstevel@tonic-gate scfdie(); 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate if (get_inst(fmri, inst) != 0) 1532*7c478bd9Sstevel@tonic-gate return; 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate if ((pg = scf_pg_create(h)) == NULL || 1535*7c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 1536*7c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL || 1537*7c478bd9Sstevel@tonic-gate (tx = scf_transaction_create(h)) == NULL || 1538*7c478bd9Sstevel@tonic-gate (txent = scf_entry_create(h)) == NULL) 1539*7c478bd9Sstevel@tonic-gate scfdie(); 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) != SCF_SUCCESS) { 1542*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1543*7c478bd9Sstevel@tonic-gate scfdie(); 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, pgname, pgtype, pgflags, pg) != 1546*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 1547*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1548*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 1549*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pgname, pg) != 1550*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 1551*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1552*7c478bd9Sstevel@tonic-gate scfdie(); 1553*7c478bd9Sstevel@tonic-gate 1554*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Repository write " 1555*7c478bd9Sstevel@tonic-gate "contention.\n")); 1556*7c478bd9Sstevel@tonic-gate goto out; 1557*7c478bd9Sstevel@tonic-gate } 1558*7c478bd9Sstevel@tonic-gate break; 1559*7c478bd9Sstevel@tonic-gate 1560*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1561*7c478bd9Sstevel@tonic-gate if (!verbose) 1562*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 1563*7c478bd9Sstevel@tonic-gate else 1564*7c478bd9Sstevel@tonic-gate uu_warn(emsg_create_pg_perm_denied, 1565*7c478bd9Sstevel@tonic-gate fmri, pgname); 1566*7c478bd9Sstevel@tonic-gate goto out; 1567*7c478bd9Sstevel@tonic-gate 1568*7c478bd9Sstevel@tonic-gate default: 1569*7c478bd9Sstevel@tonic-gate scfdie(); 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate } 1573*7c478bd9Sstevel@tonic-gate 1574*7c478bd9Sstevel@tonic-gate do { 1575*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, pg) != SCF_SUCCESS) { 1576*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED) 1577*7c478bd9Sstevel@tonic-gate scfdie(); 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate if (!verbose) 1580*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 1581*7c478bd9Sstevel@tonic-gate else 1582*7c478bd9Sstevel@tonic-gate uu_warn(emsg_pg_perm_denied, fmri, pgname); 1583*7c478bd9Sstevel@tonic-gate goto out; 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, txent, propname, 1587*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING) != 0) { 1588*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1589*7c478bd9Sstevel@tonic-gate scfdie(); 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, txent, propname, 1592*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING) != 0) 1593*7c478bd9Sstevel@tonic-gate scfdie(); 1594*7c478bd9Sstevel@tonic-gate } 1595*7c478bd9Sstevel@tonic-gate 1596*7c478bd9Sstevel@tonic-gate if (scf_value_set_astring(val, str) != SCF_SUCCESS) 1597*7c478bd9Sstevel@tonic-gate scfdie(); 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate if (scf_entry_add_value(txent, val) != SCF_SUCCESS) 1600*7c478bd9Sstevel@tonic-gate scfdie(); 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(tx); 1603*7c478bd9Sstevel@tonic-gate if (ret == -1) { 1604*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_PERMISSION_DENIED) 1605*7c478bd9Sstevel@tonic-gate scfdie(); 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate if (!verbose) 1608*7c478bd9Sstevel@tonic-gate uu_warn(emsg_permission_denied, fmri); 1609*7c478bd9Sstevel@tonic-gate else 1610*7c478bd9Sstevel@tonic-gate uu_warn(emsg_prop_perm_denied, fmri, pgname, 1611*7c478bd9Sstevel@tonic-gate propname); 1612*7c478bd9Sstevel@tonic-gate goto out; 1613*7c478bd9Sstevel@tonic-gate } 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate if (ret == 0) { 1616*7c478bd9Sstevel@tonic-gate scf_transaction_reset(tx); 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) != SCF_SUCCESS) 1619*7c478bd9Sstevel@tonic-gate scfdie(); 1620*7c478bd9Sstevel@tonic-gate } 1621*7c478bd9Sstevel@tonic-gate } while (ret == 0); 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate out: 1624*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx); 1625*7c478bd9Sstevel@tonic-gate scf_entry_destroy(txent); 1626*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 1627*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1628*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1629*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 1630*7c478bd9Sstevel@tonic-gate } 1631*7c478bd9Sstevel@tonic-gate 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate /* 1634*7c478bd9Sstevel@tonic-gate * Flags to control enable and disable actions. 1635*7c478bd9Sstevel@tonic-gate */ 1636*7c478bd9Sstevel@tonic-gate #define SET_ENABLED 0x1 1637*7c478bd9Sstevel@tonic-gate #define SET_TEMPORARY 0x2 1638*7c478bd9Sstevel@tonic-gate #define SET_RECURSIVE 0x4 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate static int 1641*7c478bd9Sstevel@tonic-gate set_fmri_enabled(void *data, scf_walkinfo_t *wip) 1642*7c478bd9Sstevel@tonic-gate { 1643*7c478bd9Sstevel@tonic-gate int flags = (int)data; 1644*7c478bd9Sstevel@tonic-gate 1645*7c478bd9Sstevel@tonic-gate assert(wip->inst != NULL); 1646*7c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate if (flags & SET_RECURSIVE) { 1649*7c478bd9Sstevel@tonic-gate char *fmri_buf = malloc(max_scf_fmri_sz); 1650*7c478bd9Sstevel@tonic-gate if (fmri_buf == NULL) 1651*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate visited = calloc(HT_BUCKETS, sizeof (*visited)); 1654*7c478bd9Sstevel@tonic-gate if (visited == NULL) 1655*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate /* scf_walk_fmri() guarantees that fmri isn't too long */ 1658*7c478bd9Sstevel@tonic-gate assert(strlen(wip->fmri) <= max_scf_fmri_sz); 1659*7c478bd9Sstevel@tonic-gate (void) strlcpy(fmri_buf, wip->fmri, max_scf_fmri_sz); 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate switch (enable_fmri_rec(fmri_buf, (flags & SET_TEMPORARY))) { 1662*7c478bd9Sstevel@tonic-gate case E2BIG: 1663*7c478bd9Sstevel@tonic-gate uu_warn(gettext("operation on service %s is ambiguous; " 1664*7c478bd9Sstevel@tonic-gate "instance specification needed.\n"), fmri_buf); 1665*7c478bd9Sstevel@tonic-gate break; 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate case ELOOP: 1668*7c478bd9Sstevel@tonic-gate uu_warn(gettext("%s: Dependency cycle detected.\n"), 1669*7c478bd9Sstevel@tonic-gate fmri_buf); 1670*7c478bd9Sstevel@tonic-gate } 1671*7c478bd9Sstevel@tonic-gate 1672*7c478bd9Sstevel@tonic-gate free(visited); 1673*7c478bd9Sstevel@tonic-gate free(fmri_buf); 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate } else { 1676*7c478bd9Sstevel@tonic-gate set_inst_enabled(wip->fmri, wip->inst, 1677*7c478bd9Sstevel@tonic-gate (flags & SET_TEMPORARY) != 0, (flags & SET_ENABLED) != 0); 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate 1680*7c478bd9Sstevel@tonic-gate return (0); 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1684*7c478bd9Sstevel@tonic-gate static int 1685*7c478bd9Sstevel@tonic-gate wait_fmri_enabled(void *data, scf_walkinfo_t *wip) 1686*7c478bd9Sstevel@tonic-gate { 1687*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 1688*7c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 1689*7c478bd9Sstevel@tonic-gate 1690*7c478bd9Sstevel@tonic-gate assert(wip->inst != NULL); 1691*7c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate do { 1694*7c478bd9Sstevel@tonic-gate if (pg) 1695*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1696*7c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, &pg) != 0) { 1697*7c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE; 1698*7c478bd9Sstevel@tonic-gate return (0); 1699*7c478bd9Sstevel@tonic-gate } 1700*7c478bd9Sstevel@tonic-gate 1701*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 1702*7c478bd9Sstevel@tonic-gate strcmp(state, SCF_STATE_STRING_DEGRADED) == 0) { 1703*7c478bd9Sstevel@tonic-gate /* 1704*7c478bd9Sstevel@tonic-gate * We're done. 1705*7c478bd9Sstevel@tonic-gate */ 1706*7c478bd9Sstevel@tonic-gate goto out; 1707*7c478bd9Sstevel@tonic-gate } 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) { 1710*7c478bd9Sstevel@tonic-gate /* 1711*7c478bd9Sstevel@tonic-gate * The service is ill. 1712*7c478bd9Sstevel@tonic-gate */ 1713*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is in maintenance" 1714*7c478bd9Sstevel@tonic-gate " state.\n"), wip->fmri); 1715*7c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE; 1716*7c478bd9Sstevel@tonic-gate goto out; 1717*7c478bd9Sstevel@tonic-gate } 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate if (!is_enabled(wip->inst)) { 1720*7c478bd9Sstevel@tonic-gate /* 1721*7c478bd9Sstevel@tonic-gate * Someone stepped in and disabled the service. 1722*7c478bd9Sstevel@tonic-gate */ 1723*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" has been disabled" 1724*7c478bd9Sstevel@tonic-gate " by another entity.\n"), wip->fmri); 1725*7c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE; 1726*7c478bd9Sstevel@tonic-gate goto out; 1727*7c478bd9Sstevel@tonic-gate } 1728*7c478bd9Sstevel@tonic-gate 1729*7c478bd9Sstevel@tonic-gate if (!has_potential(wip->inst, B_FALSE)) { 1730*7c478bd9Sstevel@tonic-gate /* 1731*7c478bd9Sstevel@tonic-gate * Our dependencies aren't met. We'll never 1732*7c478bd9Sstevel@tonic-gate * amount to anything. 1733*7c478bd9Sstevel@tonic-gate */ 1734*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" has unsatisfied" 1735*7c478bd9Sstevel@tonic-gate " dependencies.\n"), wip->fmri); 1736*7c478bd9Sstevel@tonic-gate /* 1737*7c478bd9Sstevel@tonic-gate * EXIT_SVC_FAILURE takes precedence over 1738*7c478bd9Sstevel@tonic-gate * EXIT_DEP_FAILURE 1739*7c478bd9Sstevel@tonic-gate */ 1740*7c478bd9Sstevel@tonic-gate if (exit_status == 0) 1741*7c478bd9Sstevel@tonic-gate exit_status = EXIT_DEP_FAILURE; 1742*7c478bd9Sstevel@tonic-gate goto out; 1743*7c478bd9Sstevel@tonic-gate } 1744*7c478bd9Sstevel@tonic-gate } while (_scf_pg_wait(pg, WAIT_INTERVAL) >= 0); 1745*7c478bd9Sstevel@tonic-gate scfdie(); 1746*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate out: 1749*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1750*7c478bd9Sstevel@tonic-gate return (0); 1751*7c478bd9Sstevel@tonic-gate } 1752*7c478bd9Sstevel@tonic-gate 1753*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1754*7c478bd9Sstevel@tonic-gate static int 1755*7c478bd9Sstevel@tonic-gate wait_fmri_disabled(void *data, scf_walkinfo_t *wip) 1756*7c478bd9Sstevel@tonic-gate { 1757*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 1758*7c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 1759*7c478bd9Sstevel@tonic-gate 1760*7c478bd9Sstevel@tonic-gate assert(wip->inst != NULL); 1761*7c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 1762*7c478bd9Sstevel@tonic-gate 1763*7c478bd9Sstevel@tonic-gate do { 1764*7c478bd9Sstevel@tonic-gate if (pg) 1765*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1766*7c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, &pg) != 0) { 1767*7c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE; 1768*7c478bd9Sstevel@tonic-gate return (0); 1769*7c478bd9Sstevel@tonic-gate } 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0) { 1772*7c478bd9Sstevel@tonic-gate /* 1773*7c478bd9Sstevel@tonic-gate * We're done. 1774*7c478bd9Sstevel@tonic-gate */ 1775*7c478bd9Sstevel@tonic-gate goto out; 1776*7c478bd9Sstevel@tonic-gate } 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) { 1779*7c478bd9Sstevel@tonic-gate /* 1780*7c478bd9Sstevel@tonic-gate * The service is ill. 1781*7c478bd9Sstevel@tonic-gate */ 1782*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is in maintenance" 1783*7c478bd9Sstevel@tonic-gate " state.\n"), wip->fmri); 1784*7c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE; 1785*7c478bd9Sstevel@tonic-gate goto out; 1786*7c478bd9Sstevel@tonic-gate } 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate if (is_enabled(wip->inst)) { 1789*7c478bd9Sstevel@tonic-gate /* 1790*7c478bd9Sstevel@tonic-gate * Someone stepped in and enabled the service. 1791*7c478bd9Sstevel@tonic-gate */ 1792*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" has been enabled" 1793*7c478bd9Sstevel@tonic-gate " by another entity.\n"), wip->fmri); 1794*7c478bd9Sstevel@tonic-gate exit_status = EXIT_SVC_FAILURE; 1795*7c478bd9Sstevel@tonic-gate goto out; 1796*7c478bd9Sstevel@tonic-gate } 1797*7c478bd9Sstevel@tonic-gate 1798*7c478bd9Sstevel@tonic-gate if (!has_potential(wip->inst, B_TRUE)) { 1799*7c478bd9Sstevel@tonic-gate /* 1800*7c478bd9Sstevel@tonic-gate * Our restarter is hopeless. 1801*7c478bd9Sstevel@tonic-gate */ 1802*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Restarter for instance \"%s\" is" 1803*7c478bd9Sstevel@tonic-gate " unavailable.\n"), wip->fmri); 1804*7c478bd9Sstevel@tonic-gate /* 1805*7c478bd9Sstevel@tonic-gate * EXIT_SVC_FAILURE takes precedence over 1806*7c478bd9Sstevel@tonic-gate * EXIT_DEP_FAILURE 1807*7c478bd9Sstevel@tonic-gate */ 1808*7c478bd9Sstevel@tonic-gate if (exit_status == 0) 1809*7c478bd9Sstevel@tonic-gate exit_status = EXIT_DEP_FAILURE; 1810*7c478bd9Sstevel@tonic-gate goto out; 1811*7c478bd9Sstevel@tonic-gate } 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate } while (_scf_pg_wait(pg, WAIT_INTERVAL) >= 0); 1814*7c478bd9Sstevel@tonic-gate scfdie(); 1815*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate out: 1818*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1819*7c478bd9Sstevel@tonic-gate return (0); 1820*7c478bd9Sstevel@tonic-gate } 1821*7c478bd9Sstevel@tonic-gate 1822*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1823*7c478bd9Sstevel@tonic-gate static int 1824*7c478bd9Sstevel@tonic-gate clear_instance(void *data, scf_walkinfo_t *wip) 1825*7c478bd9Sstevel@tonic-gate { 1826*7c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate assert(wip->inst != NULL); 1829*7c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0) 1832*7c478bd9Sstevel@tonic-gate return (0); 1833*7c478bd9Sstevel@tonic-gate 1834*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) { 1835*7c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, SCF_PROPERTY_MAINT_OFF); 1836*7c478bd9Sstevel@tonic-gate } else if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 1837*7c478bd9Sstevel@tonic-gate 0) { 1838*7c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, SCF_PROPERTY_RESTORE); 1839*7c478bd9Sstevel@tonic-gate } else { 1840*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is not in a " 1841*7c478bd9Sstevel@tonic-gate "maintenance or degraded state.\n"), wip->fmri); 1842*7c478bd9Sstevel@tonic-gate 1843*7c478bd9Sstevel@tonic-gate exit_status = 1; 1844*7c478bd9Sstevel@tonic-gate } 1845*7c478bd9Sstevel@tonic-gate 1846*7c478bd9Sstevel@tonic-gate return (0); 1847*7c478bd9Sstevel@tonic-gate } 1848*7c478bd9Sstevel@tonic-gate 1849*7c478bd9Sstevel@tonic-gate static int 1850*7c478bd9Sstevel@tonic-gate set_fmri_action(void *action, scf_walkinfo_t *wip) 1851*7c478bd9Sstevel@tonic-gate { 1852*7c478bd9Sstevel@tonic-gate assert(wip->inst != NULL && wip->pg == NULL); 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, action); 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate return (0); 1857*7c478bd9Sstevel@tonic-gate } 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate /* 1860*7c478bd9Sstevel@tonic-gate * Flags to control 'mark' action. 1861*7c478bd9Sstevel@tonic-gate */ 1862*7c478bd9Sstevel@tonic-gate #define MARK_IMMEDIATE 0x1 1863*7c478bd9Sstevel@tonic-gate #define MARK_TEMPORARY 0x2 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate static int 1866*7c478bd9Sstevel@tonic-gate force_degraded(void *data, scf_walkinfo_t *wip) 1867*7c478bd9Sstevel@tonic-gate { 1868*7c478bd9Sstevel@tonic-gate int flags = (int)data; 1869*7c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate if (inst_get_state(wip->inst, state, wip->fmri, NULL) != 0) { 1872*7c478bd9Sstevel@tonic-gate exit_status = 1; 1873*7c478bd9Sstevel@tonic-gate return (0); 1874*7c478bd9Sstevel@tonic-gate } 1875*7c478bd9Sstevel@tonic-gate 1876*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_ONLINE) != 0) { 1877*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Instance \"%s\" is not online.\n"), wip->fmri); 1878*7c478bd9Sstevel@tonic-gate exit_status = 1; 1879*7c478bd9Sstevel@tonic-gate return (0); 1880*7c478bd9Sstevel@tonic-gate } 1881*7c478bd9Sstevel@tonic-gate 1882*7c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, (flags & MARK_IMMEDIATE) ? 1883*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_DEGRADE_IMMEDIATE : SCF_PROPERTY_DEGRADED); 1884*7c478bd9Sstevel@tonic-gate 1885*7c478bd9Sstevel@tonic-gate return (0); 1886*7c478bd9Sstevel@tonic-gate } 1887*7c478bd9Sstevel@tonic-gate 1888*7c478bd9Sstevel@tonic-gate static int 1889*7c478bd9Sstevel@tonic-gate force_maintenance(void *data, scf_walkinfo_t *wip) 1890*7c478bd9Sstevel@tonic-gate { 1891*7c478bd9Sstevel@tonic-gate int flags = (int)data; 1892*7c478bd9Sstevel@tonic-gate const char *prop; 1893*7c478bd9Sstevel@tonic-gate 1894*7c478bd9Sstevel@tonic-gate if (flags & MARK_IMMEDIATE) { 1895*7c478bd9Sstevel@tonic-gate prop = (flags & MARK_TEMPORARY) ? 1896*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON_IMMTEMP : 1897*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON_IMMEDIATE; 1898*7c478bd9Sstevel@tonic-gate } else { 1899*7c478bd9Sstevel@tonic-gate prop = (flags & MARK_TEMPORARY) ? 1900*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON_TEMPORARY : 1901*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MAINT_ON; 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate set_inst_action(wip->fmri, wip->inst, prop); 1905*7c478bd9Sstevel@tonic-gate 1906*7c478bd9Sstevel@tonic-gate return (0); 1907*7c478bd9Sstevel@tonic-gate } 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate static void 1910*7c478bd9Sstevel@tonic-gate set_milestone(const char *fmri, boolean_t temporary) 1911*7c478bd9Sstevel@tonic-gate { 1912*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 1913*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg; 1914*7c478bd9Sstevel@tonic-gate int r; 1915*7c478bd9Sstevel@tonic-gate 1916*7c478bd9Sstevel@tonic-gate if (temporary) { 1917*7c478bd9Sstevel@tonic-gate set_astring_prop(SCF_SERVICE_STARTD, SCF_PG_OPTIONS_OVR, 1918*7c478bd9Sstevel@tonic-gate SCF_PG_OPTIONS_OVR_TYPE, SCF_PG_OPTIONS_OVR_FLAGS, 1919*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, fmri); 1920*7c478bd9Sstevel@tonic-gate return; 1921*7c478bd9Sstevel@tonic-gate } 1922*7c478bd9Sstevel@tonic-gate 1923*7c478bd9Sstevel@tonic-gate if ((inst = scf_instance_create(h)) == NULL || 1924*7c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL) 1925*7c478bd9Sstevel@tonic-gate scfdie(); 1926*7c478bd9Sstevel@tonic-gate 1927*7c478bd9Sstevel@tonic-gate if (get_inst(SCF_SERVICE_STARTD, inst) != 0) { 1928*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 1929*7c478bd9Sstevel@tonic-gate return; 1930*7c478bd9Sstevel@tonic-gate } 1931*7c478bd9Sstevel@tonic-gate 1932*7c478bd9Sstevel@tonic-gate /* 1933*7c478bd9Sstevel@tonic-gate * Set the persistent milestone before deleting the override so we don't 1934*7c478bd9Sstevel@tonic-gate * glitch. 1935*7c478bd9Sstevel@tonic-gate */ 1936*7c478bd9Sstevel@tonic-gate set_astring_prop(SCF_SERVICE_STARTD, SCF_PG_OPTIONS, 1937*7c478bd9Sstevel@tonic-gate SCF_PG_OPTIONS_TYPE, SCF_PG_OPTIONS_FLAGS, SCF_PROPERTY_MILESTONE, 1938*7c478bd9Sstevel@tonic-gate fmri); 1939*7c478bd9Sstevel@tonic-gate 1940*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_OPTIONS_OVR, pg) == 0) { 1941*7c478bd9Sstevel@tonic-gate r = delete_prop(pg, SCF_PROPERTY_MILESTONE); 1942*7c478bd9Sstevel@tonic-gate switch (r) { 1943*7c478bd9Sstevel@tonic-gate case 0: 1944*7c478bd9Sstevel@tonic-gate break; 1945*7c478bd9Sstevel@tonic-gate 1946*7c478bd9Sstevel@tonic-gate case ECANCELED: 1947*7c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri); 1948*7c478bd9Sstevel@tonic-gate exit_status = 1; 1949*7c478bd9Sstevel@tonic-gate goto out; 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate case EPERM: 1952*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s property of " 1953*7c478bd9Sstevel@tonic-gate "%s: permission denied.\n"), SCF_PG_OPTIONS_OVR, 1954*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_SERVICE_STARTD); 1955*7c478bd9Sstevel@tonic-gate exit_status = 1; 1956*7c478bd9Sstevel@tonic-gate goto out; 1957*7c478bd9Sstevel@tonic-gate 1958*7c478bd9Sstevel@tonic-gate case EACCES: 1959*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s property of " 1960*7c478bd9Sstevel@tonic-gate "%s: access denied.\n"), SCF_PG_OPTIONS_OVR, 1961*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_SERVICE_STARTD); 1962*7c478bd9Sstevel@tonic-gate exit_status = 1; 1963*7c478bd9Sstevel@tonic-gate goto out; 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate case EROFS: 1966*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not delete %s/%s property of " 1967*7c478bd9Sstevel@tonic-gate "%s: backend read-only.\n"), SCF_PG_OPTIONS_OVR, 1968*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_MILESTONE, SCF_SERVICE_STARTD); 1969*7c478bd9Sstevel@tonic-gate exit_status = 1; 1970*7c478bd9Sstevel@tonic-gate goto out; 1971*7c478bd9Sstevel@tonic-gate 1972*7c478bd9Sstevel@tonic-gate default: 1973*7c478bd9Sstevel@tonic-gate bad_error("delete_prop", r); 1974*7c478bd9Sstevel@tonic-gate } 1975*7c478bd9Sstevel@tonic-gate } else { 1976*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1977*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1978*7c478bd9Sstevel@tonic-gate break; 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1981*7c478bd9Sstevel@tonic-gate uu_warn(emsg_no_service, fmri); 1982*7c478bd9Sstevel@tonic-gate exit_status = 1; 1983*7c478bd9Sstevel@tonic-gate goto out; 1984*7c478bd9Sstevel@tonic-gate 1985*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1986*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1987*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 1988*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1989*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1990*7c478bd9Sstevel@tonic-gate default: 1991*7c478bd9Sstevel@tonic-gate scfdie(); 1992*7c478bd9Sstevel@tonic-gate } 1993*7c478bd9Sstevel@tonic-gate } 1994*7c478bd9Sstevel@tonic-gate 1995*7c478bd9Sstevel@tonic-gate out: 1996*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1997*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 1998*7c478bd9Sstevel@tonic-gate } 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate static char const *milestones[] = { 2001*7c478bd9Sstevel@tonic-gate SCF_MILESTONE_SINGLE_USER, 2002*7c478bd9Sstevel@tonic-gate SCF_MILESTONE_MULTI_USER, 2003*7c478bd9Sstevel@tonic-gate SCF_MILESTONE_MULTI_USER_SERVER, 2004*7c478bd9Sstevel@tonic-gate NULL 2005*7c478bd9Sstevel@tonic-gate }; 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate static void 2008*7c478bd9Sstevel@tonic-gate usage_milestone() 2009*7c478bd9Sstevel@tonic-gate { 2010*7c478bd9Sstevel@tonic-gate const char **ms; 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2013*7c478bd9Sstevel@tonic-gate "Usage: svcadm milestone [-d] <milestone>\n\n" 2014*7c478bd9Sstevel@tonic-gate "\t-d\tmake the specified milestone the default for system boot\n\n" 2015*7c478bd9Sstevel@tonic-gate "\tMilestones can be specified using an FMRI or abbreviation.\n" 2016*7c478bd9Sstevel@tonic-gate "\tThe major milestones are as follows:\n\n" 2017*7c478bd9Sstevel@tonic-gate "\tall\n" 2018*7c478bd9Sstevel@tonic-gate "\tnone\n")); 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate for (ms = milestones; *ms != NULL; ms++) 2021*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\t%s\n", *ms); 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE); 2024*7c478bd9Sstevel@tonic-gate } 2025*7c478bd9Sstevel@tonic-gate 2026*7c478bd9Sstevel@tonic-gate static const char * 2027*7c478bd9Sstevel@tonic-gate validate_milestone(const char *milestone) 2028*7c478bd9Sstevel@tonic-gate { 2029*7c478bd9Sstevel@tonic-gate const char **ms; 2030*7c478bd9Sstevel@tonic-gate const char *tmp; 2031*7c478bd9Sstevel@tonic-gate size_t len; 2032*7c478bd9Sstevel@tonic-gate 2033*7c478bd9Sstevel@tonic-gate if (strcmp(milestone, "all") == 0) 2034*7c478bd9Sstevel@tonic-gate return (milestone); 2035*7c478bd9Sstevel@tonic-gate 2036*7c478bd9Sstevel@tonic-gate if (strcmp(milestone, "none") == 0) 2037*7c478bd9Sstevel@tonic-gate return (milestone); 2038*7c478bd9Sstevel@tonic-gate 2039*7c478bd9Sstevel@tonic-gate /* 2040*7c478bd9Sstevel@tonic-gate * Determine if this is a full or partial milestone 2041*7c478bd9Sstevel@tonic-gate */ 2042*7c478bd9Sstevel@tonic-gate for (ms = milestones; *ms != NULL; ms++) { 2043*7c478bd9Sstevel@tonic-gate if ((tmp = strstr(*ms, milestone)) != NULL) { 2044*7c478bd9Sstevel@tonic-gate len = strlen(milestone); 2045*7c478bd9Sstevel@tonic-gate 2046*7c478bd9Sstevel@tonic-gate /* 2047*7c478bd9Sstevel@tonic-gate * The beginning of the string must align with the start 2048*7c478bd9Sstevel@tonic-gate * of a milestone fmri, or on the boundary between 2049*7c478bd9Sstevel@tonic-gate * elements. The end of the string must align with the 2050*7c478bd9Sstevel@tonic-gate * end of the milestone, or at the instance boundary. 2051*7c478bd9Sstevel@tonic-gate */ 2052*7c478bd9Sstevel@tonic-gate if ((tmp == *ms || tmp[-1] == '/') && 2053*7c478bd9Sstevel@tonic-gate (tmp[len] == '\0' || tmp[len] == ':')) 2054*7c478bd9Sstevel@tonic-gate return (*ms); 2055*7c478bd9Sstevel@tonic-gate } 2056*7c478bd9Sstevel@tonic-gate } 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2059*7c478bd9Sstevel@tonic-gate gettext("\"%s\" is not a valid major milestone.\n"), milestone); 2060*7c478bd9Sstevel@tonic-gate 2061*7c478bd9Sstevel@tonic-gate usage_milestone(); 2062*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2063*7c478bd9Sstevel@tonic-gate } 2064*7c478bd9Sstevel@tonic-gate 2065*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2066*7c478bd9Sstevel@tonic-gate static void 2067*7c478bd9Sstevel@tonic-gate quiet(const char *fmt, ...) 2068*7c478bd9Sstevel@tonic-gate { 2069*7c478bd9Sstevel@tonic-gate /* Do nothing */ 2070*7c478bd9Sstevel@tonic-gate } 2071*7c478bd9Sstevel@tonic-gate 2072*7c478bd9Sstevel@tonic-gate int 2073*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 2074*7c478bd9Sstevel@tonic-gate { 2075*7c478bd9Sstevel@tonic-gate int o; 2076*7c478bd9Sstevel@tonic-gate int err; 2077*7c478bd9Sstevel@tonic-gate 2078*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2079*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2080*7c478bd9Sstevel@tonic-gate 2081*7c478bd9Sstevel@tonic-gate (void) uu_setpname(argv[0]); 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate if (argc < 2) 2084*7c478bd9Sstevel@tonic-gate usage(); 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate max_scf_fmri_sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 2087*7c478bd9Sstevel@tonic-gate if (max_scf_fmri_sz < 0) 2088*7c478bd9Sstevel@tonic-gate scfdie(); 2089*7c478bd9Sstevel@tonic-gate ++max_scf_fmri_sz; 2090*7c478bd9Sstevel@tonic-gate 2091*7c478bd9Sstevel@tonic-gate scratch_fmri = malloc(max_scf_fmri_sz); 2092*7c478bd9Sstevel@tonic-gate if (scratch_fmri == NULL) 2093*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 2094*7c478bd9Sstevel@tonic-gate 2095*7c478bd9Sstevel@tonic-gate h = scf_handle_create(SCF_VERSION); 2096*7c478bd9Sstevel@tonic-gate if (h == NULL) 2097*7c478bd9Sstevel@tonic-gate scfdie(); 2098*7c478bd9Sstevel@tonic-gate 2099*7c478bd9Sstevel@tonic-gate if (scf_handle_bind(h) == -1) 2100*7c478bd9Sstevel@tonic-gate uu_die(gettext("Couldn't bind to svc.configd.\n")); 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "v")) != -1) { 2103*7c478bd9Sstevel@tonic-gate if (o == 'v') 2104*7c478bd9Sstevel@tonic-gate verbose = 1; 2105*7c478bd9Sstevel@tonic-gate else 2106*7c478bd9Sstevel@tonic-gate usage(); 2107*7c478bd9Sstevel@tonic-gate } 2108*7c478bd9Sstevel@tonic-gate 2109*7c478bd9Sstevel@tonic-gate if (optind >= argc) 2110*7c478bd9Sstevel@tonic-gate usage(); 2111*7c478bd9Sstevel@tonic-gate 2112*7c478bd9Sstevel@tonic-gate emsg_permission_denied = gettext("%s: Permission denied.\n"); 2113*7c478bd9Sstevel@tonic-gate emsg_nomem = gettext("Out of memory.\n"); 2114*7c478bd9Sstevel@tonic-gate emsg_create_pg_perm_denied = gettext("%s: Couldn't create \"%s\" " 2115*7c478bd9Sstevel@tonic-gate "property group (permission denied).\n"); 2116*7c478bd9Sstevel@tonic-gate emsg_pg_perm_denied = gettext("%s: Couldn't modify \"%s\" property " 2117*7c478bd9Sstevel@tonic-gate "group (permission denied).\n"); 2118*7c478bd9Sstevel@tonic-gate emsg_prop_perm_denied = gettext("%s: Couldn't modify \"%s/%s\" " 2119*7c478bd9Sstevel@tonic-gate "property (permission denied).\n"); 2120*7c478bd9Sstevel@tonic-gate emsg_no_service = gettext("No such service \"%s\".\n"); 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate if (strcmp(argv[optind], "enable") == 0) { 2123*7c478bd9Sstevel@tonic-gate int flags = SET_ENABLED; 2124*7c478bd9Sstevel@tonic-gate int wait = 0; 2125*7c478bd9Sstevel@tonic-gate int error = 0; 2126*7c478bd9Sstevel@tonic-gate 2127*7c478bd9Sstevel@tonic-gate ++optind; 2128*7c478bd9Sstevel@tonic-gate 2129*7c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "rst")) != -1) { 2130*7c478bd9Sstevel@tonic-gate if (o == 'r') 2131*7c478bd9Sstevel@tonic-gate flags |= SET_RECURSIVE; 2132*7c478bd9Sstevel@tonic-gate else if (o == 't') 2133*7c478bd9Sstevel@tonic-gate flags |= SET_TEMPORARY; 2134*7c478bd9Sstevel@tonic-gate else if (o == 's') 2135*7c478bd9Sstevel@tonic-gate wait = 1; 2136*7c478bd9Sstevel@tonic-gate else if (o == '?') 2137*7c478bd9Sstevel@tonic-gate usage(); 2138*7c478bd9Sstevel@tonic-gate else { 2139*7c478bd9Sstevel@tonic-gate assert(0); 2140*7c478bd9Sstevel@tonic-gate abort(); 2141*7c478bd9Sstevel@tonic-gate } 2142*7c478bd9Sstevel@tonic-gate } 2143*7c478bd9Sstevel@tonic-gate argc -= optind; 2144*7c478bd9Sstevel@tonic-gate argv += optind; 2145*7c478bd9Sstevel@tonic-gate 2146*7c478bd9Sstevel@tonic-gate if (argc <= 0) 2147*7c478bd9Sstevel@tonic-gate usage(); 2148*7c478bd9Sstevel@tonic-gate 2149*7c478bd9Sstevel@tonic-gate /* 2150*7c478bd9Sstevel@tonic-gate * We want to continue with -s processing if we had 2151*7c478bd9Sstevel@tonic-gate * invalid options, but not if an enable failed. We 2152*7c478bd9Sstevel@tonic-gate * squelch output the second time we walk fmris; we saw 2153*7c478bd9Sstevel@tonic-gate * the errors the first time. 2154*7c478bd9Sstevel@tonic-gate */ 2155*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc, argv, 0, set_fmri_enabled, 2156*7c478bd9Sstevel@tonic-gate (void *)flags, &error, uu_warn)) != 0) { 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2159*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2160*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2161*7c478bd9Sstevel@tonic-gate 2162*7c478bd9Sstevel@tonic-gate } else if (wait && exit_status == 0 && 2163*7c478bd9Sstevel@tonic-gate (err = scf_walk_fmri(h, argc, argv, 0, wait_fmri_enabled, 2164*7c478bd9Sstevel@tonic-gate (void *)flags, &error, quiet)) != 0) { 2165*7c478bd9Sstevel@tonic-gate 2166*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2167*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2168*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2169*7c478bd9Sstevel@tonic-gate } 2170*7c478bd9Sstevel@tonic-gate 2171*7c478bd9Sstevel@tonic-gate if (error > 0) 2172*7c478bd9Sstevel@tonic-gate exit_status = error; 2173*7c478bd9Sstevel@tonic-gate 2174*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "disable") == 0) { 2175*7c478bd9Sstevel@tonic-gate int flags = 0; 2176*7c478bd9Sstevel@tonic-gate int wait = 0; 2177*7c478bd9Sstevel@tonic-gate int error = 0; 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate ++optind; 2180*7c478bd9Sstevel@tonic-gate 2181*7c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "st")) != -1) { 2182*7c478bd9Sstevel@tonic-gate if (o == 't') 2183*7c478bd9Sstevel@tonic-gate flags |= SET_TEMPORARY; 2184*7c478bd9Sstevel@tonic-gate else if (o == 's') 2185*7c478bd9Sstevel@tonic-gate wait = 1; 2186*7c478bd9Sstevel@tonic-gate else if (o == '?') 2187*7c478bd9Sstevel@tonic-gate usage(); 2188*7c478bd9Sstevel@tonic-gate else { 2189*7c478bd9Sstevel@tonic-gate assert(0); 2190*7c478bd9Sstevel@tonic-gate abort(); 2191*7c478bd9Sstevel@tonic-gate } 2192*7c478bd9Sstevel@tonic-gate } 2193*7c478bd9Sstevel@tonic-gate argc -= optind; 2194*7c478bd9Sstevel@tonic-gate argv += optind; 2195*7c478bd9Sstevel@tonic-gate 2196*7c478bd9Sstevel@tonic-gate if (argc <= 0) 2197*7c478bd9Sstevel@tonic-gate usage(); 2198*7c478bd9Sstevel@tonic-gate 2199*7c478bd9Sstevel@tonic-gate /* 2200*7c478bd9Sstevel@tonic-gate * We want to continue with -s processing if we had 2201*7c478bd9Sstevel@tonic-gate * invalid options, but not if a disable failed. We 2202*7c478bd9Sstevel@tonic-gate * squelch output the second time we walk fmris; we saw 2203*7c478bd9Sstevel@tonic-gate * the errors the first time. 2204*7c478bd9Sstevel@tonic-gate */ 2205*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc, argv, 0, set_fmri_enabled, 2206*7c478bd9Sstevel@tonic-gate (void *)flags, &exit_status, uu_warn)) != 0) { 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2209*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2210*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2211*7c478bd9Sstevel@tonic-gate 2212*7c478bd9Sstevel@tonic-gate } else if (wait && exit_status == 0 && 2213*7c478bd9Sstevel@tonic-gate (err = scf_walk_fmri(h, argc, argv, 0, wait_fmri_disabled, 2214*7c478bd9Sstevel@tonic-gate (void *)flags, &error, quiet)) != 0) { 2215*7c478bd9Sstevel@tonic-gate 2216*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2217*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2218*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2219*7c478bd9Sstevel@tonic-gate } 2220*7c478bd9Sstevel@tonic-gate 2221*7c478bd9Sstevel@tonic-gate if (error > 0) 2222*7c478bd9Sstevel@tonic-gate exit_status = error; 2223*7c478bd9Sstevel@tonic-gate 2224*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "restart") == 0) { 2225*7c478bd9Sstevel@tonic-gate ++optind; 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate if (optind >= argc) 2228*7c478bd9Sstevel@tonic-gate usage(); 2229*7c478bd9Sstevel@tonic-gate 2230*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc - optind, argv + optind, 0, 2231*7c478bd9Sstevel@tonic-gate set_fmri_action, (void *)SCF_PROPERTY_RESTART, 2232*7c478bd9Sstevel@tonic-gate &exit_status, uu_warn)) != 0) { 2233*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2234*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2235*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2236*7c478bd9Sstevel@tonic-gate } 2237*7c478bd9Sstevel@tonic-gate 2238*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "refresh") == 0) { 2239*7c478bd9Sstevel@tonic-gate ++optind; 2240*7c478bd9Sstevel@tonic-gate 2241*7c478bd9Sstevel@tonic-gate if (optind >= argc) 2242*7c478bd9Sstevel@tonic-gate usage(); 2243*7c478bd9Sstevel@tonic-gate 2244*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc - optind, argv + optind, 0, 2245*7c478bd9Sstevel@tonic-gate set_fmri_action, (void *)SCF_PROPERTY_REFRESH, 2246*7c478bd9Sstevel@tonic-gate &exit_status, uu_warn)) != 0) { 2247*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2248*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(scf_error())); 2249*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2250*7c478bd9Sstevel@tonic-gate } 2251*7c478bd9Sstevel@tonic-gate 2252*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "mark") == 0) { 2253*7c478bd9Sstevel@tonic-gate int flags = 0; 2254*7c478bd9Sstevel@tonic-gate scf_walk_callback callback; 2255*7c478bd9Sstevel@tonic-gate 2256*7c478bd9Sstevel@tonic-gate ++optind; 2257*7c478bd9Sstevel@tonic-gate 2258*7c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "It")) != -1) { 2259*7c478bd9Sstevel@tonic-gate if (o == 'I') 2260*7c478bd9Sstevel@tonic-gate flags |= MARK_IMMEDIATE; 2261*7c478bd9Sstevel@tonic-gate else if (o == 't') 2262*7c478bd9Sstevel@tonic-gate flags |= MARK_TEMPORARY; 2263*7c478bd9Sstevel@tonic-gate else if (o == '?') 2264*7c478bd9Sstevel@tonic-gate usage(); 2265*7c478bd9Sstevel@tonic-gate else { 2266*7c478bd9Sstevel@tonic-gate assert(0); 2267*7c478bd9Sstevel@tonic-gate abort(); 2268*7c478bd9Sstevel@tonic-gate } 2269*7c478bd9Sstevel@tonic-gate } 2270*7c478bd9Sstevel@tonic-gate 2271*7c478bd9Sstevel@tonic-gate if (argc - optind < 2) 2272*7c478bd9Sstevel@tonic-gate usage(); 2273*7c478bd9Sstevel@tonic-gate 2274*7c478bd9Sstevel@tonic-gate if (strcmp(argv[optind], "degraded") == 0) { 2275*7c478bd9Sstevel@tonic-gate if (flags & MARK_TEMPORARY) 2276*7c478bd9Sstevel@tonic-gate uu_xdie(UU_EXIT_USAGE, gettext("-t may not be " 2277*7c478bd9Sstevel@tonic-gate "used with degraded.\n")); 2278*7c478bd9Sstevel@tonic-gate callback = force_degraded; 2279*7c478bd9Sstevel@tonic-gate 2280*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "maintenance") == 0) { 2281*7c478bd9Sstevel@tonic-gate callback = force_maintenance; 2282*7c478bd9Sstevel@tonic-gate } else { 2283*7c478bd9Sstevel@tonic-gate usage(); 2284*7c478bd9Sstevel@tonic-gate } 2285*7c478bd9Sstevel@tonic-gate 2286*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc - optind - 1, 2287*7c478bd9Sstevel@tonic-gate argv + optind + 1, 0, callback, NULL, &exit_status, 2288*7c478bd9Sstevel@tonic-gate uu_warn)) != 0) { 2289*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2290*7c478bd9Sstevel@tonic-gate "instances: %s\n"), 2291*7c478bd9Sstevel@tonic-gate scf_strerror(err)); 2292*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2293*7c478bd9Sstevel@tonic-gate } 2294*7c478bd9Sstevel@tonic-gate 2295*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "clear") == 0) { 2296*7c478bd9Sstevel@tonic-gate ++optind; 2297*7c478bd9Sstevel@tonic-gate 2298*7c478bd9Sstevel@tonic-gate if (optind >= argc) 2299*7c478bd9Sstevel@tonic-gate usage(); 2300*7c478bd9Sstevel@tonic-gate 2301*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc - optind, argv + optind, 0, 2302*7c478bd9Sstevel@tonic-gate clear_instance, NULL, &exit_status, uu_warn)) != 0) { 2303*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2304*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2305*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2306*7c478bd9Sstevel@tonic-gate } 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "milestone") == 0) { 2309*7c478bd9Sstevel@tonic-gate boolean_t temporary = B_TRUE; 2310*7c478bd9Sstevel@tonic-gate const char *milestone; 2311*7c478bd9Sstevel@tonic-gate 2312*7c478bd9Sstevel@tonic-gate ++optind; 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate while ((o = getopt(argc, argv, "d")) != -1) { 2315*7c478bd9Sstevel@tonic-gate if (o == 'd') 2316*7c478bd9Sstevel@tonic-gate temporary = B_FALSE; 2317*7c478bd9Sstevel@tonic-gate else if (o == '?') 2318*7c478bd9Sstevel@tonic-gate usage_milestone(); 2319*7c478bd9Sstevel@tonic-gate else { 2320*7c478bd9Sstevel@tonic-gate assert(0); 2321*7c478bd9Sstevel@tonic-gate abort(); 2322*7c478bd9Sstevel@tonic-gate } 2323*7c478bd9Sstevel@tonic-gate } 2324*7c478bd9Sstevel@tonic-gate 2325*7c478bd9Sstevel@tonic-gate if (optind >= argc) 2326*7c478bd9Sstevel@tonic-gate usage_milestone(); 2327*7c478bd9Sstevel@tonic-gate 2328*7c478bd9Sstevel@tonic-gate milestone = validate_milestone(argv[optind]); 2329*7c478bd9Sstevel@tonic-gate 2330*7c478bd9Sstevel@tonic-gate set_milestone(milestone, temporary); 2331*7c478bd9Sstevel@tonic-gate } else if (strcmp(argv[optind], "_smf_backup") == 0) { 2332*7c478bd9Sstevel@tonic-gate const char *reason = NULL; 2333*7c478bd9Sstevel@tonic-gate 2334*7c478bd9Sstevel@tonic-gate ++optind; 2335*7c478bd9Sstevel@tonic-gate 2336*7c478bd9Sstevel@tonic-gate if (optind != argc - 1) 2337*7c478bd9Sstevel@tonic-gate usage(); 2338*7c478bd9Sstevel@tonic-gate 2339*7c478bd9Sstevel@tonic-gate if ((err = _scf_request_backup(h, argv[optind])) != 2340*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2341*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 2342*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_BOUND: 2343*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2344*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 2345*7c478bd9Sstevel@tonic-gate scfdie(); 2346*7c478bd9Sstevel@tonic-gate break; 2347*7c478bd9Sstevel@tonic-gate 2348*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 2349*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2350*7c478bd9Sstevel@tonic-gate reason = scf_strerror(scf_error()); 2351*7c478bd9Sstevel@tonic-gate break; 2352*7c478bd9Sstevel@tonic-gate 2353*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INTERNAL: 2354*7c478bd9Sstevel@tonic-gate reason = 2355*7c478bd9Sstevel@tonic-gate "unknown error (see console for details)"; 2356*7c478bd9Sstevel@tonic-gate break; 2357*7c478bd9Sstevel@tonic-gate } 2358*7c478bd9Sstevel@tonic-gate uu_warn("failed to backup repository: %s\n", reason); 2359*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2360*7c478bd9Sstevel@tonic-gate } 2361*7c478bd9Sstevel@tonic-gate } else { 2362*7c478bd9Sstevel@tonic-gate usage(); 2363*7c478bd9Sstevel@tonic-gate } 2364*7c478bd9Sstevel@tonic-gate 2365*7c478bd9Sstevel@tonic-gate if (scf_handle_unbind(h) == -1) 2366*7c478bd9Sstevel@tonic-gate scfdie(); 2367*7c478bd9Sstevel@tonic-gate scf_handle_destroy(h); 2368*7c478bd9Sstevel@tonic-gate 2369*7c478bd9Sstevel@tonic-gate return (exit_status); 2370*7c478bd9Sstevel@tonic-gate } 2371