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 2005 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 * Service state explanation. For select services, display a description, the 31*7c478bd9Sstevel@tonic-gate * state, and possibly why the service is in that state, what's causing it to 32*7c478bd9Sstevel@tonic-gate * be in that state, and what other services it is keeping offline (impact). 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * Explaining states other than offline is easy. For maintenance and 35*7c478bd9Sstevel@tonic-gate * degraded, we just use the auxiliary state. For offline, we must determine 36*7c478bd9Sstevel@tonic-gate * which dependencies are unsatisfied and recurse. If a causal service is not 37*7c478bd9Sstevel@tonic-gate * offline, then a svcptr to it is added to the offline service's causes list. 38*7c478bd9Sstevel@tonic-gate * If a causal service is offline, then we recurse to determine its causes and 39*7c478bd9Sstevel@tonic-gate * merge them into the causes list of the service in question (see 40*7c478bd9Sstevel@tonic-gate * add_causes()). Note that by adding a self-pointing svcptr to the causes 41*7c478bd9Sstevel@tonic-gate * lists of services which are not offline or are offline for unknown reasons, 42*7c478bd9Sstevel@tonic-gate * we can always merge the unsatisfied dependency's causes into the 43*7c478bd9Sstevel@tonic-gate * dependent's list. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * Computing an impact list is more involved because the dependencies in the 46*7c478bd9Sstevel@tonic-gate * repository are unidirectional; it requires determining the causes of all 47*7c478bd9Sstevel@tonic-gate * offline services. For each unsatisfied dependency of an offline service, 48*7c478bd9Sstevel@tonic-gate * a svcptr to the dependent is added to the dependency's impact_dependents 49*7c478bd9Sstevel@tonic-gate * list (see add_causes()). determine_impact() uses the lists to build an 50*7c478bd9Sstevel@tonic-gate * impact list. The direct dependency is used so that a path from the 51*7c478bd9Sstevel@tonic-gate * affected service to the causal service can be constructed (see 52*7c478bd9Sstevel@tonic-gate * print_dependency_reasons()). 53*7c478bd9Sstevel@tonic-gate * 54*7c478bd9Sstevel@tonic-gate * Because we always need at least impact counts, we always run 55*7c478bd9Sstevel@tonic-gate * determine_causes() on all services. 56*7c478bd9Sstevel@tonic-gate * 57*7c478bd9Sstevel@tonic-gate * If no arguments are given, we must select the services which are causing 58*7c478bd9Sstevel@tonic-gate * other services to be offline. We do so by adding services which are not 59*7c478bd9Sstevel@tonic-gate * running for any reason other than another service to the g_causes list in 60*7c478bd9Sstevel@tonic-gate * determine_causes(). 61*7c478bd9Sstevel@tonic-gate * 62*7c478bd9Sstevel@tonic-gate * Since all services must be examined, and their states may be consulted 63*7c478bd9Sstevel@tonic-gate * a lot, it is important that we only read volatile data (like states) from 64*7c478bd9Sstevel@tonic-gate * the repository once. add_instance() reads data for an instance from the 65*7c478bd9Sstevel@tonic-gate * repository into an inst_t and puts it into the "services" cache, which is 66*7c478bd9Sstevel@tonic-gate * organized as a hash table of svc_t's, each of which has a list of inst_t's. 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #include "svcs.h" 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #include <assert.h> 75*7c478bd9Sstevel@tonic-gate #include <errno.h> 76*7c478bd9Sstevel@tonic-gate #include <libintl.h> 77*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 78*7c478bd9Sstevel@tonic-gate #include <libscf.h> 79*7c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 80*7c478bd9Sstevel@tonic-gate #include <string.h> 81*7c478bd9Sstevel@tonic-gate #include <stdio.h> 82*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 83*7c478bd9Sstevel@tonic-gate #include <time.h> 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #define DC_DISABLED "SMF-8000-05" 87*7c478bd9Sstevel@tonic-gate #define DC_TEMPDISABLED "SMF-8000-1S" 88*7c478bd9Sstevel@tonic-gate #define DC_RSTRINVALID "SMF-8000-2A" 89*7c478bd9Sstevel@tonic-gate #define DC_RSTRABSENT "SMF-8000-3P" 90*7c478bd9Sstevel@tonic-gate #define DC_UNINIT "SMF-8000-4D" 91*7c478bd9Sstevel@tonic-gate #define DC_RSTRDEAD "SMF-8000-5H" 92*7c478bd9Sstevel@tonic-gate #define DC_ADMINMAINT "SMF-8000-63" 93*7c478bd9Sstevel@tonic-gate #define DC_REPTFAIL "SMF-8000-7Y" 94*7c478bd9Sstevel@tonic-gate #define DC_METHFAIL "SMF-8000-8Q" 95*7c478bd9Sstevel@tonic-gate #define DC_NONE "SMF-8000-9C" 96*7c478bd9Sstevel@tonic-gate #define DC_UNKNOWN "SMF-8000-AR" 97*7c478bd9Sstevel@tonic-gate #define DC_STARTING "SMF-8000-C4" 98*7c478bd9Sstevel@tonic-gate #define DC_ADMINDEGR "SMF-8000-DX" 99*7c478bd9Sstevel@tonic-gate #define DC_DEPABSENT "SMF-8000-E2" 100*7c478bd9Sstevel@tonic-gate #define DC_DEPRUNNING "SMF-8000-FJ" 101*7c478bd9Sstevel@tonic-gate #define DC_DEPOTHER "SMF-8000-GE" 102*7c478bd9Sstevel@tonic-gate #define DC_DEPCYCLE "SMF-8000-HP" 103*7c478bd9Sstevel@tonic-gate #define DC_INVALIDDEP "SMF-8000-JA" 104*7c478bd9Sstevel@tonic-gate #define DC_STARTFAIL "SMF-8000-KS" 105*7c478bd9Sstevel@tonic-gate #define DC_TOOQUICKLY "SMF-8000-L5" 106*7c478bd9Sstevel@tonic-gate #define DC_INVALIDSTATE "SMF-8000-N3" 107*7c478bd9Sstevel@tonic-gate #define DC_TRANSITION "SMF-8000-PH" 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate #define DEFAULT_MAN_PATH "/usr/share/man" 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate #define uu_list_append(lst, e) uu_list_insert_before(lst, NULL, e) 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate #ifdef NDEBUG 115*7c478bd9Sstevel@tonic-gate #define bad_error(func, err) abort() 116*7c478bd9Sstevel@tonic-gate #else 117*7c478bd9Sstevel@tonic-gate #define bad_error(func, err) \ 118*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: %s() failed with unknown error %d.\n", \ 119*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__, func, err); \ 120*7c478bd9Sstevel@tonic-gate abort(); 121*7c478bd9Sstevel@tonic-gate #endif 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate typedef struct { 125*7c478bd9Sstevel@tonic-gate const char *svcname; 126*7c478bd9Sstevel@tonic-gate const char *instname; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* restarter pg properties */ 129*7c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 130*7c478bd9Sstevel@tonic-gate char next_state[MAX_SCF_STATE_STRING_SZ]; 131*7c478bd9Sstevel@tonic-gate struct timeval stime; 132*7c478bd9Sstevel@tonic-gate const char *aux_state; 133*7c478bd9Sstevel@tonic-gate int64_t start_method_waitstatus; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate int enabled; 136*7c478bd9Sstevel@tonic-gate int temporary; 137*7c478bd9Sstevel@tonic-gate const char *restarter; 138*7c478bd9Sstevel@tonic-gate uu_list_t *dependencies; /* list of dependency_group's */ 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate int active; /* In use? (cycle detection) */ 141*7c478bd9Sstevel@tonic-gate int restarter_bad; 142*7c478bd9Sstevel@tonic-gate const char *summary; 143*7c478bd9Sstevel@tonic-gate uu_list_t *baddeps; /* list of dependency's */ 144*7c478bd9Sstevel@tonic-gate uu_list_t *causes; /* list of svcptrs */ 145*7c478bd9Sstevel@tonic-gate uu_list_t *impact_dependents; /* list of svcptrs */ 146*7c478bd9Sstevel@tonic-gate uu_list_t *impact; /* list of svcptrs */ 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate uu_list_node_t node; 149*7c478bd9Sstevel@tonic-gate } inst_t; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate typedef struct service { 152*7c478bd9Sstevel@tonic-gate const char *svcname; 153*7c478bd9Sstevel@tonic-gate uu_list_t *instances; 154*7c478bd9Sstevel@tonic-gate struct service *next; 155*7c478bd9Sstevel@tonic-gate } svc_t; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate struct svcptr { 158*7c478bd9Sstevel@tonic-gate inst_t *svcp; 159*7c478bd9Sstevel@tonic-gate inst_t *next_hop; 160*7c478bd9Sstevel@tonic-gate uu_list_node_t node; 161*7c478bd9Sstevel@tonic-gate }; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate struct dependency_group { 164*7c478bd9Sstevel@tonic-gate enum { DGG_REQALL, DGG_REQANY, DGG_OPTALL, DGG_EXCALL } grouping; 165*7c478bd9Sstevel@tonic-gate const char *type; 166*7c478bd9Sstevel@tonic-gate uu_list_t *entities; /* List of struct dependency's */ 167*7c478bd9Sstevel@tonic-gate uu_list_node_t node; 168*7c478bd9Sstevel@tonic-gate }; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate struct dependency { 171*7c478bd9Sstevel@tonic-gate const char *fmri; 172*7c478bd9Sstevel@tonic-gate uu_list_node_t node; 173*7c478bd9Sstevel@tonic-gate }; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* Hash table of service names -> svc_t's */ 176*7c478bd9Sstevel@tonic-gate #define SVC_HASH_NBUCKETS 256 177*7c478bd9Sstevel@tonic-gate #define SVC_HASH_MASK (SVC_HASH_NBUCKETS - 1) 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate static svc_t **services; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate static uu_list_pool_t *insts, *svcptrs, *depgroups, *deps; 182*7c478bd9Sstevel@tonic-gate static uu_list_t *g_causes; /* list of svcptrs */ 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate static scf_scope_t *g_local_scope; 185*7c478bd9Sstevel@tonic-gate static scf_service_t *g_svc; 186*7c478bd9Sstevel@tonic-gate static scf_instance_t *g_inst; 187*7c478bd9Sstevel@tonic-gate static scf_snapshot_t *g_snap; 188*7c478bd9Sstevel@tonic-gate static scf_propertygroup_t *g_pg; 189*7c478bd9Sstevel@tonic-gate static scf_property_t *g_prop; 190*7c478bd9Sstevel@tonic-gate static scf_value_t *g_val; 191*7c478bd9Sstevel@tonic-gate static scf_iter_t *g_iter, *g_viter; 192*7c478bd9Sstevel@tonic-gate static char *g_fmri, *g_value; 193*7c478bd9Sstevel@tonic-gate static size_t g_fmri_sz, g_value_sz; 194*7c478bd9Sstevel@tonic-gate static const char *g_msgbase = "http://sun.com/msg/"; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate static char *emsg_nomem; 197*7c478bd9Sstevel@tonic-gate static char *emsg_invalid_dep; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate extern scf_handle_t *h; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 202*7c478bd9Sstevel@tonic-gate static int 203*7c478bd9Sstevel@tonic-gate svcptr_compare(struct svcptr *a, struct svcptr *b, void *data) 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate return (b->svcp - a->svcp); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate static uint32_t 209*7c478bd9Sstevel@tonic-gate hash_name(const char *name) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate uint32_t h = 0, g; 212*7c478bd9Sstevel@tonic-gate const char *p; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate for (p = name; *p != '\0'; ++p) { 215*7c478bd9Sstevel@tonic-gate h = (h << 4) + *p; 216*7c478bd9Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) { 217*7c478bd9Sstevel@tonic-gate h ^= (g >> 24); 218*7c478bd9Sstevel@tonic-gate h ^= g; 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate return (h); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate static void 227*7c478bd9Sstevel@tonic-gate x_init(void) 228*7c478bd9Sstevel@tonic-gate { 229*7c478bd9Sstevel@tonic-gate emsg_nomem = gettext("Out of memory.\n"); 230*7c478bd9Sstevel@tonic-gate emsg_invalid_dep = 231*7c478bd9Sstevel@tonic-gate gettext("svc:/%s:%s has invalid dependency \"%s\".\n"); 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate services = calloc(SVC_HASH_NBUCKETS, sizeof (*services)); 234*7c478bd9Sstevel@tonic-gate if (services == NULL) 235*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate insts = uu_list_pool_create("insts", sizeof (inst_t), 238*7c478bd9Sstevel@tonic-gate offsetof(inst_t, node), NULL, UU_LIST_POOL_DEBUG); 239*7c478bd9Sstevel@tonic-gate svcptrs = uu_list_pool_create("svcptrs", sizeof (struct svcptr), 240*7c478bd9Sstevel@tonic-gate offsetof(struct svcptr, node), (uu_compare_fn_t *)svcptr_compare, 241*7c478bd9Sstevel@tonic-gate UU_LIST_POOL_DEBUG); 242*7c478bd9Sstevel@tonic-gate depgroups = uu_list_pool_create("depgroups", 243*7c478bd9Sstevel@tonic-gate sizeof (struct dependency_group), 244*7c478bd9Sstevel@tonic-gate offsetof(struct dependency_group, node), NULL, UU_LIST_POOL_DEBUG); 245*7c478bd9Sstevel@tonic-gate deps = uu_list_pool_create("deps", sizeof (struct dependency), 246*7c478bd9Sstevel@tonic-gate offsetof(struct dependency, node), NULL, UU_LIST_POOL_DEBUG); 247*7c478bd9Sstevel@tonic-gate g_causes = uu_list_create(svcptrs, NULL, UU_LIST_DEBUG); 248*7c478bd9Sstevel@tonic-gate if (insts == NULL || svcptrs == NULL || depgroups == NULL || 249*7c478bd9Sstevel@tonic-gate deps == NULL || g_causes == NULL) 250*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if ((g_local_scope = scf_scope_create(h)) == NULL || 253*7c478bd9Sstevel@tonic-gate (g_svc = scf_service_create(h)) == NULL || 254*7c478bd9Sstevel@tonic-gate (g_inst = scf_instance_create(h)) == NULL || 255*7c478bd9Sstevel@tonic-gate (g_snap = scf_snapshot_create(h)) == NULL || 256*7c478bd9Sstevel@tonic-gate (g_pg = scf_pg_create(h)) == NULL || 257*7c478bd9Sstevel@tonic-gate (g_prop = scf_property_create(h)) == NULL || 258*7c478bd9Sstevel@tonic-gate (g_val = scf_value_create(h)) == NULL || 259*7c478bd9Sstevel@tonic-gate (g_iter = scf_iter_create(h)) == NULL || 260*7c478bd9Sstevel@tonic-gate (g_viter = scf_iter_create(h)) == NULL) 261*7c478bd9Sstevel@tonic-gate scfdie(); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, g_local_scope) != 0) 264*7c478bd9Sstevel@tonic-gate scfdie(); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate g_fmri_sz = max_scf_fmri_length + 1; 267*7c478bd9Sstevel@tonic-gate g_fmri = safe_malloc(g_fmri_sz); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate g_value_sz = max_scf_value_length + 1; 270*7c478bd9Sstevel@tonic-gate g_value = safe_malloc(g_value_sz); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* 274*7c478bd9Sstevel@tonic-gate * Repository loading routines. 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate /* 278*7c478bd9Sstevel@tonic-gate * Returns 279*7c478bd9Sstevel@tonic-gate * 0 - success 280*7c478bd9Sstevel@tonic-gate * ECANCELED - inst was deleted 281*7c478bd9Sstevel@tonic-gate * EINVAL - inst is invalid 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate static int 284*7c478bd9Sstevel@tonic-gate load_dependencies(inst_t *svcp, scf_instance_t *inst) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 287*7c478bd9Sstevel@tonic-gate struct dependency_group *dg; 288*7c478bd9Sstevel@tonic-gate struct dependency *d; 289*7c478bd9Sstevel@tonic-gate int r; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate assert(svcp->dependencies == NULL); 292*7c478bd9Sstevel@tonic-gate svcp->dependencies = uu_list_create(depgroups, svcp, UU_LIST_DEBUG); 293*7c478bd9Sstevel@tonic-gate if (svcp->dependencies == NULL) 294*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", g_snap) == 0) { 297*7c478bd9Sstevel@tonic-gate snap = g_snap; 298*7c478bd9Sstevel@tonic-gate } else { 299*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 300*7c478bd9Sstevel@tonic-gate scfdie(); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate snap = NULL; 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(g_iter, inst, snap, 306*7c478bd9Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) != 0) { 307*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 308*7c478bd9Sstevel@tonic-gate scfdie(); 309*7c478bd9Sstevel@tonic-gate return (ECANCELED); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate for (;;) { 313*7c478bd9Sstevel@tonic-gate r = scf_iter_next_pg(g_iter, g_pg); 314*7c478bd9Sstevel@tonic-gate if (r == 0) 315*7c478bd9Sstevel@tonic-gate break; 316*7c478bd9Sstevel@tonic-gate if (r != 1) { 317*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 318*7c478bd9Sstevel@tonic-gate scfdie(); 319*7c478bd9Sstevel@tonic-gate return (ECANCELED); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate dg = safe_malloc(sizeof (*dg)); 323*7c478bd9Sstevel@tonic-gate (void) memset(dg, 0, sizeof (*dg)); 324*7c478bd9Sstevel@tonic-gate dg->entities = uu_list_create(deps, dg, UU_LIST_DEBUG); 325*7c478bd9Sstevel@tonic-gate if (dg->entities == NULL) 326*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_GROUPING, 329*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, g_value, g_value_sz, 0) != 0) 330*7c478bd9Sstevel@tonic-gate return (EINVAL); 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate if (strcmp(g_value, "require_all") == 0) 333*7c478bd9Sstevel@tonic-gate dg->grouping = DGG_REQALL; 334*7c478bd9Sstevel@tonic-gate else if (strcmp(g_value, "require_any") == 0) 335*7c478bd9Sstevel@tonic-gate dg->grouping = DGG_REQANY; 336*7c478bd9Sstevel@tonic-gate else if (strcmp(g_value, "optional_all") == 0) 337*7c478bd9Sstevel@tonic-gate dg->grouping = DGG_OPTALL; 338*7c478bd9Sstevel@tonic-gate else if (strcmp(g_value, "exclude_all") == 0) 339*7c478bd9Sstevel@tonic-gate dg->grouping = DGG_EXCALL; 340*7c478bd9Sstevel@tonic-gate else { 341*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has " 342*7c478bd9Sstevel@tonic-gate "dependency with unknown type \"%s\".\n"), 343*7c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname, g_value); 344*7c478bd9Sstevel@tonic-gate return (EINVAL); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TYPE, SCF_TYPE_ASTRING, 348*7c478bd9Sstevel@tonic-gate g_value, g_value_sz, 0) != 0) 349*7c478bd9Sstevel@tonic-gate return (EINVAL); 350*7c478bd9Sstevel@tonic-gate dg->type = safe_strdup(g_value); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(g_pg, SCF_PROPERTY_ENTITIES, g_prop) != 353*7c478bd9Sstevel@tonic-gate 0) { 354*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 355*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 356*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has " 357*7c478bd9Sstevel@tonic-gate "dependency without an entities " 358*7c478bd9Sstevel@tonic-gate "property.\n"), svcp->svcname, 359*7c478bd9Sstevel@tonic-gate svcp->instname); 360*7c478bd9Sstevel@tonic-gate return (EINVAL); 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 363*7c478bd9Sstevel@tonic-gate return (ECANCELED); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate default: 366*7c478bd9Sstevel@tonic-gate scfdie(); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(g_viter, g_prop) != 0) { 371*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 372*7c478bd9Sstevel@tonic-gate scfdie(); 373*7c478bd9Sstevel@tonic-gate return (ECANCELED); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate for (;;) { 377*7c478bd9Sstevel@tonic-gate r = scf_iter_next_value(g_viter, g_val); 378*7c478bd9Sstevel@tonic-gate if (r == 0) 379*7c478bd9Sstevel@tonic-gate break; 380*7c478bd9Sstevel@tonic-gate if (r != 1) { 381*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 382*7c478bd9Sstevel@tonic-gate scfdie(); 383*7c478bd9Sstevel@tonic-gate return (ECANCELED); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate d = safe_malloc(sizeof (*d)); 387*7c478bd9Sstevel@tonic-gate d->fmri = safe_malloc(max_scf_fmri_length + 1); 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, (char *)d->fmri, 390*7c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1) < 0) 391*7c478bd9Sstevel@tonic-gate scfdie(); 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate uu_list_node_init(d, &d->node, deps); 394*7c478bd9Sstevel@tonic-gate (void) uu_list_append(dg->entities, d); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate uu_list_node_init(dg, &dg->node, depgroups); 398*7c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->dependencies, dg); 399*7c478bd9Sstevel@tonic-gate assert(r == 0); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate return (0); 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate static void 406*7c478bd9Sstevel@tonic-gate add_instance(const char *svcname, const char *instname, scf_instance_t *inst) 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate inst_t *instp; 409*7c478bd9Sstevel@tonic-gate svc_t *svcp; 410*7c478bd9Sstevel@tonic-gate int have_enabled = 0; 411*7c478bd9Sstevel@tonic-gate int i; 412*7c478bd9Sstevel@tonic-gate uint32_t h; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate h = hash_name(svcname) & SVC_HASH_MASK; 415*7c478bd9Sstevel@tonic-gate for (svcp = services[h]; svcp != NULL; svcp = svcp->next) { 416*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->svcname, svcname) == 0) 417*7c478bd9Sstevel@tonic-gate break; 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate if (svcp == NULL) { 421*7c478bd9Sstevel@tonic-gate svcp = safe_malloc(sizeof (*svcp)); 422*7c478bd9Sstevel@tonic-gate svcp->svcname = safe_strdup(svcname); 423*7c478bd9Sstevel@tonic-gate svcp->instances = uu_list_create(insts, svcp, UU_LIST_DEBUG); 424*7c478bd9Sstevel@tonic-gate if (svcp->instances == NULL) 425*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 426*7c478bd9Sstevel@tonic-gate svcp->next = services[h]; 427*7c478bd9Sstevel@tonic-gate services[h] = svcp; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate instp = safe_malloc(sizeof (*instp)); 431*7c478bd9Sstevel@tonic-gate (void) memset(instp, 0, sizeof (*instp)); 432*7c478bd9Sstevel@tonic-gate instp->svcname = svcp->svcname; 433*7c478bd9Sstevel@tonic-gate instp->instname = safe_strdup(instname); 434*7c478bd9Sstevel@tonic-gate instp->impact_dependents = 435*7c478bd9Sstevel@tonic-gate uu_list_create(svcptrs, instp, UU_LIST_DEBUG); 436*7c478bd9Sstevel@tonic-gate if (instp->impact_dependents == NULL) 437*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, g_pg) != 0) { 440*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 441*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 442*7c478bd9Sstevel@tonic-gate return; 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 445*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has no " 446*7c478bd9Sstevel@tonic-gate "\"%s\" property group; ignoring.\n"), 447*7c478bd9Sstevel@tonic-gate instp->svcname, instp->instname, SCF_PG_RESTARTER); 448*7c478bd9Sstevel@tonic-gate return; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate default: 451*7c478bd9Sstevel@tonic-gate scfdie(); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_STATE, SCF_TYPE_ASTRING, 456*7c478bd9Sstevel@tonic-gate (void *)instp->state, sizeof (instp->state), 0) != 0) 457*7c478bd9Sstevel@tonic-gate return; 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_NEXT_STATE, SCF_TYPE_ASTRING, 460*7c478bd9Sstevel@tonic-gate (void *)instp->next_state, sizeof (instp->next_state), 0) != 0) 461*7c478bd9Sstevel@tonic-gate return; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_STATE_TIMESTAMP, 464*7c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, &instp->stime, 0, 0) != 0) 465*7c478bd9Sstevel@tonic-gate return; 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_AUX_STATE, SCF_TYPE_ASTRING, 468*7c478bd9Sstevel@tonic-gate g_fmri, g_fmri_sz, 0) != 0) 469*7c478bd9Sstevel@tonic-gate return; 470*7c478bd9Sstevel@tonic-gate instp->aux_state = safe_strdup(g_fmri); 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate (void) pg_get_single_val(g_pg, SCF_PROPERTY_START_METHOD_WAITSTATUS, 473*7c478bd9Sstevel@tonic-gate SCF_TYPE_INTEGER, &instp->start_method_waitstatus, 0, 0); 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_GENERAL_OVR, g_pg) == 0) { 476*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED, 477*7c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN, &instp->enabled, 0, 0) == 0) 478*7c478bd9Sstevel@tonic-gate have_enabled = 1; 479*7c478bd9Sstevel@tonic-gate } else { 480*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 481*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 482*7c478bd9Sstevel@tonic-gate break; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 485*7c478bd9Sstevel@tonic-gate return; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate default: 488*7c478bd9Sstevel@tonic-gate scfdie(); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_GENERAL, g_pg) != 493*7c478bd9Sstevel@tonic-gate 0) { 494*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 495*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 496*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 497*7c478bd9Sstevel@tonic-gate return; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate default: 500*7c478bd9Sstevel@tonic-gate scfdie(); 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN, 505*7c478bd9Sstevel@tonic-gate &i, 0, 0) != 0) 506*7c478bd9Sstevel@tonic-gate return; 507*7c478bd9Sstevel@tonic-gate if (!have_enabled) { 508*7c478bd9Sstevel@tonic-gate instp->enabled = i; 509*7c478bd9Sstevel@tonic-gate instp->temporary = 0; 510*7c478bd9Sstevel@tonic-gate } else { 511*7c478bd9Sstevel@tonic-gate instp->temporary = (instp->enabled != i); 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_RESTARTER, SCF_TYPE_ASTRING, 515*7c478bd9Sstevel@tonic-gate g_fmri, g_fmri_sz, 0) == 0) 516*7c478bd9Sstevel@tonic-gate instp->restarter = safe_strdup(g_fmri); 517*7c478bd9Sstevel@tonic-gate else 518*7c478bd9Sstevel@tonic-gate instp->restarter = SCF_SERVICE_STARTD; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (strcmp(instp->state, SCF_STATE_STRING_OFFLINE) == 0 && 521*7c478bd9Sstevel@tonic-gate load_dependencies(instp, inst) != 0) 522*7c478bd9Sstevel@tonic-gate return; 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate uu_list_node_init(instp, &instp->node, insts); 525*7c478bd9Sstevel@tonic-gate i = uu_list_append(svcp->instances, instp); 526*7c478bd9Sstevel@tonic-gate assert(i == 0); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate static void 530*7c478bd9Sstevel@tonic-gate load_services(void) 531*7c478bd9Sstevel@tonic-gate { 532*7c478bd9Sstevel@tonic-gate scf_iter_t *siter, *iiter; 533*7c478bd9Sstevel@tonic-gate int r; 534*7c478bd9Sstevel@tonic-gate char *svcname, *instname; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate if ((siter = scf_iter_create(h)) == NULL || 537*7c478bd9Sstevel@tonic-gate (iiter = scf_iter_create(h)) == NULL) 538*7c478bd9Sstevel@tonic-gate scfdie(); 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate svcname = safe_malloc(max_scf_name_length + 1); 541*7c478bd9Sstevel@tonic-gate instname = safe_malloc(max_scf_name_length + 1); 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate if (scf_iter_scope_services(siter, g_local_scope) != 0) 544*7c478bd9Sstevel@tonic-gate scfdie(); 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate for (;;) { 547*7c478bd9Sstevel@tonic-gate r = scf_iter_next_service(siter, g_svc); 548*7c478bd9Sstevel@tonic-gate if (r == 0) 549*7c478bd9Sstevel@tonic-gate break; 550*7c478bd9Sstevel@tonic-gate if (r != 1) 551*7c478bd9Sstevel@tonic-gate scfdie(); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate if (scf_service_get_name(g_svc, svcname, 554*7c478bd9Sstevel@tonic-gate max_scf_name_length + 1) < 0) { 555*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 556*7c478bd9Sstevel@tonic-gate scfdie(); 557*7c478bd9Sstevel@tonic-gate continue; 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iiter, g_svc) != 0) { 561*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 562*7c478bd9Sstevel@tonic-gate scfdie(); 563*7c478bd9Sstevel@tonic-gate continue; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate for (;;) { 567*7c478bd9Sstevel@tonic-gate r = scf_iter_next_instance(iiter, g_inst); 568*7c478bd9Sstevel@tonic-gate if (r == 0) 569*7c478bd9Sstevel@tonic-gate break; 570*7c478bd9Sstevel@tonic-gate if (r != 1) { 571*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 572*7c478bd9Sstevel@tonic-gate scfdie(); 573*7c478bd9Sstevel@tonic-gate break; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate if (scf_instance_get_name(g_inst, instname, 577*7c478bd9Sstevel@tonic-gate max_scf_name_length + 1) < 0) { 578*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 579*7c478bd9Sstevel@tonic-gate scfdie(); 580*7c478bd9Sstevel@tonic-gate continue; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate add_instance(svcname, instname, g_inst); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate free(svcname); 588*7c478bd9Sstevel@tonic-gate free(instname); 589*7c478bd9Sstevel@tonic-gate scf_iter_destroy(siter); 590*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iiter); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * Dependency analysis routines. 595*7c478bd9Sstevel@tonic-gate */ 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate static void 598*7c478bd9Sstevel@tonic-gate add_svcptr(uu_list_t *lst, inst_t *svcp) 599*7c478bd9Sstevel@tonic-gate { 600*7c478bd9Sstevel@tonic-gate struct svcptr *spp; 601*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 602*7c478bd9Sstevel@tonic-gate int r; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate spp = safe_malloc(sizeof (*spp)); 605*7c478bd9Sstevel@tonic-gate spp->svcp = svcp; 606*7c478bd9Sstevel@tonic-gate spp->next_hop = NULL; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate if (uu_list_find(lst, spp, NULL, &idx) != NULL) { 609*7c478bd9Sstevel@tonic-gate free(spp); 610*7c478bd9Sstevel@tonic-gate return; 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate uu_list_node_init(spp, &spp->node, svcptrs); 614*7c478bd9Sstevel@tonic-gate r = uu_list_append(lst, spp); 615*7c478bd9Sstevel@tonic-gate assert(r == 0); 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate static int determine_causes(inst_t *, void *); 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * Determine the causes of src and add them to the causes list of dst. 622*7c478bd9Sstevel@tonic-gate * Returns ELOOP if src is active, and 0 otherwise. 623*7c478bd9Sstevel@tonic-gate */ 624*7c478bd9Sstevel@tonic-gate static int 625*7c478bd9Sstevel@tonic-gate add_causes(inst_t *dst, inst_t *src) 626*7c478bd9Sstevel@tonic-gate { 627*7c478bd9Sstevel@tonic-gate struct svcptr *spp, *copy; 628*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate if (determine_causes(src, (void *)1) != UU_WALK_NEXT) { 631*7c478bd9Sstevel@tonic-gate /* Dependency cycle. */ 632*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " svc:/%s:%s\n", dst->svcname, 633*7c478bd9Sstevel@tonic-gate dst->instname); 634*7c478bd9Sstevel@tonic-gate return (ELOOP); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate add_svcptr(src->impact_dependents, dst); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate for (spp = uu_list_first(src->causes); 640*7c478bd9Sstevel@tonic-gate spp != NULL; 641*7c478bd9Sstevel@tonic-gate spp = uu_list_next(src->causes, spp)) { 642*7c478bd9Sstevel@tonic-gate if (uu_list_find(dst->causes, spp, NULL, &idx) != NULL) 643*7c478bd9Sstevel@tonic-gate continue; 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate copy = safe_malloc(sizeof (*copy)); 646*7c478bd9Sstevel@tonic-gate copy->svcp = spp->svcp; 647*7c478bd9Sstevel@tonic-gate copy->next_hop = src; 648*7c478bd9Sstevel@tonic-gate uu_list_node_init(copy, ©->node, svcptrs); 649*7c478bd9Sstevel@tonic-gate uu_list_insert(dst->causes, copy, idx); 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, spp->svcp); 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate return (0); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate static int 658*7c478bd9Sstevel@tonic-gate inst_running(inst_t *ip) 659*7c478bd9Sstevel@tonic-gate { 660*7c478bd9Sstevel@tonic-gate return (strcmp(ip->state, SCF_STATE_STRING_ONLINE) == 0 || 661*7c478bd9Sstevel@tonic-gate strcmp(ip->state, SCF_STATE_STRING_DEGRADED) == 0); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate static int 665*7c478bd9Sstevel@tonic-gate inst_running_or_maint(inst_t *ip) 666*7c478bd9Sstevel@tonic-gate { 667*7c478bd9Sstevel@tonic-gate return (inst_running(ip) || 668*7c478bd9Sstevel@tonic-gate strcmp(ip->state, SCF_STATE_STRING_MAINT) == 0); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate static svc_t * 672*7c478bd9Sstevel@tonic-gate get_svc(const char *sn) 673*7c478bd9Sstevel@tonic-gate { 674*7c478bd9Sstevel@tonic-gate uint32_t h; 675*7c478bd9Sstevel@tonic-gate svc_t *svcp; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate h = hash_name(sn) & SVC_HASH_MASK; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate for (svcp = services[h]; svcp != NULL; svcp = svcp->next) { 680*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->svcname, sn) == 0) 681*7c478bd9Sstevel@tonic-gate break; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate return (svcp); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 688*7c478bd9Sstevel@tonic-gate static inst_t * 689*7c478bd9Sstevel@tonic-gate get_inst(svc_t *svcp, const char *in) 690*7c478bd9Sstevel@tonic-gate { 691*7c478bd9Sstevel@tonic-gate inst_t *instp; 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate for (instp = uu_list_first(svcp->instances); 694*7c478bd9Sstevel@tonic-gate instp != NULL; 695*7c478bd9Sstevel@tonic-gate instp = uu_list_next(svcp->instances, instp)) { 696*7c478bd9Sstevel@tonic-gate if (strcmp(instp->instname, in) == 0) 697*7c478bd9Sstevel@tonic-gate return (instp); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate return (NULL); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate static int 704*7c478bd9Sstevel@tonic-gate get_fmri(const char *fmri, svc_t **spp, inst_t **ipp) 705*7c478bd9Sstevel@tonic-gate { 706*7c478bd9Sstevel@tonic-gate const char *sn, *in; 707*7c478bd9Sstevel@tonic-gate svc_t *sp; 708*7c478bd9Sstevel@tonic-gate inst_t *ip; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate if (strlcpy(g_fmri, fmri, g_fmri_sz) >= g_fmri_sz) 711*7c478bd9Sstevel@tonic-gate return (EINVAL); 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(g_fmri, NULL, &sn, &in, NULL, NULL) != 0) 714*7c478bd9Sstevel@tonic-gate return (EINVAL); 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if (sn == NULL) 717*7c478bd9Sstevel@tonic-gate return (EINVAL); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate sp = get_svc(sn); 720*7c478bd9Sstevel@tonic-gate if (sp == NULL) 721*7c478bd9Sstevel@tonic-gate return (ENOENT); 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate if (in != NULL) { 724*7c478bd9Sstevel@tonic-gate ip = get_inst(sp, in); 725*7c478bd9Sstevel@tonic-gate if (ip == NULL) 726*7c478bd9Sstevel@tonic-gate return (ENOENT); 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate if (spp != NULL) 730*7c478bd9Sstevel@tonic-gate *spp = sp; 731*7c478bd9Sstevel@tonic-gate if (ipp != NULL) 732*7c478bd9Sstevel@tonic-gate *ipp = ((in == NULL) ? NULL : ip); 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate return (0); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate static int 738*7c478bd9Sstevel@tonic-gate process_reqall(inst_t *svcp, struct dependency_group *dg) 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 741*7c478bd9Sstevel@tonic-gate struct dependency *d; 742*7c478bd9Sstevel@tonic-gate int r, svcrunning; 743*7c478bd9Sstevel@tonic-gate svc_t *sp; 744*7c478bd9Sstevel@tonic-gate inst_t *ip; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 747*7c478bd9Sstevel@tonic-gate if (walk == NULL) 748*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 751*7c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 752*7c478bd9Sstevel@tonic-gate switch (r) { 753*7c478bd9Sstevel@tonic-gate case EINVAL: 754*7c478bd9Sstevel@tonic-gate /* LINTED */ 755*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 756*7c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 757*7c478bd9Sstevel@tonic-gate continue; 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate case ENOENT: 760*7c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 761*7c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 762*7c478bd9Sstevel@tonic-gate assert(r == 0); 763*7c478bd9Sstevel@tonic-gate continue; 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate case 0: 766*7c478bd9Sstevel@tonic-gate break; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate default: 769*7c478bd9Sstevel@tonic-gate bad_error("get_fmri", r); 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate if (ip != NULL) { 773*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) 774*7c478bd9Sstevel@tonic-gate continue; 775*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 776*7c478bd9Sstevel@tonic-gate if (r != 0) { 777*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 778*7c478bd9Sstevel@tonic-gate return (r); 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate continue; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate svcrunning = 0; 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 786*7c478bd9Sstevel@tonic-gate ip != NULL; 787*7c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 788*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) 789*7c478bd9Sstevel@tonic-gate svcrunning = 1; 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate if (!svcrunning) { 793*7c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 794*7c478bd9Sstevel@tonic-gate ip != NULL; 795*7c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 796*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 797*7c478bd9Sstevel@tonic-gate if (r != 0) { 798*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 799*7c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 800*7c478bd9Sstevel@tonic-gate return (r); 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 807*7c478bd9Sstevel@tonic-gate return (0); 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate static int 811*7c478bd9Sstevel@tonic-gate process_reqany(inst_t *svcp, struct dependency_group *dg) 812*7c478bd9Sstevel@tonic-gate { 813*7c478bd9Sstevel@tonic-gate svc_t *sp; 814*7c478bd9Sstevel@tonic-gate inst_t *ip; 815*7c478bd9Sstevel@tonic-gate struct dependency *d; 816*7c478bd9Sstevel@tonic-gate int r; 817*7c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate for (d = uu_list_first(dg->entities); 820*7c478bd9Sstevel@tonic-gate d != NULL; 821*7c478bd9Sstevel@tonic-gate d = uu_list_next(dg->entities, d)) { 822*7c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 823*7c478bd9Sstevel@tonic-gate switch (r) { 824*7c478bd9Sstevel@tonic-gate case 0: 825*7c478bd9Sstevel@tonic-gate break; 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate case EINVAL: 828*7c478bd9Sstevel@tonic-gate /* LINTED */ 829*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 830*7c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 831*7c478bd9Sstevel@tonic-gate continue; 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate case ENOENT: 834*7c478bd9Sstevel@tonic-gate continue; 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate default: 837*7c478bd9Sstevel@tonic-gate bad_error("eval_svc_dep", r); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate if (ip != NULL) { 841*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) 842*7c478bd9Sstevel@tonic-gate return (0); 843*7c478bd9Sstevel@tonic-gate continue; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 847*7c478bd9Sstevel@tonic-gate ip != NULL; 848*7c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 849*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) 850*7c478bd9Sstevel@tonic-gate return (0); 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate /* 855*7c478bd9Sstevel@tonic-gate * The dependency group is not satisfied. Add all unsatisfied members 856*7c478bd9Sstevel@tonic-gate * to the cause list. 857*7c478bd9Sstevel@tonic-gate */ 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 860*7c478bd9Sstevel@tonic-gate if (walk == NULL) 861*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 864*7c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 865*7c478bd9Sstevel@tonic-gate switch (r) { 866*7c478bd9Sstevel@tonic-gate case 0: 867*7c478bd9Sstevel@tonic-gate break; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate case ENOENT: 870*7c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 871*7c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 872*7c478bd9Sstevel@tonic-gate assert(r == 0); 873*7c478bd9Sstevel@tonic-gate continue; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate case EINVAL: 876*7c478bd9Sstevel@tonic-gate /* Should have caught above. */ 877*7c478bd9Sstevel@tonic-gate default: 878*7c478bd9Sstevel@tonic-gate bad_error("eval_svc_dep", r); 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate if (ip != NULL) { 882*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) 883*7c478bd9Sstevel@tonic-gate continue; 884*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 885*7c478bd9Sstevel@tonic-gate if (r != 0) { 886*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 887*7c478bd9Sstevel@tonic-gate return (r); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate continue; 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 893*7c478bd9Sstevel@tonic-gate ip != NULL; 894*7c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 895*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) 896*7c478bd9Sstevel@tonic-gate continue; 897*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 898*7c478bd9Sstevel@tonic-gate if (r != 0) { 899*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 900*7c478bd9Sstevel@tonic-gate return (r); 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate return (0); 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate static int 909*7c478bd9Sstevel@tonic-gate process_optall(inst_t *svcp, struct dependency_group *dg) 910*7c478bd9Sstevel@tonic-gate { 911*7c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 912*7c478bd9Sstevel@tonic-gate struct dependency *d; 913*7c478bd9Sstevel@tonic-gate int r; 914*7c478bd9Sstevel@tonic-gate inst_t *ip; 915*7c478bd9Sstevel@tonic-gate svc_t *sp; 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 918*7c478bd9Sstevel@tonic-gate if (walk == NULL) 919*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 922*7c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate switch (r) { 925*7c478bd9Sstevel@tonic-gate case 0: 926*7c478bd9Sstevel@tonic-gate break; 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate case EINVAL: 929*7c478bd9Sstevel@tonic-gate /* LINTED */ 930*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 931*7c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 932*7c478bd9Sstevel@tonic-gate continue; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate case ENOENT: 935*7c478bd9Sstevel@tonic-gate continue; 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate default: 938*7c478bd9Sstevel@tonic-gate bad_error("get_fmri", r); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate if (ip != NULL) { 942*7c478bd9Sstevel@tonic-gate if (ip->enabled && !inst_running_or_maint(ip)) { 943*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 944*7c478bd9Sstevel@tonic-gate if (r != 0) { 945*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 946*7c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 947*7c478bd9Sstevel@tonic-gate return (r); 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate continue; 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 954*7c478bd9Sstevel@tonic-gate ip != NULL; 955*7c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 956*7c478bd9Sstevel@tonic-gate if (ip->enabled && !inst_running_or_maint(ip)) { 957*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 958*7c478bd9Sstevel@tonic-gate if (r != 0) { 959*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 960*7c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 961*7c478bd9Sstevel@tonic-gate return (r); 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 968*7c478bd9Sstevel@tonic-gate return (0); 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate static int 972*7c478bd9Sstevel@tonic-gate process_excall(inst_t *svcp, struct dependency_group *dg) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate struct dependency *d; 975*7c478bd9Sstevel@tonic-gate int r; 976*7c478bd9Sstevel@tonic-gate svc_t *sp; 977*7c478bd9Sstevel@tonic-gate inst_t *ip; 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate for (d = uu_list_first(dg->entities); 980*7c478bd9Sstevel@tonic-gate d != NULL; 981*7c478bd9Sstevel@tonic-gate d = uu_list_next(dg->entities, d)) { 982*7c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate switch (r) { 985*7c478bd9Sstevel@tonic-gate case 0: 986*7c478bd9Sstevel@tonic-gate break; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate case EINVAL: 989*7c478bd9Sstevel@tonic-gate /* LINTED */ 990*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 991*7c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 992*7c478bd9Sstevel@tonic-gate continue; 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate case ENOENT: 995*7c478bd9Sstevel@tonic-gate continue; 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate default: 998*7c478bd9Sstevel@tonic-gate bad_error("eval_svc_dep", r); 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate if (ip != NULL) { 1002*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) { 1003*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 1004*7c478bd9Sstevel@tonic-gate if (r != 0) { 1005*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 1006*7c478bd9Sstevel@tonic-gate return (r); 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate continue; 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 1013*7c478bd9Sstevel@tonic-gate ip != NULL; 1014*7c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 1015*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) { 1016*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 1017*7c478bd9Sstevel@tonic-gate if (r != 0) { 1018*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 1019*7c478bd9Sstevel@tonic-gate return (r); 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate } 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate return (0); 1026*7c478bd9Sstevel@tonic-gate } 1027*7c478bd9Sstevel@tonic-gate 1028*7c478bd9Sstevel@tonic-gate static int 1029*7c478bd9Sstevel@tonic-gate process_svc_dg(inst_t *svcp, struct dependency_group *dg) 1030*7c478bd9Sstevel@tonic-gate { 1031*7c478bd9Sstevel@tonic-gate switch (dg->grouping) { 1032*7c478bd9Sstevel@tonic-gate case DGG_REQALL: 1033*7c478bd9Sstevel@tonic-gate return (process_reqall(svcp, dg)); 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate case DGG_REQANY: 1036*7c478bd9Sstevel@tonic-gate return (process_reqany(svcp, dg)); 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate case DGG_OPTALL: 1039*7c478bd9Sstevel@tonic-gate return (process_optall(svcp, dg)); 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate case DGG_EXCALL: 1042*7c478bd9Sstevel@tonic-gate return (process_excall(svcp, dg)); 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate default: 1045*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 1046*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1047*7c478bd9Sstevel@tonic-gate "%s:%d: Unknown dependency grouping %d.\n", __FILE__, 1048*7c478bd9Sstevel@tonic-gate __LINE__, dg->grouping); 1049*7c478bd9Sstevel@tonic-gate #endif 1050*7c478bd9Sstevel@tonic-gate abort(); 1051*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate /* 1056*7c478bd9Sstevel@tonic-gate * Returns 1057*7c478bd9Sstevel@tonic-gate * EINVAL - fmri is not a valid FMRI 1058*7c478bd9Sstevel@tonic-gate * 0 - the file indicated by fmri is missing 1059*7c478bd9Sstevel@tonic-gate * 1 - the file indicated by fmri is present 1060*7c478bd9Sstevel@tonic-gate */ 1061*7c478bd9Sstevel@tonic-gate static int 1062*7c478bd9Sstevel@tonic-gate eval_file_dep(const char *fmri) 1063*7c478bd9Sstevel@tonic-gate { 1064*7c478bd9Sstevel@tonic-gate const char *path; 1065*7c478bd9Sstevel@tonic-gate struct stat st; 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate if (strncmp(fmri, "file:", sizeof ("file:") - 1) != 0) 1068*7c478bd9Sstevel@tonic-gate return (EINVAL); 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate path = fmri + (sizeof ("file:") - 1); 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate if (path[0] != '/') 1073*7c478bd9Sstevel@tonic-gate return (EINVAL); 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate if (path[1] == '/') { 1076*7c478bd9Sstevel@tonic-gate path += 2; 1077*7c478bd9Sstevel@tonic-gate if (strncmp(path, "localhost/", sizeof ("localhost/") - 1) == 0) 1078*7c478bd9Sstevel@tonic-gate path += sizeof ("localhost") - 1; 1079*7c478bd9Sstevel@tonic-gate else if (path[0] != '/') 1080*7c478bd9Sstevel@tonic-gate return (EINVAL); 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate return (stat(path, &st) == 0 ? 1 : 0); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate static void 1087*7c478bd9Sstevel@tonic-gate process_file_dg(inst_t *svcp, struct dependency_group *dg) 1088*7c478bd9Sstevel@tonic-gate { 1089*7c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 1090*7c478bd9Sstevel@tonic-gate struct dependency *d, **deps; 1091*7c478bd9Sstevel@tonic-gate int r, i = 0, any_satisfied = 0; 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate if (dg->grouping == DGG_REQANY) { 1094*7c478bd9Sstevel@tonic-gate deps = calloc(uu_list_numnodes(dg->entities), sizeof (*deps)); 1095*7c478bd9Sstevel@tonic-gate if (deps == NULL) 1096*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 1100*7c478bd9Sstevel@tonic-gate if (walk == NULL) 1101*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 1104*7c478bd9Sstevel@tonic-gate r = eval_file_dep(d->fmri); 1105*7c478bd9Sstevel@tonic-gate if (r == EINVAL) { 1106*7c478bd9Sstevel@tonic-gate /* LINTED */ 1107*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 1108*7c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 1109*7c478bd9Sstevel@tonic-gate continue; 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate assert(r == 0 || r == 1); 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate switch (dg->grouping) { 1115*7c478bd9Sstevel@tonic-gate case DGG_REQALL: 1116*7c478bd9Sstevel@tonic-gate case DGG_OPTALL: 1117*7c478bd9Sstevel@tonic-gate if (r == 0) { 1118*7c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 1119*7c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 1120*7c478bd9Sstevel@tonic-gate assert(r == 0); 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate break; 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate case DGG_REQANY: 1125*7c478bd9Sstevel@tonic-gate if (r == 1) 1126*7c478bd9Sstevel@tonic-gate any_satisfied = 1; 1127*7c478bd9Sstevel@tonic-gate else 1128*7c478bd9Sstevel@tonic-gate deps[i++] = d; 1129*7c478bd9Sstevel@tonic-gate break; 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate case DGG_EXCALL: 1132*7c478bd9Sstevel@tonic-gate if (r == 1) { 1133*7c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 1134*7c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 1135*7c478bd9Sstevel@tonic-gate assert(r == 0); 1136*7c478bd9Sstevel@tonic-gate } 1137*7c478bd9Sstevel@tonic-gate break; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate default: 1140*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 1141*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: Unknown grouping %d.\n", 1142*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__, dg->grouping); 1143*7c478bd9Sstevel@tonic-gate #endif 1144*7c478bd9Sstevel@tonic-gate abort(); 1145*7c478bd9Sstevel@tonic-gate } 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate if (dg->grouping != DGG_REQANY) 1151*7c478bd9Sstevel@tonic-gate return; 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate if (!any_satisfied) { 1154*7c478bd9Sstevel@tonic-gate for (; i >= 0; --i) { 1155*7c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, deps[i]); 1156*7c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, deps[i]); 1157*7c478bd9Sstevel@tonic-gate assert(r == 0); 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate free(deps); 1162*7c478bd9Sstevel@tonic-gate } 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate /* 1165*7c478bd9Sstevel@tonic-gate * Populate the causes list of svcp. This function should not return with 1166*7c478bd9Sstevel@tonic-gate * causes empty. 1167*7c478bd9Sstevel@tonic-gate */ 1168*7c478bd9Sstevel@tonic-gate static int 1169*7c478bd9Sstevel@tonic-gate determine_causes(inst_t *svcp, void *canfailp) 1170*7c478bd9Sstevel@tonic-gate { 1171*7c478bd9Sstevel@tonic-gate struct dependency_group *dg; 1172*7c478bd9Sstevel@tonic-gate int r; 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate if (svcp->active) { 1175*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Dependency cycle detected:\n" 1176*7c478bd9Sstevel@tonic-gate " svc:/%s:%s\n"), svcp->svcname, svcp->instname); 1177*7c478bd9Sstevel@tonic-gate return ((int)canfailp != 0 ? UU_WALK_ERROR : UU_WALK_NEXT); 1178*7c478bd9Sstevel@tonic-gate } 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate if (svcp->causes != NULL) 1181*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate svcp->causes = uu_list_create(svcptrs, svcp, UU_LIST_DEBUG); 1184*7c478bd9Sstevel@tonic-gate svcp->baddeps = uu_list_create(deps, svcp, UU_LIST_DEBUG); 1185*7c478bd9Sstevel@tonic-gate if (svcp->causes == NULL || svcp->baddeps == NULL) 1186*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate if (inst_running(svcp) || 1189*7c478bd9Sstevel@tonic-gate strcmp(svcp->state, SCF_STATE_STRING_UNINIT) == 0) { 1190*7c478bd9Sstevel@tonic-gate /* 1191*7c478bd9Sstevel@tonic-gate * If we're running, add a self-pointer in case we're 1192*7c478bd9Sstevel@tonic-gate * excluding another service. 1193*7c478bd9Sstevel@tonic-gate */ 1194*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1195*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) { 1199*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1200*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 1201*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) { 1205*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1206*7c478bd9Sstevel@tonic-gate if (svcp->enabled) 1207*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1210*7c478bd9Sstevel@tonic-gate } 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) != 0) { 1213*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1214*7c478bd9Sstevel@tonic-gate gettext("svc:/%s:%s has invalid state \"%s\".\n"), 1215*7c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname, svcp->state); 1216*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1217*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 1218*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->next_state, SCF_STATE_STRING_NONE) != 0) { 1222*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1223*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 1224*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1225*7c478bd9Sstevel@tonic-gate } 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate svcp->active = 1; 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate /* 1230*7c478bd9Sstevel@tonic-gate * Dependency analysis can add elements to our baddeps list (absent 1231*7c478bd9Sstevel@tonic-gate * dependency, unsatisfied file dependency), or to our cause list 1232*7c478bd9Sstevel@tonic-gate * (unsatisfied dependency). 1233*7c478bd9Sstevel@tonic-gate */ 1234*7c478bd9Sstevel@tonic-gate for (dg = uu_list_first(svcp->dependencies); 1235*7c478bd9Sstevel@tonic-gate dg != NULL; 1236*7c478bd9Sstevel@tonic-gate dg = uu_list_next(svcp->dependencies, dg)) { 1237*7c478bd9Sstevel@tonic-gate if (strcmp(dg->type, "path") == 0) { 1238*7c478bd9Sstevel@tonic-gate process_file_dg(svcp, dg); 1239*7c478bd9Sstevel@tonic-gate } else if (strcmp(dg->type, "service") == 0) { 1240*7c478bd9Sstevel@tonic-gate int r; 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate r = process_svc_dg(svcp, dg); 1243*7c478bd9Sstevel@tonic-gate if (r != 0) { 1244*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 1245*7c478bd9Sstevel@tonic-gate svcp->active = 0; 1246*7c478bd9Sstevel@tonic-gate return ((int)canfailp != 0 ? 1247*7c478bd9Sstevel@tonic-gate UU_WALK_ERROR : UU_WALK_NEXT); 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate } else { 1250*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has " 1251*7c478bd9Sstevel@tonic-gate "dependency group with invalid type \"%s\".\n"), 1252*7c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname, dg->type); 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate } 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate if (uu_list_numnodes(svcp->causes) == 0) { 1257*7c478bd9Sstevel@tonic-gate if (uu_list_numnodes(svcp->baddeps) > 0) { 1258*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 1259*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1260*7c478bd9Sstevel@tonic-gate } else { 1261*7c478bd9Sstevel@tonic-gate inst_t *restarter; 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate r = get_fmri(svcp->restarter, NULL, &restarter); 1264*7c478bd9Sstevel@tonic-gate if (r == 0 && !inst_running(restarter)) { 1265*7c478bd9Sstevel@tonic-gate r = add_causes(svcp, restarter); 1266*7c478bd9Sstevel@tonic-gate if (r != 0) { 1267*7c478bd9Sstevel@tonic-gate assert(r == ELOOP); 1268*7c478bd9Sstevel@tonic-gate svcp->active = 0; 1269*7c478bd9Sstevel@tonic-gate return ((int)canfailp != 0 ? 1270*7c478bd9Sstevel@tonic-gate UU_WALK_ERROR : UU_WALK_NEXT); 1271*7c478bd9Sstevel@tonic-gate } 1272*7c478bd9Sstevel@tonic-gate } else { 1273*7c478bd9Sstevel@tonic-gate svcp->restarter_bad = r; 1274*7c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1275*7c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 1276*7c478bd9Sstevel@tonic-gate } 1277*7c478bd9Sstevel@tonic-gate } 1278*7c478bd9Sstevel@tonic-gate } 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate assert(uu_list_numnodes(svcp->causes) > 0); 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate svcp->active = 0; 1283*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 1284*7c478bd9Sstevel@tonic-gate } 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate static void 1287*7c478bd9Sstevel@tonic-gate determine_all_causes(void) 1288*7c478bd9Sstevel@tonic-gate { 1289*7c478bd9Sstevel@tonic-gate svc_t *svcp; 1290*7c478bd9Sstevel@tonic-gate int i; 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate for (i = 0; i < SVC_HASH_NBUCKETS; ++i) { 1293*7c478bd9Sstevel@tonic-gate for (svcp = services[i]; svcp != NULL; svcp = svcp->next) 1294*7c478bd9Sstevel@tonic-gate (void) uu_list_walk(svcp->instances, 1295*7c478bd9Sstevel@tonic-gate (uu_walk_fn_t *)determine_causes, 0, 0); 1296*7c478bd9Sstevel@tonic-gate } 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate /* 1300*7c478bd9Sstevel@tonic-gate * Returns 1301*7c478bd9Sstevel@tonic-gate * 0 - success 1302*7c478bd9Sstevel@tonic-gate * ELOOP - dependency cycle detected 1303*7c478bd9Sstevel@tonic-gate */ 1304*7c478bd9Sstevel@tonic-gate static int 1305*7c478bd9Sstevel@tonic-gate determine_impact(inst_t *ip) 1306*7c478bd9Sstevel@tonic-gate { 1307*7c478bd9Sstevel@tonic-gate struct svcptr *idsp, *spp, *copy; 1308*7c478bd9Sstevel@tonic-gate uu_list_index_t idx; 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate if (ip->active) { 1311*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Dependency cycle detected:\n" 1312*7c478bd9Sstevel@tonic-gate " svc:/%s:%s\n"), ip->svcname, ip->instname); 1313*7c478bd9Sstevel@tonic-gate return (ELOOP); 1314*7c478bd9Sstevel@tonic-gate } 1315*7c478bd9Sstevel@tonic-gate 1316*7c478bd9Sstevel@tonic-gate if (ip->impact != NULL) 1317*7c478bd9Sstevel@tonic-gate return (0); 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate ip->impact = uu_list_create(svcptrs, ip, UU_LIST_DEBUG); 1320*7c478bd9Sstevel@tonic-gate if (ip->impact == NULL) 1321*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 1322*7c478bd9Sstevel@tonic-gate ip->active = 1; 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate for (idsp = uu_list_first(ip->impact_dependents); 1325*7c478bd9Sstevel@tonic-gate idsp != NULL; 1326*7c478bd9Sstevel@tonic-gate idsp = uu_list_next(ip->impact_dependents, idsp)) { 1327*7c478bd9Sstevel@tonic-gate if (determine_impact(idsp->svcp) != 0) { 1328*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " svc:/%s:%s\n", 1329*7c478bd9Sstevel@tonic-gate ip->svcname, ip->instname); 1330*7c478bd9Sstevel@tonic-gate return (ELOOP); 1331*7c478bd9Sstevel@tonic-gate } 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate add_svcptr(ip->impact, idsp->svcp); 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate for (spp = uu_list_first(idsp->svcp->impact); 1336*7c478bd9Sstevel@tonic-gate spp != NULL; 1337*7c478bd9Sstevel@tonic-gate spp = uu_list_next(idsp->svcp->impact, spp)) { 1338*7c478bd9Sstevel@tonic-gate if (uu_list_find(ip->impact, spp, NULL, &idx) != NULL) 1339*7c478bd9Sstevel@tonic-gate continue; 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate copy = safe_malloc(sizeof (*copy)); 1342*7c478bd9Sstevel@tonic-gate copy->svcp = spp->svcp; 1343*7c478bd9Sstevel@tonic-gate copy->next_hop = NULL; 1344*7c478bd9Sstevel@tonic-gate uu_list_node_init(copy, ©->node, svcptrs); 1345*7c478bd9Sstevel@tonic-gate uu_list_insert(ip->impact, copy, idx); 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate } 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate ip->active = 0; 1350*7c478bd9Sstevel@tonic-gate return (0); 1351*7c478bd9Sstevel@tonic-gate } 1352*7c478bd9Sstevel@tonic-gate 1353*7c478bd9Sstevel@tonic-gate /* 1354*7c478bd9Sstevel@tonic-gate * Printing routines. 1355*7c478bd9Sstevel@tonic-gate */ 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate static void 1358*7c478bd9Sstevel@tonic-gate check_msgbase(void) 1359*7c478bd9Sstevel@tonic-gate { 1360*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, SCF_SERVICE_STARTD, NULL, NULL, g_inst, 1361*7c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) { 1362*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1363*7c478bd9Sstevel@tonic-gate scfdie(); 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate return; 1366*7c478bd9Sstevel@tonic-gate } 1367*7c478bd9Sstevel@tonic-gate 1368*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(g_inst, NULL, "msg", g_pg) != 0) { 1369*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1370*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1371*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1372*7c478bd9Sstevel@tonic-gate return; 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate default: 1375*7c478bd9Sstevel@tonic-gate scfdie(); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate } 1378*7c478bd9Sstevel@tonic-gate 1379*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(g_pg, "base", g_prop) != 0) { 1380*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1381*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1382*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1383*7c478bd9Sstevel@tonic-gate return; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate default: 1386*7c478bd9Sstevel@tonic-gate scfdie(); 1387*7c478bd9Sstevel@tonic-gate } 1388*7c478bd9Sstevel@tonic-gate } 1389*7c478bd9Sstevel@tonic-gate 1390*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(g_prop, g_val) != 0) { 1391*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1392*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1393*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 1394*7c478bd9Sstevel@tonic-gate g_msgbase = NULL; 1395*7c478bd9Sstevel@tonic-gate return; 1396*7c478bd9Sstevel@tonic-gate 1397*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1398*7c478bd9Sstevel@tonic-gate return; 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate default: 1401*7c478bd9Sstevel@tonic-gate scfdie(); 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate } 1404*7c478bd9Sstevel@tonic-gate 1405*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, g_value, g_value_sz) < 0) { 1406*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH) 1407*7c478bd9Sstevel@tonic-gate scfdie(); 1408*7c478bd9Sstevel@tonic-gate return; 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate g_msgbase = safe_strdup(g_value); 1412*7c478bd9Sstevel@tonic-gate } 1413*7c478bd9Sstevel@tonic-gate 1414*7c478bd9Sstevel@tonic-gate static void 1415*7c478bd9Sstevel@tonic-gate determine_summary(inst_t *ip) 1416*7c478bd9Sstevel@tonic-gate { 1417*7c478bd9Sstevel@tonic-gate if (ip->summary != NULL) 1418*7c478bd9Sstevel@tonic-gate return; 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate if (inst_running(ip)) { 1421*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is running."); 1422*7c478bd9Sstevel@tonic-gate return; 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate if (strcmp(ip->state, SCF_STATE_STRING_UNINIT) == 0) { 1426*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is uninitialized."); 1427*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->state, SCF_STATE_STRING_DISABLED) == 0) { 1428*7c478bd9Sstevel@tonic-gate if (!ip->temporary) 1429*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is disabled."); 1430*7c478bd9Sstevel@tonic-gate else 1431*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is temporarily disabled."); 1432*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->state, SCF_STATE_STRING_OFFLINE) == 0) { 1433*7c478bd9Sstevel@tonic-gate if (uu_list_numnodes(ip->baddeps) != 0) 1434*7c478bd9Sstevel@tonic-gate ip->summary = gettext("has missing dependencies."); 1435*7c478bd9Sstevel@tonic-gate else if (strcmp(ip->next_state, SCF_STATE_STRING_ONLINE) == 0) 1436*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is starting."); 1437*7c478bd9Sstevel@tonic-gate else 1438*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is offline."); 1439*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->state, SCF_STATE_STRING_MAINT) == 0) { 1440*7c478bd9Sstevel@tonic-gate if (strcmp(ip->aux_state, "administrative_request") == 0) { 1441*7c478bd9Sstevel@tonic-gate ip->summary = gettext("was taken down for maintenace " 1442*7c478bd9Sstevel@tonic-gate "by an administrator."); 1443*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "dependency_cycle") == 0) { 1444*7c478bd9Sstevel@tonic-gate ip->summary = gettext("completed a dependency cycle."); 1445*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "fault_threshold_reached") == 1446*7c478bd9Sstevel@tonic-gate 0) { 1447*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is not running because " 1448*7c478bd9Sstevel@tonic-gate "a method failed repeatedly."); 1449*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "invalid_dependency") == 0) { 1450*7c478bd9Sstevel@tonic-gate ip->summary = gettext("has an invalid dependency."); 1451*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "invalid_restarter") == 0) { 1452*7c478bd9Sstevel@tonic-gate ip->summary = gettext("has an invalid restarter."); 1453*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "method_failed") == 0) { 1454*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is not running because " 1455*7c478bd9Sstevel@tonic-gate "a method failed."); 1456*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "none") == 0) { 1457*7c478bd9Sstevel@tonic-gate ip->summary = 1458*7c478bd9Sstevel@tonic-gate gettext("is not running for an unknown reason."); 1459*7c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "restarting_too_quickly") == 1460*7c478bd9Sstevel@tonic-gate 0) { 1461*7c478bd9Sstevel@tonic-gate ip->summary = gettext("was restarting too quickly."); 1462*7c478bd9Sstevel@tonic-gate } else { 1463*7c478bd9Sstevel@tonic-gate ip->summary = gettext("requires maintenance."); 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate } else { 1466*7c478bd9Sstevel@tonic-gate ip->summary = gettext("is in an invalid state."); 1467*7c478bd9Sstevel@tonic-gate } 1468*7c478bd9Sstevel@tonic-gate } 1469*7c478bd9Sstevel@tonic-gate 1470*7c478bd9Sstevel@tonic-gate static void 1471*7c478bd9Sstevel@tonic-gate print_method_failure(const inst_t *ip, const char **dcp) 1472*7c478bd9Sstevel@tonic-gate { 1473*7c478bd9Sstevel@tonic-gate char buf[50]; 1474*7c478bd9Sstevel@tonic-gate int stat = ip->start_method_waitstatus; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate if (stat != 0) { 1477*7c478bd9Sstevel@tonic-gate if (WIFEXITED(stat)) { 1478*7c478bd9Sstevel@tonic-gate if (WEXITSTATUS(stat) == SMF_EXIT_ERR_CONFIG) { 1479*7c478bd9Sstevel@tonic-gate (void) strlcpy(buf, gettext( 1480*7c478bd9Sstevel@tonic-gate "exited with $SMF_EXIT_ERR_CONFIG"), 1481*7c478bd9Sstevel@tonic-gate sizeof (buf)); 1482*7c478bd9Sstevel@tonic-gate } else if (WEXITSTATUS(stat) == SMF_EXIT_ERR_FATAL) { 1483*7c478bd9Sstevel@tonic-gate (void) strlcpy(buf, gettext( 1484*7c478bd9Sstevel@tonic-gate "exited with $SMF_EXIT_ERR_FATAL"), 1485*7c478bd9Sstevel@tonic-gate sizeof (buf)); 1486*7c478bd9Sstevel@tonic-gate } else { 1487*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 1488*7c478bd9Sstevel@tonic-gate gettext("exited with status %d"), 1489*7c478bd9Sstevel@tonic-gate WEXITSTATUS(stat)); 1490*7c478bd9Sstevel@tonic-gate } 1491*7c478bd9Sstevel@tonic-gate } else if (WIFSIGNALED(stat)) { 1492*7c478bd9Sstevel@tonic-gate if (WCOREDUMP(stat)) { 1493*7c478bd9Sstevel@tonic-gate if (strsignal(WTERMSIG(stat)) != NULL) 1494*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 1495*7c478bd9Sstevel@tonic-gate gettext("dumped core on %s (%d)"), 1496*7c478bd9Sstevel@tonic-gate strsignal(WTERMSIG(stat)), 1497*7c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 1498*7c478bd9Sstevel@tonic-gate else 1499*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 1500*7c478bd9Sstevel@tonic-gate gettext("dumped core signal %d"), 1501*7c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 1502*7c478bd9Sstevel@tonic-gate } else { 1503*7c478bd9Sstevel@tonic-gate if (strsignal(WTERMSIG(stat)) != NULL) { 1504*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 1505*7c478bd9Sstevel@tonic-gate gettext("died on %s (%d)"), 1506*7c478bd9Sstevel@tonic-gate strsignal(WTERMSIG(stat)), 1507*7c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 1508*7c478bd9Sstevel@tonic-gate } else { 1509*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 1510*7c478bd9Sstevel@tonic-gate gettext("died on signal %d"), 1511*7c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 1512*7c478bd9Sstevel@tonic-gate } 1513*7c478bd9Sstevel@tonic-gate } 1514*7c478bd9Sstevel@tonic-gate } else { 1515*7c478bd9Sstevel@tonic-gate goto fail; 1516*7c478bd9Sstevel@tonic-gate } 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate if (strcmp(ip->aux_state, "fault_threshold_reached") != 0) 1519*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Start method %s.\n"), 1520*7c478bd9Sstevel@tonic-gate buf); 1521*7c478bd9Sstevel@tonic-gate else 1522*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 1523*7c478bd9Sstevel@tonic-gate "Start method failed repeatedly, last %s.\n"), buf); 1524*7c478bd9Sstevel@tonic-gate *dcp = DC_STARTFAIL; 1525*7c478bd9Sstevel@tonic-gate } else { 1526*7c478bd9Sstevel@tonic-gate fail: 1527*7c478bd9Sstevel@tonic-gate if (strcmp(ip->aux_state, "fault_threshold_reached") == 0) 1528*7c478bd9Sstevel@tonic-gate (void) puts(gettext( 1529*7c478bd9Sstevel@tonic-gate "Reason: Method failed repeatedly.")); 1530*7c478bd9Sstevel@tonic-gate else 1531*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Method failed.")); 1532*7c478bd9Sstevel@tonic-gate *dcp = DC_METHFAIL; 1533*7c478bd9Sstevel@tonic-gate } 1534*7c478bd9Sstevel@tonic-gate } 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate static void 1537*7c478bd9Sstevel@tonic-gate print_dependency_reasons(const inst_t *svcp, int verbose) 1538*7c478bd9Sstevel@tonic-gate { 1539*7c478bd9Sstevel@tonic-gate struct dependency *d; 1540*7c478bd9Sstevel@tonic-gate struct svcptr *spp; 1541*7c478bd9Sstevel@tonic-gate const char *dc; 1542*7c478bd9Sstevel@tonic-gate 1543*7c478bd9Sstevel@tonic-gate /* 1544*7c478bd9Sstevel@tonic-gate * If we couldn't determine why the service is offline, then baddeps 1545*7c478bd9Sstevel@tonic-gate * will be empty and causes will have a pointer to self. 1546*7c478bd9Sstevel@tonic-gate */ 1547*7c478bd9Sstevel@tonic-gate if (uu_list_numnodes(svcp->baddeps) == 0 && 1548*7c478bd9Sstevel@tonic-gate uu_list_numnodes(svcp->causes) == 1) { 1549*7c478bd9Sstevel@tonic-gate spp = uu_list_first(svcp->causes); 1550*7c478bd9Sstevel@tonic-gate if (spp->svcp == svcp) { 1551*7c478bd9Sstevel@tonic-gate switch (svcp->restarter_bad) { 1552*7c478bd9Sstevel@tonic-gate case 0: 1553*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Unknown.")); 1554*7c478bd9Sstevel@tonic-gate dc = DC_UNKNOWN; 1555*7c478bd9Sstevel@tonic-gate break; 1556*7c478bd9Sstevel@tonic-gate 1557*7c478bd9Sstevel@tonic-gate case EINVAL: 1558*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 1559*7c478bd9Sstevel@tonic-gate "Restarter \"%s\" is invalid.\n"), 1560*7c478bd9Sstevel@tonic-gate svcp->restarter); 1561*7c478bd9Sstevel@tonic-gate dc = DC_RSTRINVALID; 1562*7c478bd9Sstevel@tonic-gate break; 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate case ENOENT: 1565*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 1566*7c478bd9Sstevel@tonic-gate "Restarter \"%s\" does not exist.\n"), 1567*7c478bd9Sstevel@tonic-gate svcp->restarter); 1568*7c478bd9Sstevel@tonic-gate dc = DC_RSTRABSENT; 1569*7c478bd9Sstevel@tonic-gate break; 1570*7c478bd9Sstevel@tonic-gate 1571*7c478bd9Sstevel@tonic-gate default: 1572*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 1573*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: Bad " 1574*7c478bd9Sstevel@tonic-gate "restarter_bad value %d. Aborting.\n", 1575*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__, svcp->restarter_bad); 1576*7c478bd9Sstevel@tonic-gate #endif 1577*7c478bd9Sstevel@tonic-gate abort(); 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate if (g_msgbase) 1581*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), 1582*7c478bd9Sstevel@tonic-gate g_msgbase, dc); 1583*7c478bd9Sstevel@tonic-gate return; 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate } 1586*7c478bd9Sstevel@tonic-gate 1587*7c478bd9Sstevel@tonic-gate for (d = uu_list_first(svcp->baddeps); 1588*7c478bd9Sstevel@tonic-gate d != NULL; 1589*7c478bd9Sstevel@tonic-gate d = uu_list_next(svcp->baddeps, d)) { 1590*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Dependency %s is absent.\n"), 1591*7c478bd9Sstevel@tonic-gate d->fmri); 1592*7c478bd9Sstevel@tonic-gate if (g_msgbase) 1593*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), g_msgbase, 1594*7c478bd9Sstevel@tonic-gate DC_DEPABSENT); 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate 1597*7c478bd9Sstevel@tonic-gate for (spp = uu_list_first(svcp->causes); 1598*7c478bd9Sstevel@tonic-gate spp != NULL && spp->svcp != svcp; 1599*7c478bd9Sstevel@tonic-gate spp = uu_list_next(svcp->causes, spp)) { 1600*7c478bd9Sstevel@tonic-gate determine_summary(spp->svcp); 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate if (inst_running(spp->svcp)) { 1603*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 1604*7c478bd9Sstevel@tonic-gate "Service svc:/%s:%s is running.\n"), 1605*7c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname); 1606*7c478bd9Sstevel@tonic-gate dc = DC_DEPRUNNING; 1607*7c478bd9Sstevel@tonic-gate } else { 1608*7c478bd9Sstevel@tonic-gate if (snprintf(NULL, 0, 1609*7c478bd9Sstevel@tonic-gate gettext("Reason: Service svc:/%s:%s %s"), 1610*7c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname, 1611*7c478bd9Sstevel@tonic-gate spp->svcp->summary) <= 80) { 1612*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1613*7c478bd9Sstevel@tonic-gate "Reason: Service svc:/%s:%s %s\n"), 1614*7c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname, 1615*7c478bd9Sstevel@tonic-gate spp->svcp->summary); 1616*7c478bd9Sstevel@tonic-gate } else { 1617*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1618*7c478bd9Sstevel@tonic-gate "Reason: Service svc:/%s:%s\n" 1619*7c478bd9Sstevel@tonic-gate " %s\n"), spp->svcp->svcname, 1620*7c478bd9Sstevel@tonic-gate spp->svcp->instname, spp->svcp->summary); 1621*7c478bd9Sstevel@tonic-gate } 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate dc = DC_DEPOTHER; 1624*7c478bd9Sstevel@tonic-gate } 1625*7c478bd9Sstevel@tonic-gate 1626*7c478bd9Sstevel@tonic-gate if (g_msgbase != NULL) 1627*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), g_msgbase, dc); 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate if (verbose) { 1630*7c478bd9Sstevel@tonic-gate inst_t *pp; 1631*7c478bd9Sstevel@tonic-gate int indent; 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" Path: svc:/%s:%s\n"), 1634*7c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname); 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate indent = 1; 1637*7c478bd9Sstevel@tonic-gate for (pp = spp->next_hop; ; ) { 1638*7c478bd9Sstevel@tonic-gate struct svcptr *tmp; 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%6s %*ssvc:/%s:%s\n"), 1641*7c478bd9Sstevel@tonic-gate "", indent++ * 2, "", pp->svcname, 1642*7c478bd9Sstevel@tonic-gate pp->instname); 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate if (pp == spp->svcp) 1645*7c478bd9Sstevel@tonic-gate break; 1646*7c478bd9Sstevel@tonic-gate 1647*7c478bd9Sstevel@tonic-gate /* set pp to next_hop of cause with same svcp */ 1648*7c478bd9Sstevel@tonic-gate tmp = uu_list_find(pp->causes, spp, NULL, NULL); 1649*7c478bd9Sstevel@tonic-gate pp = tmp->next_hop; 1650*7c478bd9Sstevel@tonic-gate } 1651*7c478bd9Sstevel@tonic-gate } 1652*7c478bd9Sstevel@tonic-gate } 1653*7c478bd9Sstevel@tonic-gate } 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate static void 1656*7c478bd9Sstevel@tonic-gate print_reasons(const inst_t *svcp, int verbose) 1657*7c478bd9Sstevel@tonic-gate { 1658*7c478bd9Sstevel@tonic-gate int r; 1659*7c478bd9Sstevel@tonic-gate const char *dc = NULL; 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_ONLINE) == 0) 1662*7c478bd9Sstevel@tonic-gate return; 1663*7c478bd9Sstevel@tonic-gate 1664*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_UNINIT) == 0) { 1665*7c478bd9Sstevel@tonic-gate inst_t *rsp; 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate r = get_fmri(svcp->restarter, NULL, &rsp); 1668*7c478bd9Sstevel@tonic-gate switch (r) { 1669*7c478bd9Sstevel@tonic-gate case 0: 1670*7c478bd9Sstevel@tonic-gate if (rsp != NULL) 1671*7c478bd9Sstevel@tonic-gate break; 1672*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate case EINVAL: 1675*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 1676*7c478bd9Sstevel@tonic-gate "Restarter \"%s\" is invalid.\n"), svcp->restarter); 1677*7c478bd9Sstevel@tonic-gate dc = DC_RSTRINVALID; 1678*7c478bd9Sstevel@tonic-gate goto diagcode; 1679*7c478bd9Sstevel@tonic-gate 1680*7c478bd9Sstevel@tonic-gate case ENOENT: 1681*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 1682*7c478bd9Sstevel@tonic-gate "Restarter \"%s\" does not exist.\n"), 1683*7c478bd9Sstevel@tonic-gate svcp->restarter); 1684*7c478bd9Sstevel@tonic-gate dc = DC_RSTRABSENT; 1685*7c478bd9Sstevel@tonic-gate goto diagcode; 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate default: 1688*7c478bd9Sstevel@tonic-gate bad_error("get_fmri", r); 1689*7c478bd9Sstevel@tonic-gate } 1690*7c478bd9Sstevel@tonic-gate 1691*7c478bd9Sstevel@tonic-gate if (inst_running(rsp)) { 1692*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Restarter %s " 1693*7c478bd9Sstevel@tonic-gate "has not initialized service state.\n"), 1694*7c478bd9Sstevel@tonic-gate svcp->restarter); 1695*7c478bd9Sstevel@tonic-gate dc = DC_UNINIT; 1696*7c478bd9Sstevel@tonic-gate } else { 1697*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1698*7c478bd9Sstevel@tonic-gate "Reason: Restarter %s is not running.\n"), 1699*7c478bd9Sstevel@tonic-gate svcp->restarter); 1700*7c478bd9Sstevel@tonic-gate dc = DC_RSTRDEAD; 1701*7c478bd9Sstevel@tonic-gate } 1702*7c478bd9Sstevel@tonic-gate 1703*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) { 1704*7c478bd9Sstevel@tonic-gate if (!svcp->temporary) { 1705*7c478bd9Sstevel@tonic-gate (void) puts(gettext( 1706*7c478bd9Sstevel@tonic-gate "Reason: Disabled by an administrator.")); 1707*7c478bd9Sstevel@tonic-gate dc = DC_DISABLED; 1708*7c478bd9Sstevel@tonic-gate } else { 1709*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: " 1710*7c478bd9Sstevel@tonic-gate "Temporarily disabled by an administrator.")); 1711*7c478bd9Sstevel@tonic-gate dc = DC_TEMPDISABLED; 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate 1714*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) { 1715*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->aux_state, "administrative_request") == 0) { 1716*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: " 1717*7c478bd9Sstevel@tonic-gate "Maintenance requested by an administrator.")); 1718*7c478bd9Sstevel@tonic-gate dc = DC_ADMINMAINT; 1719*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "dependency_cycle") == 0) { 1720*7c478bd9Sstevel@tonic-gate (void) puts(gettext( 1721*7c478bd9Sstevel@tonic-gate "Reason: Completes a dependency cycle.")); 1722*7c478bd9Sstevel@tonic-gate dc = DC_DEPCYCLE; 1723*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "fault_threshold_reached") == 1724*7c478bd9Sstevel@tonic-gate 0) { 1725*7c478bd9Sstevel@tonic-gate print_method_failure(svcp, &dc); 1726*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "invalid_dependency") == 0) { 1727*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Has invalid dependency.")); 1728*7c478bd9Sstevel@tonic-gate dc = DC_INVALIDDEP; 1729*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "invalid_restarter") == 0) { 1730*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Restarter \"%s\" is " 1731*7c478bd9Sstevel@tonic-gate "invalid.\n"), svcp->restarter); 1732*7c478bd9Sstevel@tonic-gate dc = DC_RSTRINVALID; 1733*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "method_failed") == 0) { 1734*7c478bd9Sstevel@tonic-gate print_method_failure(svcp, &dc); 1735*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "restarting_too_quickly") == 1736*7c478bd9Sstevel@tonic-gate 0) { 1737*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Restarting too quickly.")); 1738*7c478bd9Sstevel@tonic-gate dc = DC_TOOQUICKLY; 1739*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "none") == 0) { 1740*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1741*7c478bd9Sstevel@tonic-gate "Reason: Restarter %s gave no explanation.\n"), 1742*7c478bd9Sstevel@tonic-gate svcp->restarter); 1743*7c478bd9Sstevel@tonic-gate dc = DC_NONE; 1744*7c478bd9Sstevel@tonic-gate } else { 1745*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Unknown.")); 1746*7c478bd9Sstevel@tonic-gate dc = DC_UNKNOWN; 1747*7c478bd9Sstevel@tonic-gate } 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) == 0) { 1750*7c478bd9Sstevel@tonic-gate if (strcmp(svcp->next_state, SCF_STATE_STRING_ONLINE) == 0) { 1751*7c478bd9Sstevel@tonic-gate (void) puts(gettext( 1752*7c478bd9Sstevel@tonic-gate "Reason: Start method is running.")); 1753*7c478bd9Sstevel@tonic-gate dc = DC_STARTING; 1754*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->next_state, SCF_STATE_STRING_NONE) == 1755*7c478bd9Sstevel@tonic-gate 0) { 1756*7c478bd9Sstevel@tonic-gate print_dependency_reasons(svcp, verbose); 1757*7c478bd9Sstevel@tonic-gate /* Function prints diagcodes. */ 1758*7c478bd9Sstevel@tonic-gate return; 1759*7c478bd9Sstevel@tonic-gate } else { 1760*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1761*7c478bd9Sstevel@tonic-gate "Reason: Transitioning to state %s.\n"), 1762*7c478bd9Sstevel@tonic-gate svcp->next_state); 1763*7c478bd9Sstevel@tonic-gate dc = DC_TRANSITION; 1764*7c478bd9Sstevel@tonic-gate } 1765*7c478bd9Sstevel@tonic-gate 1766*7c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0) { 1767*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Degraded by an administrator.")); 1768*7c478bd9Sstevel@tonic-gate dc = DC_ADMINDEGR; 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate } else { 1771*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Not in valid state (%s).\n"), 1772*7c478bd9Sstevel@tonic-gate svcp->state); 1773*7c478bd9Sstevel@tonic-gate dc = DC_INVALIDSTATE; 1774*7c478bd9Sstevel@tonic-gate } 1775*7c478bd9Sstevel@tonic-gate 1776*7c478bd9Sstevel@tonic-gate diagcode: 1777*7c478bd9Sstevel@tonic-gate if (g_msgbase != NULL) 1778*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), g_msgbase, dc); 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate static void 1782*7c478bd9Sstevel@tonic-gate print_manpage(int verbose) 1783*7c478bd9Sstevel@tonic-gate { 1784*7c478bd9Sstevel@tonic-gate static char *title = NULL; 1785*7c478bd9Sstevel@tonic-gate static char *section = NULL; 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate if (title == NULL) { 1788*7c478bd9Sstevel@tonic-gate title = safe_malloc(g_value_sz); 1789*7c478bd9Sstevel@tonic-gate section = safe_malloc(g_value_sz); 1790*7c478bd9Sstevel@tonic-gate } 1791*7c478bd9Sstevel@tonic-gate 1792*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_TITLE, SCF_TYPE_ASTRING, 1793*7c478bd9Sstevel@tonic-gate (void *)title, g_value_sz, 0) != 0) 1794*7c478bd9Sstevel@tonic-gate return; 1795*7c478bd9Sstevel@tonic-gate 1796*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_SECTION, 1797*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, (void *)section, g_value_sz, 0) != 0) 1798*7c478bd9Sstevel@tonic-gate return; 1799*7c478bd9Sstevel@tonic-gate 1800*7c478bd9Sstevel@tonic-gate if (!verbose) { 1801*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s(%s)\n"), title, section); 1802*7c478bd9Sstevel@tonic-gate return; 1803*7c478bd9Sstevel@tonic-gate } 1804*7c478bd9Sstevel@tonic-gate 1805*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_MANPATH, SCF_TYPE_ASTRING, 1806*7c478bd9Sstevel@tonic-gate (void *)g_value, g_value_sz, 0) != 0) 1807*7c478bd9Sstevel@tonic-gate return; 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate if (strcmp(g_value, ":default") == 0) { 1810*7c478bd9Sstevel@tonic-gate assert(sizeof (DEFAULT_MAN_PATH) < g_value_sz); 1811*7c478bd9Sstevel@tonic-gate (void) strcpy(g_value, DEFAULT_MAN_PATH); 1812*7c478bd9Sstevel@tonic-gate } 1813*7c478bd9Sstevel@tonic-gate 1814*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: man -M %s -s %s %s\n"), g_value, 1815*7c478bd9Sstevel@tonic-gate section, title); 1816*7c478bd9Sstevel@tonic-gate } 1817*7c478bd9Sstevel@tonic-gate 1818*7c478bd9Sstevel@tonic-gate static void 1819*7c478bd9Sstevel@tonic-gate print_doclink() 1820*7c478bd9Sstevel@tonic-gate { 1821*7c478bd9Sstevel@tonic-gate static char *uri = NULL; 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate if (uri == NULL) { 1824*7c478bd9Sstevel@tonic-gate uri = safe_malloc(g_value_sz); 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate 1827*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_URI, SCF_TYPE_ASTRING, 1828*7c478bd9Sstevel@tonic-gate (void *)uri, g_value_sz, 0) != 0) 1829*7c478bd9Sstevel@tonic-gate return; 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s\n"), uri); 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate /* 1836*7c478bd9Sstevel@tonic-gate * Returns 1837*7c478bd9Sstevel@tonic-gate * 0 - success 1838*7c478bd9Sstevel@tonic-gate * 1 - inst was deleted 1839*7c478bd9Sstevel@tonic-gate */ 1840*7c478bd9Sstevel@tonic-gate static int 1841*7c478bd9Sstevel@tonic-gate print_docs(scf_instance_t *inst, int verbose) 1842*7c478bd9Sstevel@tonic-gate { 1843*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 1844*7c478bd9Sstevel@tonic-gate int r; 1845*7c478bd9Sstevel@tonic-gate 1846*7c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", g_snap) != 0) { 1847*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1848*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1849*7c478bd9Sstevel@tonic-gate break; 1850*7c478bd9Sstevel@tonic-gate 1851*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1852*7c478bd9Sstevel@tonic-gate return (1); 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate default: 1855*7c478bd9Sstevel@tonic-gate scfdie(); 1856*7c478bd9Sstevel@tonic-gate } 1857*7c478bd9Sstevel@tonic-gate 1858*7c478bd9Sstevel@tonic-gate snap = NULL; 1859*7c478bd9Sstevel@tonic-gate } else { 1860*7c478bd9Sstevel@tonic-gate snap = g_snap; 1861*7c478bd9Sstevel@tonic-gate } 1862*7c478bd9Sstevel@tonic-gate 1863*7c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(g_iter, inst, snap, 1864*7c478bd9Sstevel@tonic-gate SCF_GROUP_TEMPLATE) != 0) { 1865*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 1866*7c478bd9Sstevel@tonic-gate scfdie(); 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate return (1); 1869*7c478bd9Sstevel@tonic-gate } 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate for (;;) { 1872*7c478bd9Sstevel@tonic-gate r = scf_iter_next_pg(g_iter, g_pg); 1873*7c478bd9Sstevel@tonic-gate if (r == 0) 1874*7c478bd9Sstevel@tonic-gate break; 1875*7c478bd9Sstevel@tonic-gate if (r != 1) { 1876*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 1877*7c478bd9Sstevel@tonic-gate scfdie(); 1878*7c478bd9Sstevel@tonic-gate 1879*7c478bd9Sstevel@tonic-gate return (1); 1880*7c478bd9Sstevel@tonic-gate } 1881*7c478bd9Sstevel@tonic-gate 1882*7c478bd9Sstevel@tonic-gate if (scf_pg_get_name(g_pg, g_fmri, g_fmri_sz) < 0) { 1883*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 1884*7c478bd9Sstevel@tonic-gate scfdie(); 1885*7c478bd9Sstevel@tonic-gate 1886*7c478bd9Sstevel@tonic-gate continue; 1887*7c478bd9Sstevel@tonic-gate } 1888*7c478bd9Sstevel@tonic-gate 1889*7c478bd9Sstevel@tonic-gate if (strncmp(g_fmri, SCF_PG_TM_MAN_PREFIX, 1890*7c478bd9Sstevel@tonic-gate strlen(SCF_PG_TM_MAN_PREFIX)) == 0) { 1891*7c478bd9Sstevel@tonic-gate print_manpage(verbose); 1892*7c478bd9Sstevel@tonic-gate continue; 1893*7c478bd9Sstevel@tonic-gate } 1894*7c478bd9Sstevel@tonic-gate 1895*7c478bd9Sstevel@tonic-gate if (strncmp(g_fmri, SCF_PG_TM_DOC_PREFIX, 1896*7c478bd9Sstevel@tonic-gate strlen(SCF_PG_TM_DOC_PREFIX)) == 0) { 1897*7c478bd9Sstevel@tonic-gate print_doclink(); 1898*7c478bd9Sstevel@tonic-gate continue; 1899*7c478bd9Sstevel@tonic-gate } 1900*7c478bd9Sstevel@tonic-gate } 1901*7c478bd9Sstevel@tonic-gate return (0); 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate static void 1905*7c478bd9Sstevel@tonic-gate print_logs(scf_instance_t *inst) 1906*7c478bd9Sstevel@tonic-gate { 1907*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, g_pg) != 0) 1908*7c478bd9Sstevel@tonic-gate return; 1909*7c478bd9Sstevel@tonic-gate 1910*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_ALT_LOGFILE, 1911*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, (void *)g_value, g_value_sz, 0) == 0) 1912*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s\n"), g_value); 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_LOGFILE, 1915*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, (void *)g_value, g_value_sz, 0) == 0) 1916*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s\n"), g_value); 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate static int first = 1; 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate /* 1922*7c478bd9Sstevel@tonic-gate * Explain why the given service is in the state it's in. 1923*7c478bd9Sstevel@tonic-gate */ 1924*7c478bd9Sstevel@tonic-gate static void 1925*7c478bd9Sstevel@tonic-gate print_service(inst_t *svcp, int verbose) 1926*7c478bd9Sstevel@tonic-gate { 1927*7c478bd9Sstevel@tonic-gate struct svcptr *spp; 1928*7c478bd9Sstevel@tonic-gate time_t stime; 1929*7c478bd9Sstevel@tonic-gate char *timebuf; 1930*7c478bd9Sstevel@tonic-gate size_t tbsz; 1931*7c478bd9Sstevel@tonic-gate struct tm *tmp; 1932*7c478bd9Sstevel@tonic-gate int deleted = 0; 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate if (first) 1935*7c478bd9Sstevel@tonic-gate first = 0; 1936*7c478bd9Sstevel@tonic-gate else 1937*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate (void) printf(gettext("svc:/%s:%s"), svcp->svcname, svcp->instname); 1940*7c478bd9Sstevel@tonic-gate 1941*7c478bd9Sstevel@tonic-gate if (scf_scope_get_service(g_local_scope, svcp->svcname, g_svc) != 0) { 1942*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1943*7c478bd9Sstevel@tonic-gate scfdie(); 1944*7c478bd9Sstevel@tonic-gate deleted = 1; 1945*7c478bd9Sstevel@tonic-gate } else if (scf_service_get_instance(g_svc, svcp->instname, g_inst) != 1946*7c478bd9Sstevel@tonic-gate 0) { 1947*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1948*7c478bd9Sstevel@tonic-gate scfdie(); 1949*7c478bd9Sstevel@tonic-gate deleted = 1; 1950*7c478bd9Sstevel@tonic-gate } 1951*7c478bd9Sstevel@tonic-gate 1952*7c478bd9Sstevel@tonic-gate if (!deleted) { 1953*7c478bd9Sstevel@tonic-gate if (inst_get_single_val(g_inst, SCF_PG_TM_COMMON_NAME, locale, 1954*7c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, g_value, g_value_sz, 0, 0, 1) == 0) 1955*7c478bd9Sstevel@tonic-gate /* EMPTY */; 1956*7c478bd9Sstevel@tonic-gate else if (inst_get_single_val(g_inst, SCF_PG_TM_COMMON_NAME, "C", 1957*7c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, g_value, g_value_sz, 0, 0, 1) != 0) 1958*7c478bd9Sstevel@tonic-gate (void) strcpy(g_value, "?"); 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" (%s)\n"), g_value); 1961*7c478bd9Sstevel@tonic-gate } else { 1962*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1963*7c478bd9Sstevel@tonic-gate } 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate stime = svcp->stime.tv_sec; 1966*7c478bd9Sstevel@tonic-gate tmp = localtime(&stime); 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate for (tbsz = 50; ; tbsz *= 2) { 1969*7c478bd9Sstevel@tonic-gate timebuf = safe_malloc(tbsz); 1970*7c478bd9Sstevel@tonic-gate if (strftime(timebuf, tbsz, NULL, tmp) != 0) 1971*7c478bd9Sstevel@tonic-gate break; 1972*7c478bd9Sstevel@tonic-gate free(timebuf); 1973*7c478bd9Sstevel@tonic-gate } 1974*7c478bd9Sstevel@tonic-gate 1975*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" State: %s since %s\n"), svcp->state, timebuf); 1976*7c478bd9Sstevel@tonic-gate 1977*7c478bd9Sstevel@tonic-gate free(timebuf); 1978*7c478bd9Sstevel@tonic-gate 1979*7c478bd9Sstevel@tonic-gate /* Reasons */ 1980*7c478bd9Sstevel@tonic-gate print_reasons(svcp, verbose); 1981*7c478bd9Sstevel@tonic-gate 1982*7c478bd9Sstevel@tonic-gate if (!deleted) 1983*7c478bd9Sstevel@tonic-gate deleted = print_docs(g_inst, verbose); 1984*7c478bd9Sstevel@tonic-gate if (!deleted) 1985*7c478bd9Sstevel@tonic-gate print_logs(g_inst); 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate (void) determine_impact(svcp); 1988*7c478bd9Sstevel@tonic-gate 1989*7c478bd9Sstevel@tonic-gate switch (uu_list_numnodes(svcp->impact)) { 1990*7c478bd9Sstevel@tonic-gate case 0: 1991*7c478bd9Sstevel@tonic-gate if (inst_running(svcp)) 1992*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Impact: None.")); 1993*7c478bd9Sstevel@tonic-gate else 1994*7c478bd9Sstevel@tonic-gate (void) puts(gettext( 1995*7c478bd9Sstevel@tonic-gate "Impact: This service is not running.")); 1996*7c478bd9Sstevel@tonic-gate break; 1997*7c478bd9Sstevel@tonic-gate 1998*7c478bd9Sstevel@tonic-gate case 1: 1999*7c478bd9Sstevel@tonic-gate if (!verbose) 2000*7c478bd9Sstevel@tonic-gate (void) puts(gettext("Impact: 1 dependent service " 2001*7c478bd9Sstevel@tonic-gate "is not running. (Use -v for list.)")); 2002*7c478bd9Sstevel@tonic-gate else 2003*7c478bd9Sstevel@tonic-gate (void) puts(gettext( 2004*7c478bd9Sstevel@tonic-gate "Impact: 1 dependent service is not running:")); 2005*7c478bd9Sstevel@tonic-gate break; 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate default: 2008*7c478bd9Sstevel@tonic-gate if (!verbose) 2009*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Impact: %d dependent services " 2010*7c478bd9Sstevel@tonic-gate "are not running. (Use -v for list.)\n"), 2011*7c478bd9Sstevel@tonic-gate uu_list_numnodes(svcp->impact)); 2012*7c478bd9Sstevel@tonic-gate else 2013*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 2014*7c478bd9Sstevel@tonic-gate "Impact: %d dependent services are not running:\n"), 2015*7c478bd9Sstevel@tonic-gate uu_list_numnodes(svcp->impact)); 2016*7c478bd9Sstevel@tonic-gate } 2017*7c478bd9Sstevel@tonic-gate 2018*7c478bd9Sstevel@tonic-gate if (verbose) { 2019*7c478bd9Sstevel@tonic-gate for (spp = uu_list_first(svcp->impact); 2020*7c478bd9Sstevel@tonic-gate spp != NULL; 2021*7c478bd9Sstevel@tonic-gate spp = uu_list_next(svcp->impact, spp)) 2022*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" svc:/%s:%s\n"), 2023*7c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname); 2024*7c478bd9Sstevel@tonic-gate } 2025*7c478bd9Sstevel@tonic-gate } 2026*7c478bd9Sstevel@tonic-gate 2027*7c478bd9Sstevel@tonic-gate /* 2028*7c478bd9Sstevel@tonic-gate * Top level routine. 2029*7c478bd9Sstevel@tonic-gate */ 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate static int 2032*7c478bd9Sstevel@tonic-gate impact_compar(const void *a, const void *b) 2033*7c478bd9Sstevel@tonic-gate { 2034*7c478bd9Sstevel@tonic-gate int n, m; 2035*7c478bd9Sstevel@tonic-gate 2036*7c478bd9Sstevel@tonic-gate n = uu_list_numnodes((*(inst_t **)a)->impact); 2037*7c478bd9Sstevel@tonic-gate m = uu_list_numnodes((*(inst_t **)b)->impact); 2038*7c478bd9Sstevel@tonic-gate 2039*7c478bd9Sstevel@tonic-gate return (m - n); 2040*7c478bd9Sstevel@tonic-gate } 2041*7c478bd9Sstevel@tonic-gate 2042*7c478bd9Sstevel@tonic-gate static int 2043*7c478bd9Sstevel@tonic-gate print_service_cb(void *verbose, scf_walkinfo_t *wip) 2044*7c478bd9Sstevel@tonic-gate { 2045*7c478bd9Sstevel@tonic-gate int r; 2046*7c478bd9Sstevel@tonic-gate inst_t *ip; 2047*7c478bd9Sstevel@tonic-gate 2048*7c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate r = get_fmri(wip->fmri, NULL, &ip); 2051*7c478bd9Sstevel@tonic-gate assert(r != EINVAL); 2052*7c478bd9Sstevel@tonic-gate if (r == ENOENT) 2053*7c478bd9Sstevel@tonic-gate return (0); 2054*7c478bd9Sstevel@tonic-gate 2055*7c478bd9Sstevel@tonic-gate assert(r == 0); 2056*7c478bd9Sstevel@tonic-gate assert(ip != NULL); 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate print_service(ip, (int)verbose); 2059*7c478bd9Sstevel@tonic-gate 2060*7c478bd9Sstevel@tonic-gate return (0); 2061*7c478bd9Sstevel@tonic-gate } 2062*7c478bd9Sstevel@tonic-gate 2063*7c478bd9Sstevel@tonic-gate void 2064*7c478bd9Sstevel@tonic-gate explain(int verbose, int argc, char **argv) 2065*7c478bd9Sstevel@tonic-gate { 2066*7c478bd9Sstevel@tonic-gate /* Initialize globals. */ 2067*7c478bd9Sstevel@tonic-gate x_init(); 2068*7c478bd9Sstevel@tonic-gate 2069*7c478bd9Sstevel@tonic-gate /* Walk the graph and populate services with inst_t's */ 2070*7c478bd9Sstevel@tonic-gate load_services(); 2071*7c478bd9Sstevel@tonic-gate 2072*7c478bd9Sstevel@tonic-gate /* Populate causes for services. */ 2073*7c478bd9Sstevel@tonic-gate determine_all_causes(); 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate if (argc > 0) { 2076*7c478bd9Sstevel@tonic-gate scf_error_t err; 2077*7c478bd9Sstevel@tonic-gate 2078*7c478bd9Sstevel@tonic-gate check_msgbase(); 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate /* Call print_service() for each operand. */ 2081*7c478bd9Sstevel@tonic-gate 2082*7c478bd9Sstevel@tonic-gate err = scf_walk_fmri(h, argc, argv, SCF_WALK_MULTIPLE, 2083*7c478bd9Sstevel@tonic-gate print_service_cb, (void *)verbose, &exit_status, uu_warn); 2084*7c478bd9Sstevel@tonic-gate if (err != 0) { 2085*7c478bd9Sstevel@tonic-gate uu_warn(gettext( 2086*7c478bd9Sstevel@tonic-gate "failed to iterate over instances: %s\n"), 2087*7c478bd9Sstevel@tonic-gate scf_strerror(err)); 2088*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2089*7c478bd9Sstevel@tonic-gate } 2090*7c478bd9Sstevel@tonic-gate } else { 2091*7c478bd9Sstevel@tonic-gate struct svcptr *spp; 2092*7c478bd9Sstevel@tonic-gate int n, i; 2093*7c478bd9Sstevel@tonic-gate inst_t **ary; 2094*7c478bd9Sstevel@tonic-gate 2095*7c478bd9Sstevel@tonic-gate /* Sort g_causes. */ 2096*7c478bd9Sstevel@tonic-gate 2097*7c478bd9Sstevel@tonic-gate n = uu_list_numnodes(g_causes); 2098*7c478bd9Sstevel@tonic-gate if (n == 0) 2099*7c478bd9Sstevel@tonic-gate return; 2100*7c478bd9Sstevel@tonic-gate 2101*7c478bd9Sstevel@tonic-gate check_msgbase(); 2102*7c478bd9Sstevel@tonic-gate 2103*7c478bd9Sstevel@tonic-gate ary = calloc(n, sizeof (*ary)); 2104*7c478bd9Sstevel@tonic-gate if (ary == NULL) 2105*7c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate i = 0; 2108*7c478bd9Sstevel@tonic-gate for (spp = uu_list_first(g_causes); 2109*7c478bd9Sstevel@tonic-gate spp != NULL; 2110*7c478bd9Sstevel@tonic-gate spp = uu_list_next(g_causes, spp)) { 2111*7c478bd9Sstevel@tonic-gate (void) determine_impact(spp->svcp); 2112*7c478bd9Sstevel@tonic-gate ary[i++] = spp->svcp; 2113*7c478bd9Sstevel@tonic-gate } 2114*7c478bd9Sstevel@tonic-gate 2115*7c478bd9Sstevel@tonic-gate qsort(ary, n, sizeof (*ary), impact_compar); 2116*7c478bd9Sstevel@tonic-gate 2117*7c478bd9Sstevel@tonic-gate /* Call print_service() for each service. */ 2118*7c478bd9Sstevel@tonic-gate 2119*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; ++i) 2120*7c478bd9Sstevel@tonic-gate print_service(ary[i], verbose); 2121*7c478bd9Sstevel@tonic-gate } 2122*7c478bd9Sstevel@tonic-gate } 2123