17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53eae19d9Swesolows * Common Development and Distribution License (the "License"). 63eae19d9Swesolows * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 213eae19d9Swesolows 227c478bd9Sstevel@tonic-gate /* 23*2e1a9474SLiane Praza * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Service state explanation. For select services, display a description, the 297c478bd9Sstevel@tonic-gate * state, and possibly why the service is in that state, what's causing it to 307c478bd9Sstevel@tonic-gate * be in that state, and what other services it is keeping offline (impact). 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * Explaining states other than offline is easy. For maintenance and 337c478bd9Sstevel@tonic-gate * degraded, we just use the auxiliary state. For offline, we must determine 347c478bd9Sstevel@tonic-gate * which dependencies are unsatisfied and recurse. If a causal service is not 357c478bd9Sstevel@tonic-gate * offline, then a svcptr to it is added to the offline service's causes list. 367c478bd9Sstevel@tonic-gate * If a causal service is offline, then we recurse to determine its causes and 377c478bd9Sstevel@tonic-gate * merge them into the causes list of the service in question (see 387c478bd9Sstevel@tonic-gate * add_causes()). Note that by adding a self-pointing svcptr to the causes 397c478bd9Sstevel@tonic-gate * lists of services which are not offline or are offline for unknown reasons, 407c478bd9Sstevel@tonic-gate * we can always merge the unsatisfied dependency's causes into the 417c478bd9Sstevel@tonic-gate * dependent's list. 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * Computing an impact list is more involved because the dependencies in the 447c478bd9Sstevel@tonic-gate * repository are unidirectional; it requires determining the causes of all 457c478bd9Sstevel@tonic-gate * offline services. For each unsatisfied dependency of an offline service, 467c478bd9Sstevel@tonic-gate * a svcptr to the dependent is added to the dependency's impact_dependents 477c478bd9Sstevel@tonic-gate * list (see add_causes()). determine_impact() uses the lists to build an 487c478bd9Sstevel@tonic-gate * impact list. The direct dependency is used so that a path from the 497c478bd9Sstevel@tonic-gate * affected service to the causal service can be constructed (see 507c478bd9Sstevel@tonic-gate * print_dependency_reasons()). 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * Because we always need at least impact counts, we always run 537c478bd9Sstevel@tonic-gate * determine_causes() on all services. 547c478bd9Sstevel@tonic-gate * 557c478bd9Sstevel@tonic-gate * If no arguments are given, we must select the services which are causing 567c478bd9Sstevel@tonic-gate * other services to be offline. We do so by adding services which are not 577c478bd9Sstevel@tonic-gate * running for any reason other than another service to the g_causes list in 587c478bd9Sstevel@tonic-gate * determine_causes(). 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * Since all services must be examined, and their states may be consulted 617c478bd9Sstevel@tonic-gate * a lot, it is important that we only read volatile data (like states) from 627c478bd9Sstevel@tonic-gate * the repository once. add_instance() reads data for an instance from the 637c478bd9Sstevel@tonic-gate * repository into an inst_t and puts it into the "services" cache, which is 647c478bd9Sstevel@tonic-gate * organized as a hash table of svc_t's, each of which has a list of inst_t's. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include "svcs.h" 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #include <sys/stat.h> 707c478bd9Sstevel@tonic-gate #include <sys/wait.h> 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate #include <assert.h> 737c478bd9Sstevel@tonic-gate #include <errno.h> 747c478bd9Sstevel@tonic-gate #include <libintl.h> 757c478bd9Sstevel@tonic-gate #include <libuutil.h> 767c478bd9Sstevel@tonic-gate #include <libscf.h> 777c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 787c478bd9Sstevel@tonic-gate #include <string.h> 797c478bd9Sstevel@tonic-gate #include <stdio.h> 807c478bd9Sstevel@tonic-gate #include <stdlib.h> 817c478bd9Sstevel@tonic-gate #include <time.h> 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #define DC_DISABLED "SMF-8000-05" 857c478bd9Sstevel@tonic-gate #define DC_TEMPDISABLED "SMF-8000-1S" 867c478bd9Sstevel@tonic-gate #define DC_RSTRINVALID "SMF-8000-2A" 877c478bd9Sstevel@tonic-gate #define DC_RSTRABSENT "SMF-8000-3P" 887c478bd9Sstevel@tonic-gate #define DC_UNINIT "SMF-8000-4D" 897c478bd9Sstevel@tonic-gate #define DC_RSTRDEAD "SMF-8000-5H" 907c478bd9Sstevel@tonic-gate #define DC_ADMINMAINT "SMF-8000-63" 917c478bd9Sstevel@tonic-gate #define DC_REPTFAIL "SMF-8000-7Y" 927c478bd9Sstevel@tonic-gate #define DC_METHFAIL "SMF-8000-8Q" 937c478bd9Sstevel@tonic-gate #define DC_NONE "SMF-8000-9C" 947c478bd9Sstevel@tonic-gate #define DC_UNKNOWN "SMF-8000-AR" 957c478bd9Sstevel@tonic-gate #define DC_STARTING "SMF-8000-C4" 967c478bd9Sstevel@tonic-gate #define DC_ADMINDEGR "SMF-8000-DX" 977c478bd9Sstevel@tonic-gate #define DC_DEPABSENT "SMF-8000-E2" 987c478bd9Sstevel@tonic-gate #define DC_DEPRUNNING "SMF-8000-FJ" 997c478bd9Sstevel@tonic-gate #define DC_DEPOTHER "SMF-8000-GE" 1007c478bd9Sstevel@tonic-gate #define DC_DEPCYCLE "SMF-8000-HP" 1017c478bd9Sstevel@tonic-gate #define DC_INVALIDDEP "SMF-8000-JA" 1027c478bd9Sstevel@tonic-gate #define DC_STARTFAIL "SMF-8000-KS" 1037c478bd9Sstevel@tonic-gate #define DC_TOOQUICKLY "SMF-8000-L5" 1047c478bd9Sstevel@tonic-gate #define DC_INVALIDSTATE "SMF-8000-N3" 1057c478bd9Sstevel@tonic-gate #define DC_TRANSITION "SMF-8000-PH" 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate #define DEFAULT_MAN_PATH "/usr/share/man" 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate #define uu_list_append(lst, e) uu_list_insert_before(lst, NULL, e) 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate #ifdef NDEBUG 1137c478bd9Sstevel@tonic-gate #define bad_error(func, err) abort() 1147c478bd9Sstevel@tonic-gate #else 1157c478bd9Sstevel@tonic-gate #define bad_error(func, err) \ 1167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: %s() failed with unknown error %d.\n", \ 1177c478bd9Sstevel@tonic-gate __FILE__, __LINE__, func, err); \ 1187c478bd9Sstevel@tonic-gate abort(); 1197c478bd9Sstevel@tonic-gate #endif 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate typedef struct { 1237c478bd9Sstevel@tonic-gate const char *svcname; 1247c478bd9Sstevel@tonic-gate const char *instname; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* restarter pg properties */ 1277c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 1287c478bd9Sstevel@tonic-gate char next_state[MAX_SCF_STATE_STRING_SZ]; 1297c478bd9Sstevel@tonic-gate struct timeval stime; 1307c478bd9Sstevel@tonic-gate const char *aux_state; 1317c478bd9Sstevel@tonic-gate int64_t start_method_waitstatus; 1327c478bd9Sstevel@tonic-gate 133*2e1a9474SLiane Praza uint8_t enabled; 1347c478bd9Sstevel@tonic-gate int temporary; 1357c478bd9Sstevel@tonic-gate const char *restarter; 1367c478bd9Sstevel@tonic-gate uu_list_t *dependencies; /* list of dependency_group's */ 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate int active; /* In use? (cycle detection) */ 1397c478bd9Sstevel@tonic-gate int restarter_bad; 1407c478bd9Sstevel@tonic-gate const char *summary; 1417c478bd9Sstevel@tonic-gate uu_list_t *baddeps; /* list of dependency's */ 1427c478bd9Sstevel@tonic-gate uu_list_t *causes; /* list of svcptrs */ 1437c478bd9Sstevel@tonic-gate uu_list_t *impact_dependents; /* list of svcptrs */ 1447c478bd9Sstevel@tonic-gate uu_list_t *impact; /* list of svcptrs */ 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate uu_list_node_t node; 1477c478bd9Sstevel@tonic-gate } inst_t; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate typedef struct service { 1507c478bd9Sstevel@tonic-gate const char *svcname; 1517c478bd9Sstevel@tonic-gate uu_list_t *instances; 1527c478bd9Sstevel@tonic-gate struct service *next; 1537c478bd9Sstevel@tonic-gate } svc_t; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate struct svcptr { 1567c478bd9Sstevel@tonic-gate inst_t *svcp; 1577c478bd9Sstevel@tonic-gate inst_t *next_hop; 1587c478bd9Sstevel@tonic-gate uu_list_node_t node; 1597c478bd9Sstevel@tonic-gate }; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate struct dependency_group { 1627c478bd9Sstevel@tonic-gate enum { DGG_REQALL, DGG_REQANY, DGG_OPTALL, DGG_EXCALL } grouping; 1637c478bd9Sstevel@tonic-gate const char *type; 1647c478bd9Sstevel@tonic-gate uu_list_t *entities; /* List of struct dependency's */ 1657c478bd9Sstevel@tonic-gate uu_list_node_t node; 1667c478bd9Sstevel@tonic-gate }; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate struct dependency { 1697c478bd9Sstevel@tonic-gate const char *fmri; 1707c478bd9Sstevel@tonic-gate uu_list_node_t node; 1717c478bd9Sstevel@tonic-gate }; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* Hash table of service names -> svc_t's */ 1747c478bd9Sstevel@tonic-gate #define SVC_HASH_NBUCKETS 256 1757c478bd9Sstevel@tonic-gate #define SVC_HASH_MASK (SVC_HASH_NBUCKETS - 1) 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate static svc_t **services; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate static uu_list_pool_t *insts, *svcptrs, *depgroups, *deps; 1807c478bd9Sstevel@tonic-gate static uu_list_t *g_causes; /* list of svcptrs */ 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate static scf_scope_t *g_local_scope; 1837c478bd9Sstevel@tonic-gate static scf_service_t *g_svc; 1847c478bd9Sstevel@tonic-gate static scf_instance_t *g_inst; 1857c478bd9Sstevel@tonic-gate static scf_snapshot_t *g_snap; 1867c478bd9Sstevel@tonic-gate static scf_propertygroup_t *g_pg; 1877c478bd9Sstevel@tonic-gate static scf_property_t *g_prop; 1887c478bd9Sstevel@tonic-gate static scf_value_t *g_val; 1897c478bd9Sstevel@tonic-gate static scf_iter_t *g_iter, *g_viter; 1907c478bd9Sstevel@tonic-gate static char *g_fmri, *g_value; 1917c478bd9Sstevel@tonic-gate static size_t g_fmri_sz, g_value_sz; 1927c478bd9Sstevel@tonic-gate static const char *g_msgbase = "http://sun.com/msg/"; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate static char *emsg_nomem; 1957c478bd9Sstevel@tonic-gate static char *emsg_invalid_dep; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate extern scf_handle_t *h; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2007c478bd9Sstevel@tonic-gate static int 2017c478bd9Sstevel@tonic-gate svcptr_compare(struct svcptr *a, struct svcptr *b, void *data) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate return (b->svcp - a->svcp); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate static uint32_t 2077c478bd9Sstevel@tonic-gate hash_name(const char *name) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate uint32_t h = 0, g; 2107c478bd9Sstevel@tonic-gate const char *p; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate for (p = name; *p != '\0'; ++p) { 2137c478bd9Sstevel@tonic-gate h = (h << 4) + *p; 2147c478bd9Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) { 2157c478bd9Sstevel@tonic-gate h ^= (g >> 24); 2167c478bd9Sstevel@tonic-gate h ^= g; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate return (h); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate static void 2257c478bd9Sstevel@tonic-gate x_init(void) 2267c478bd9Sstevel@tonic-gate { 2277c478bd9Sstevel@tonic-gate emsg_nomem = gettext("Out of memory.\n"); 2287c478bd9Sstevel@tonic-gate emsg_invalid_dep = 2297c478bd9Sstevel@tonic-gate gettext("svc:/%s:%s has invalid dependency \"%s\".\n"); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate services = calloc(SVC_HASH_NBUCKETS, sizeof (*services)); 2327c478bd9Sstevel@tonic-gate if (services == NULL) 2337c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate insts = uu_list_pool_create("insts", sizeof (inst_t), 2367c478bd9Sstevel@tonic-gate offsetof(inst_t, node), NULL, UU_LIST_POOL_DEBUG); 2377c478bd9Sstevel@tonic-gate svcptrs = uu_list_pool_create("svcptrs", sizeof (struct svcptr), 2387c478bd9Sstevel@tonic-gate offsetof(struct svcptr, node), (uu_compare_fn_t *)svcptr_compare, 2397c478bd9Sstevel@tonic-gate UU_LIST_POOL_DEBUG); 2407c478bd9Sstevel@tonic-gate depgroups = uu_list_pool_create("depgroups", 2417c478bd9Sstevel@tonic-gate sizeof (struct dependency_group), 2427c478bd9Sstevel@tonic-gate offsetof(struct dependency_group, node), NULL, UU_LIST_POOL_DEBUG); 2437c478bd9Sstevel@tonic-gate deps = uu_list_pool_create("deps", sizeof (struct dependency), 2447c478bd9Sstevel@tonic-gate offsetof(struct dependency, node), NULL, UU_LIST_POOL_DEBUG); 2457c478bd9Sstevel@tonic-gate g_causes = uu_list_create(svcptrs, NULL, UU_LIST_DEBUG); 2467c478bd9Sstevel@tonic-gate if (insts == NULL || svcptrs == NULL || depgroups == NULL || 2477c478bd9Sstevel@tonic-gate deps == NULL || g_causes == NULL) 2487c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate if ((g_local_scope = scf_scope_create(h)) == NULL || 2517c478bd9Sstevel@tonic-gate (g_svc = scf_service_create(h)) == NULL || 2527c478bd9Sstevel@tonic-gate (g_inst = scf_instance_create(h)) == NULL || 2537c478bd9Sstevel@tonic-gate (g_snap = scf_snapshot_create(h)) == NULL || 2547c478bd9Sstevel@tonic-gate (g_pg = scf_pg_create(h)) == NULL || 2557c478bd9Sstevel@tonic-gate (g_prop = scf_property_create(h)) == NULL || 2567c478bd9Sstevel@tonic-gate (g_val = scf_value_create(h)) == NULL || 2577c478bd9Sstevel@tonic-gate (g_iter = scf_iter_create(h)) == NULL || 2587c478bd9Sstevel@tonic-gate (g_viter = scf_iter_create(h)) == NULL) 2597c478bd9Sstevel@tonic-gate scfdie(); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, g_local_scope) != 0) 2627c478bd9Sstevel@tonic-gate scfdie(); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate g_fmri_sz = max_scf_fmri_length + 1; 2657c478bd9Sstevel@tonic-gate g_fmri = safe_malloc(g_fmri_sz); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate g_value_sz = max_scf_value_length + 1; 2687c478bd9Sstevel@tonic-gate g_value = safe_malloc(g_value_sz); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * Repository loading routines. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * Returns 2777c478bd9Sstevel@tonic-gate * 0 - success 2787c478bd9Sstevel@tonic-gate * ECANCELED - inst was deleted 2797c478bd9Sstevel@tonic-gate * EINVAL - inst is invalid 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate static int 2827c478bd9Sstevel@tonic-gate load_dependencies(inst_t *svcp, scf_instance_t *inst) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 2857c478bd9Sstevel@tonic-gate struct dependency_group *dg; 2867c478bd9Sstevel@tonic-gate struct dependency *d; 2877c478bd9Sstevel@tonic-gate int r; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate assert(svcp->dependencies == NULL); 2907c478bd9Sstevel@tonic-gate svcp->dependencies = uu_list_create(depgroups, svcp, UU_LIST_DEBUG); 2917c478bd9Sstevel@tonic-gate if (svcp->dependencies == NULL) 2927c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", g_snap) == 0) { 2957c478bd9Sstevel@tonic-gate snap = g_snap; 2967c478bd9Sstevel@tonic-gate } else { 2977c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2987c478bd9Sstevel@tonic-gate scfdie(); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate snap = NULL; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(g_iter, inst, snap, 3047c478bd9Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) != 0) { 3057c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 3067c478bd9Sstevel@tonic-gate scfdie(); 3077c478bd9Sstevel@tonic-gate return (ECANCELED); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate for (;;) { 3117c478bd9Sstevel@tonic-gate r = scf_iter_next_pg(g_iter, g_pg); 3127c478bd9Sstevel@tonic-gate if (r == 0) 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate if (r != 1) { 3157c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 3167c478bd9Sstevel@tonic-gate scfdie(); 3177c478bd9Sstevel@tonic-gate return (ECANCELED); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate dg = safe_malloc(sizeof (*dg)); 3217c478bd9Sstevel@tonic-gate (void) memset(dg, 0, sizeof (*dg)); 3227c478bd9Sstevel@tonic-gate dg->entities = uu_list_create(deps, dg, UU_LIST_DEBUG); 3237c478bd9Sstevel@tonic-gate if (dg->entities == NULL) 3247c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_GROUPING, 3277c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, g_value, g_value_sz, 0) != 0) 3287c478bd9Sstevel@tonic-gate return (EINVAL); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if (strcmp(g_value, "require_all") == 0) 3317c478bd9Sstevel@tonic-gate dg->grouping = DGG_REQALL; 3327c478bd9Sstevel@tonic-gate else if (strcmp(g_value, "require_any") == 0) 3337c478bd9Sstevel@tonic-gate dg->grouping = DGG_REQANY; 3347c478bd9Sstevel@tonic-gate else if (strcmp(g_value, "optional_all") == 0) 3357c478bd9Sstevel@tonic-gate dg->grouping = DGG_OPTALL; 3367c478bd9Sstevel@tonic-gate else if (strcmp(g_value, "exclude_all") == 0) 3377c478bd9Sstevel@tonic-gate dg->grouping = DGG_EXCALL; 3387c478bd9Sstevel@tonic-gate else { 3397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has " 3407c478bd9Sstevel@tonic-gate "dependency with unknown type \"%s\".\n"), 3417c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname, g_value); 3427c478bd9Sstevel@tonic-gate return (EINVAL); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TYPE, SCF_TYPE_ASTRING, 3467c478bd9Sstevel@tonic-gate g_value, g_value_sz, 0) != 0) 3477c478bd9Sstevel@tonic-gate return (EINVAL); 3487c478bd9Sstevel@tonic-gate dg->type = safe_strdup(g_value); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (scf_pg_get_property(g_pg, SCF_PROPERTY_ENTITIES, g_prop) != 3517c478bd9Sstevel@tonic-gate 0) { 3527c478bd9Sstevel@tonic-gate switch (scf_error()) { 3537c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 3547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has " 3557c478bd9Sstevel@tonic-gate "dependency without an entities " 3567c478bd9Sstevel@tonic-gate "property.\n"), svcp->svcname, 3577c478bd9Sstevel@tonic-gate svcp->instname); 3587c478bd9Sstevel@tonic-gate return (EINVAL); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 3617c478bd9Sstevel@tonic-gate return (ECANCELED); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate default: 3647c478bd9Sstevel@tonic-gate scfdie(); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (scf_iter_property_values(g_viter, g_prop) != 0) { 3697c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 3707c478bd9Sstevel@tonic-gate scfdie(); 3717c478bd9Sstevel@tonic-gate return (ECANCELED); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate for (;;) { 3757c478bd9Sstevel@tonic-gate r = scf_iter_next_value(g_viter, g_val); 3767c478bd9Sstevel@tonic-gate if (r == 0) 3777c478bd9Sstevel@tonic-gate break; 3787c478bd9Sstevel@tonic-gate if (r != 1) { 3797c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 3807c478bd9Sstevel@tonic-gate scfdie(); 3817c478bd9Sstevel@tonic-gate return (ECANCELED); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate d = safe_malloc(sizeof (*d)); 3857c478bd9Sstevel@tonic-gate d->fmri = safe_malloc(max_scf_fmri_length + 1); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, (char *)d->fmri, 3887c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1) < 0) 3897c478bd9Sstevel@tonic-gate scfdie(); 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate uu_list_node_init(d, &d->node, deps); 3927c478bd9Sstevel@tonic-gate (void) uu_list_append(dg->entities, d); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate uu_list_node_init(dg, &dg->node, depgroups); 3967c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->dependencies, dg); 3977c478bd9Sstevel@tonic-gate assert(r == 0); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate return (0); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate static void 4047c478bd9Sstevel@tonic-gate add_instance(const char *svcname, const char *instname, scf_instance_t *inst) 4057c478bd9Sstevel@tonic-gate { 4067c478bd9Sstevel@tonic-gate inst_t *instp; 4077c478bd9Sstevel@tonic-gate svc_t *svcp; 4087c478bd9Sstevel@tonic-gate int have_enabled = 0; 409*2e1a9474SLiane Praza uint8_t i; 4107c478bd9Sstevel@tonic-gate uint32_t h; 411*2e1a9474SLiane Praza int r; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate h = hash_name(svcname) & SVC_HASH_MASK; 4147c478bd9Sstevel@tonic-gate for (svcp = services[h]; svcp != NULL; svcp = svcp->next) { 4157c478bd9Sstevel@tonic-gate if (strcmp(svcp->svcname, svcname) == 0) 4167c478bd9Sstevel@tonic-gate break; 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if (svcp == NULL) { 4207c478bd9Sstevel@tonic-gate svcp = safe_malloc(sizeof (*svcp)); 4217c478bd9Sstevel@tonic-gate svcp->svcname = safe_strdup(svcname); 4227c478bd9Sstevel@tonic-gate svcp->instances = uu_list_create(insts, svcp, UU_LIST_DEBUG); 4237c478bd9Sstevel@tonic-gate if (svcp->instances == NULL) 4247c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 4257c478bd9Sstevel@tonic-gate svcp->next = services[h]; 4267c478bd9Sstevel@tonic-gate services[h] = svcp; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate instp = safe_malloc(sizeof (*instp)); 4307c478bd9Sstevel@tonic-gate (void) memset(instp, 0, sizeof (*instp)); 4317c478bd9Sstevel@tonic-gate instp->svcname = svcp->svcname; 4327c478bd9Sstevel@tonic-gate instp->instname = safe_strdup(instname); 4337c478bd9Sstevel@tonic-gate instp->impact_dependents = 4347c478bd9Sstevel@tonic-gate uu_list_create(svcptrs, instp, UU_LIST_DEBUG); 4357c478bd9Sstevel@tonic-gate if (instp->impact_dependents == NULL) 4367c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, g_pg) != 0) { 4397c478bd9Sstevel@tonic-gate switch (scf_error()) { 4407c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 4417c478bd9Sstevel@tonic-gate return; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 4447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has no " 4457c478bd9Sstevel@tonic-gate "\"%s\" property group; ignoring.\n"), 4467c478bd9Sstevel@tonic-gate instp->svcname, instp->instname, SCF_PG_RESTARTER); 4477c478bd9Sstevel@tonic-gate return; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate default: 4507c478bd9Sstevel@tonic-gate scfdie(); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_STATE, SCF_TYPE_ASTRING, 4557c478bd9Sstevel@tonic-gate (void *)instp->state, sizeof (instp->state), 0) != 0) 4567c478bd9Sstevel@tonic-gate return; 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_NEXT_STATE, SCF_TYPE_ASTRING, 4597c478bd9Sstevel@tonic-gate (void *)instp->next_state, sizeof (instp->next_state), 0) != 0) 4607c478bd9Sstevel@tonic-gate return; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_STATE_TIMESTAMP, 4637c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, &instp->stime, 0, 0) != 0) 4647c478bd9Sstevel@tonic-gate return; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_AUX_STATE, SCF_TYPE_ASTRING, 4677c478bd9Sstevel@tonic-gate g_fmri, g_fmri_sz, 0) != 0) 4687c478bd9Sstevel@tonic-gate return; 4697c478bd9Sstevel@tonic-gate instp->aux_state = safe_strdup(g_fmri); 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate (void) pg_get_single_val(g_pg, SCF_PROPERTY_START_METHOD_WAITSTATUS, 4727c478bd9Sstevel@tonic-gate SCF_TYPE_INTEGER, &instp->start_method_waitstatus, 0, 0); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_GENERAL_OVR, g_pg) == 0) { 4757c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED, 4767c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN, &instp->enabled, 0, 0) == 0) 4777c478bd9Sstevel@tonic-gate have_enabled = 1; 4787c478bd9Sstevel@tonic-gate } else { 4797c478bd9Sstevel@tonic-gate switch (scf_error()) { 4807c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 4817c478bd9Sstevel@tonic-gate break; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 4847c478bd9Sstevel@tonic-gate return; 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate default: 4877c478bd9Sstevel@tonic-gate scfdie(); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_GENERAL, g_pg) != 4927c478bd9Sstevel@tonic-gate 0) { 4937c478bd9Sstevel@tonic-gate switch (scf_error()) { 4947c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 4957c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 4967c478bd9Sstevel@tonic-gate return; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate default: 4997c478bd9Sstevel@tonic-gate scfdie(); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN, 5047c478bd9Sstevel@tonic-gate &i, 0, 0) != 0) 5057c478bd9Sstevel@tonic-gate return; 5067c478bd9Sstevel@tonic-gate if (!have_enabled) { 5077c478bd9Sstevel@tonic-gate instp->enabled = i; 5087c478bd9Sstevel@tonic-gate instp->temporary = 0; 5097c478bd9Sstevel@tonic-gate } else { 5107c478bd9Sstevel@tonic-gate instp->temporary = (instp->enabled != i); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_RESTARTER, SCF_TYPE_ASTRING, 5147c478bd9Sstevel@tonic-gate g_fmri, g_fmri_sz, 0) == 0) 5157c478bd9Sstevel@tonic-gate instp->restarter = safe_strdup(g_fmri); 5167c478bd9Sstevel@tonic-gate else 5177c478bd9Sstevel@tonic-gate instp->restarter = SCF_SERVICE_STARTD; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (strcmp(instp->state, SCF_STATE_STRING_OFFLINE) == 0 && 5207c478bd9Sstevel@tonic-gate load_dependencies(instp, inst) != 0) 5217c478bd9Sstevel@tonic-gate return; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate uu_list_node_init(instp, &instp->node, insts); 524*2e1a9474SLiane Praza r = uu_list_append(svcp->instances, instp); 525*2e1a9474SLiane Praza assert(r == 0); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate static void 5297c478bd9Sstevel@tonic-gate load_services(void) 5307c478bd9Sstevel@tonic-gate { 5317c478bd9Sstevel@tonic-gate scf_iter_t *siter, *iiter; 5327c478bd9Sstevel@tonic-gate int r; 5337c478bd9Sstevel@tonic-gate char *svcname, *instname; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate if ((siter = scf_iter_create(h)) == NULL || 5367c478bd9Sstevel@tonic-gate (iiter = scf_iter_create(h)) == NULL) 5377c478bd9Sstevel@tonic-gate scfdie(); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate svcname = safe_malloc(max_scf_name_length + 1); 5407c478bd9Sstevel@tonic-gate instname = safe_malloc(max_scf_name_length + 1); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (scf_iter_scope_services(siter, g_local_scope) != 0) 5437c478bd9Sstevel@tonic-gate scfdie(); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate for (;;) { 5467c478bd9Sstevel@tonic-gate r = scf_iter_next_service(siter, g_svc); 5477c478bd9Sstevel@tonic-gate if (r == 0) 5487c478bd9Sstevel@tonic-gate break; 5497c478bd9Sstevel@tonic-gate if (r != 1) 5507c478bd9Sstevel@tonic-gate scfdie(); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate if (scf_service_get_name(g_svc, svcname, 5537c478bd9Sstevel@tonic-gate max_scf_name_length + 1) < 0) { 5547c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 5557c478bd9Sstevel@tonic-gate scfdie(); 5567c478bd9Sstevel@tonic-gate continue; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iiter, g_svc) != 0) { 5607c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 5617c478bd9Sstevel@tonic-gate scfdie(); 5627c478bd9Sstevel@tonic-gate continue; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate for (;;) { 5667c478bd9Sstevel@tonic-gate r = scf_iter_next_instance(iiter, g_inst); 5677c478bd9Sstevel@tonic-gate if (r == 0) 5687c478bd9Sstevel@tonic-gate break; 5697c478bd9Sstevel@tonic-gate if (r != 1) { 5707c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 5717c478bd9Sstevel@tonic-gate scfdie(); 5727c478bd9Sstevel@tonic-gate break; 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate if (scf_instance_get_name(g_inst, instname, 5767c478bd9Sstevel@tonic-gate max_scf_name_length + 1) < 0) { 5777c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 5787c478bd9Sstevel@tonic-gate scfdie(); 5797c478bd9Sstevel@tonic-gate continue; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate add_instance(svcname, instname, g_inst); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate free(svcname); 5877c478bd9Sstevel@tonic-gate free(instname); 5887c478bd9Sstevel@tonic-gate scf_iter_destroy(siter); 5897c478bd9Sstevel@tonic-gate scf_iter_destroy(iiter); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * Dependency analysis routines. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate static void 5977c478bd9Sstevel@tonic-gate add_svcptr(uu_list_t *lst, inst_t *svcp) 5987c478bd9Sstevel@tonic-gate { 5997c478bd9Sstevel@tonic-gate struct svcptr *spp; 6007c478bd9Sstevel@tonic-gate uu_list_index_t idx; 6017c478bd9Sstevel@tonic-gate int r; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate spp = safe_malloc(sizeof (*spp)); 6047c478bd9Sstevel@tonic-gate spp->svcp = svcp; 6057c478bd9Sstevel@tonic-gate spp->next_hop = NULL; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate if (uu_list_find(lst, spp, NULL, &idx) != NULL) { 6087c478bd9Sstevel@tonic-gate free(spp); 6097c478bd9Sstevel@tonic-gate return; 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate uu_list_node_init(spp, &spp->node, svcptrs); 6137c478bd9Sstevel@tonic-gate r = uu_list_append(lst, spp); 6147c478bd9Sstevel@tonic-gate assert(r == 0); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate static int determine_causes(inst_t *, void *); 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * Determine the causes of src and add them to the causes list of dst. 6217c478bd9Sstevel@tonic-gate * Returns ELOOP if src is active, and 0 otherwise. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate static int 6247c478bd9Sstevel@tonic-gate add_causes(inst_t *dst, inst_t *src) 6257c478bd9Sstevel@tonic-gate { 6267c478bd9Sstevel@tonic-gate struct svcptr *spp, *copy; 6277c478bd9Sstevel@tonic-gate uu_list_index_t idx; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (determine_causes(src, (void *)1) != UU_WALK_NEXT) { 6307c478bd9Sstevel@tonic-gate /* Dependency cycle. */ 6317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " svc:/%s:%s\n", dst->svcname, 6327c478bd9Sstevel@tonic-gate dst->instname); 6337c478bd9Sstevel@tonic-gate return (ELOOP); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate add_svcptr(src->impact_dependents, dst); 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate for (spp = uu_list_first(src->causes); 6397c478bd9Sstevel@tonic-gate spp != NULL; 6407c478bd9Sstevel@tonic-gate spp = uu_list_next(src->causes, spp)) { 6417c478bd9Sstevel@tonic-gate if (uu_list_find(dst->causes, spp, NULL, &idx) != NULL) 6427c478bd9Sstevel@tonic-gate continue; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate copy = safe_malloc(sizeof (*copy)); 6457c478bd9Sstevel@tonic-gate copy->svcp = spp->svcp; 6467c478bd9Sstevel@tonic-gate copy->next_hop = src; 6477c478bd9Sstevel@tonic-gate uu_list_node_init(copy, ©->node, svcptrs); 6487c478bd9Sstevel@tonic-gate uu_list_insert(dst->causes, copy, idx); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate add_svcptr(g_causes, spp->svcp); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate return (0); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate static int 6577c478bd9Sstevel@tonic-gate inst_running(inst_t *ip) 6587c478bd9Sstevel@tonic-gate { 6597c478bd9Sstevel@tonic-gate return (strcmp(ip->state, SCF_STATE_STRING_ONLINE) == 0 || 6607c478bd9Sstevel@tonic-gate strcmp(ip->state, SCF_STATE_STRING_DEGRADED) == 0); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate static int 6647c478bd9Sstevel@tonic-gate inst_running_or_maint(inst_t *ip) 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate return (inst_running(ip) || 6677c478bd9Sstevel@tonic-gate strcmp(ip->state, SCF_STATE_STRING_MAINT) == 0); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate static svc_t * 6717c478bd9Sstevel@tonic-gate get_svc(const char *sn) 6727c478bd9Sstevel@tonic-gate { 6737c478bd9Sstevel@tonic-gate uint32_t h; 6747c478bd9Sstevel@tonic-gate svc_t *svcp; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate h = hash_name(sn) & SVC_HASH_MASK; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate for (svcp = services[h]; svcp != NULL; svcp = svcp->next) { 6797c478bd9Sstevel@tonic-gate if (strcmp(svcp->svcname, sn) == 0) 6807c478bd9Sstevel@tonic-gate break; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate return (svcp); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6877c478bd9Sstevel@tonic-gate static inst_t * 6887c478bd9Sstevel@tonic-gate get_inst(svc_t *svcp, const char *in) 6897c478bd9Sstevel@tonic-gate { 6907c478bd9Sstevel@tonic-gate inst_t *instp; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate for (instp = uu_list_first(svcp->instances); 6937c478bd9Sstevel@tonic-gate instp != NULL; 6947c478bd9Sstevel@tonic-gate instp = uu_list_next(svcp->instances, instp)) { 6957c478bd9Sstevel@tonic-gate if (strcmp(instp->instname, in) == 0) 6967c478bd9Sstevel@tonic-gate return (instp); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate return (NULL); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate static int 7037c478bd9Sstevel@tonic-gate get_fmri(const char *fmri, svc_t **spp, inst_t **ipp) 7047c478bd9Sstevel@tonic-gate { 7057c478bd9Sstevel@tonic-gate const char *sn, *in; 7067c478bd9Sstevel@tonic-gate svc_t *sp; 7077c478bd9Sstevel@tonic-gate inst_t *ip; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if (strlcpy(g_fmri, fmri, g_fmri_sz) >= g_fmri_sz) 7107c478bd9Sstevel@tonic-gate return (EINVAL); 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(g_fmri, NULL, &sn, &in, NULL, NULL) != 0) 7137c478bd9Sstevel@tonic-gate return (EINVAL); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (sn == NULL) 7167c478bd9Sstevel@tonic-gate return (EINVAL); 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate sp = get_svc(sn); 7197c478bd9Sstevel@tonic-gate if (sp == NULL) 7207c478bd9Sstevel@tonic-gate return (ENOENT); 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate if (in != NULL) { 7237c478bd9Sstevel@tonic-gate ip = get_inst(sp, in); 7247c478bd9Sstevel@tonic-gate if (ip == NULL) 7257c478bd9Sstevel@tonic-gate return (ENOENT); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate if (spp != NULL) 7297c478bd9Sstevel@tonic-gate *spp = sp; 7307c478bd9Sstevel@tonic-gate if (ipp != NULL) 7317c478bd9Sstevel@tonic-gate *ipp = ((in == NULL) ? NULL : ip); 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate return (0); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate static int 7377c478bd9Sstevel@tonic-gate process_reqall(inst_t *svcp, struct dependency_group *dg) 7387c478bd9Sstevel@tonic-gate { 7397c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 7407c478bd9Sstevel@tonic-gate struct dependency *d; 7417c478bd9Sstevel@tonic-gate int r, svcrunning; 7427c478bd9Sstevel@tonic-gate svc_t *sp; 7437c478bd9Sstevel@tonic-gate inst_t *ip; 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 7467c478bd9Sstevel@tonic-gate if (walk == NULL) 7477c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 7507c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 7517c478bd9Sstevel@tonic-gate switch (r) { 7527c478bd9Sstevel@tonic-gate case EINVAL: 7537c478bd9Sstevel@tonic-gate /* LINTED */ 7547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 7557c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 7567c478bd9Sstevel@tonic-gate continue; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate case ENOENT: 7597c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 7607c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 7617c478bd9Sstevel@tonic-gate assert(r == 0); 7627c478bd9Sstevel@tonic-gate continue; 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate case 0: 7657c478bd9Sstevel@tonic-gate break; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate default: 7687c478bd9Sstevel@tonic-gate bad_error("get_fmri", r); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate if (ip != NULL) { 7727c478bd9Sstevel@tonic-gate if (inst_running(ip)) 7737c478bd9Sstevel@tonic-gate continue; 7747c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 7757c478bd9Sstevel@tonic-gate if (r != 0) { 7767c478bd9Sstevel@tonic-gate assert(r == ELOOP); 7777c478bd9Sstevel@tonic-gate return (r); 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate continue; 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate svcrunning = 0; 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 7857c478bd9Sstevel@tonic-gate ip != NULL; 7867c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 7877c478bd9Sstevel@tonic-gate if (inst_running(ip)) 7887c478bd9Sstevel@tonic-gate svcrunning = 1; 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate if (!svcrunning) { 7927c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 7937c478bd9Sstevel@tonic-gate ip != NULL; 7947c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 7957c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 7967c478bd9Sstevel@tonic-gate if (r != 0) { 7977c478bd9Sstevel@tonic-gate assert(r == ELOOP); 7987c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 7997c478bd9Sstevel@tonic-gate return (r); 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 8067c478bd9Sstevel@tonic-gate return (0); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate static int 8107c478bd9Sstevel@tonic-gate process_reqany(inst_t *svcp, struct dependency_group *dg) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate svc_t *sp; 8137c478bd9Sstevel@tonic-gate inst_t *ip; 8147c478bd9Sstevel@tonic-gate struct dependency *d; 8157c478bd9Sstevel@tonic-gate int r; 8167c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate for (d = uu_list_first(dg->entities); 8197c478bd9Sstevel@tonic-gate d != NULL; 8207c478bd9Sstevel@tonic-gate d = uu_list_next(dg->entities, d)) { 8217c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 8227c478bd9Sstevel@tonic-gate switch (r) { 8237c478bd9Sstevel@tonic-gate case 0: 8247c478bd9Sstevel@tonic-gate break; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate case EINVAL: 8277c478bd9Sstevel@tonic-gate /* LINTED */ 8287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 8297c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 8307c478bd9Sstevel@tonic-gate continue; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate case ENOENT: 8337c478bd9Sstevel@tonic-gate continue; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate default: 8367c478bd9Sstevel@tonic-gate bad_error("eval_svc_dep", r); 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (ip != NULL) { 8407c478bd9Sstevel@tonic-gate if (inst_running(ip)) 8417c478bd9Sstevel@tonic-gate return (0); 8427c478bd9Sstevel@tonic-gate continue; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 8467c478bd9Sstevel@tonic-gate ip != NULL; 8477c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 8487c478bd9Sstevel@tonic-gate if (inst_running(ip)) 8497c478bd9Sstevel@tonic-gate return (0); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate /* 8547c478bd9Sstevel@tonic-gate * The dependency group is not satisfied. Add all unsatisfied members 8557c478bd9Sstevel@tonic-gate * to the cause list. 8567c478bd9Sstevel@tonic-gate */ 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 8597c478bd9Sstevel@tonic-gate if (walk == NULL) 8607c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 8637c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 8647c478bd9Sstevel@tonic-gate switch (r) { 8657c478bd9Sstevel@tonic-gate case 0: 8667c478bd9Sstevel@tonic-gate break; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate case ENOENT: 8697c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 8707c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 8717c478bd9Sstevel@tonic-gate assert(r == 0); 8727c478bd9Sstevel@tonic-gate continue; 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate case EINVAL: 8757c478bd9Sstevel@tonic-gate /* Should have caught above. */ 8767c478bd9Sstevel@tonic-gate default: 8777c478bd9Sstevel@tonic-gate bad_error("eval_svc_dep", r); 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate if (ip != NULL) { 8817c478bd9Sstevel@tonic-gate if (inst_running(ip)) 8827c478bd9Sstevel@tonic-gate continue; 8837c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 8847c478bd9Sstevel@tonic-gate if (r != 0) { 8857c478bd9Sstevel@tonic-gate assert(r == ELOOP); 8867c478bd9Sstevel@tonic-gate return (r); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate continue; 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 8927c478bd9Sstevel@tonic-gate ip != NULL; 8937c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 8947c478bd9Sstevel@tonic-gate if (inst_running(ip)) 8957c478bd9Sstevel@tonic-gate continue; 8967c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 8977c478bd9Sstevel@tonic-gate if (r != 0) { 8987c478bd9Sstevel@tonic-gate assert(r == ELOOP); 8997c478bd9Sstevel@tonic-gate return (r); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate return (0); 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate static int 9087c478bd9Sstevel@tonic-gate process_optall(inst_t *svcp, struct dependency_group *dg) 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 9117c478bd9Sstevel@tonic-gate struct dependency *d; 9127c478bd9Sstevel@tonic-gate int r; 9137c478bd9Sstevel@tonic-gate inst_t *ip; 9147c478bd9Sstevel@tonic-gate svc_t *sp; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 9177c478bd9Sstevel@tonic-gate if (walk == NULL) 9187c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 9217c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate switch (r) { 9247c478bd9Sstevel@tonic-gate case 0: 9257c478bd9Sstevel@tonic-gate break; 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate case EINVAL: 9287c478bd9Sstevel@tonic-gate /* LINTED */ 9297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 9307c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 9317c478bd9Sstevel@tonic-gate continue; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate case ENOENT: 9347c478bd9Sstevel@tonic-gate continue; 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate default: 9377c478bd9Sstevel@tonic-gate bad_error("get_fmri", r); 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (ip != NULL) { 941*2e1a9474SLiane Praza if ((ip->enabled != 0) && !inst_running_or_maint(ip)) { 9427c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 9437c478bd9Sstevel@tonic-gate if (r != 0) { 9447c478bd9Sstevel@tonic-gate assert(r == ELOOP); 9457c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 9467c478bd9Sstevel@tonic-gate return (r); 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate continue; 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 9537c478bd9Sstevel@tonic-gate ip != NULL; 9547c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 955*2e1a9474SLiane Praza if ((ip->enabled != 0) && !inst_running_or_maint(ip)) { 9567c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 9577c478bd9Sstevel@tonic-gate if (r != 0) { 9587c478bd9Sstevel@tonic-gate assert(r == ELOOP); 9597c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 9607c478bd9Sstevel@tonic-gate return (r); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 9677c478bd9Sstevel@tonic-gate return (0); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate static int 9717c478bd9Sstevel@tonic-gate process_excall(inst_t *svcp, struct dependency_group *dg) 9727c478bd9Sstevel@tonic-gate { 9737c478bd9Sstevel@tonic-gate struct dependency *d; 9747c478bd9Sstevel@tonic-gate int r; 9757c478bd9Sstevel@tonic-gate svc_t *sp; 9767c478bd9Sstevel@tonic-gate inst_t *ip; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate for (d = uu_list_first(dg->entities); 9797c478bd9Sstevel@tonic-gate d != NULL; 9807c478bd9Sstevel@tonic-gate d = uu_list_next(dg->entities, d)) { 9817c478bd9Sstevel@tonic-gate r = get_fmri(d->fmri, &sp, &ip); 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate switch (r) { 9847c478bd9Sstevel@tonic-gate case 0: 9857c478bd9Sstevel@tonic-gate break; 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate case EINVAL: 9887c478bd9Sstevel@tonic-gate /* LINTED */ 9897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 9907c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 9917c478bd9Sstevel@tonic-gate continue; 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate case ENOENT: 9947c478bd9Sstevel@tonic-gate continue; 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate default: 9977c478bd9Sstevel@tonic-gate bad_error("eval_svc_dep", r); 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate if (ip != NULL) { 10017c478bd9Sstevel@tonic-gate if (inst_running(ip)) { 10027c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 10037c478bd9Sstevel@tonic-gate if (r != 0) { 10047c478bd9Sstevel@tonic-gate assert(r == ELOOP); 10057c478bd9Sstevel@tonic-gate return (r); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate continue; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate for (ip = uu_list_first(sp->instances); 10127c478bd9Sstevel@tonic-gate ip != NULL; 10137c478bd9Sstevel@tonic-gate ip = uu_list_next(sp->instances, ip)) { 10147c478bd9Sstevel@tonic-gate if (inst_running(ip)) { 10157c478bd9Sstevel@tonic-gate r = add_causes(svcp, ip); 10167c478bd9Sstevel@tonic-gate if (r != 0) { 10177c478bd9Sstevel@tonic-gate assert(r == ELOOP); 10187c478bd9Sstevel@tonic-gate return (r); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate return (0); 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate static int 10287c478bd9Sstevel@tonic-gate process_svc_dg(inst_t *svcp, struct dependency_group *dg) 10297c478bd9Sstevel@tonic-gate { 10307c478bd9Sstevel@tonic-gate switch (dg->grouping) { 10317c478bd9Sstevel@tonic-gate case DGG_REQALL: 10327c478bd9Sstevel@tonic-gate return (process_reqall(svcp, dg)); 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate case DGG_REQANY: 10357c478bd9Sstevel@tonic-gate return (process_reqany(svcp, dg)); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate case DGG_OPTALL: 10387c478bd9Sstevel@tonic-gate return (process_optall(svcp, dg)); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate case DGG_EXCALL: 10417c478bd9Sstevel@tonic-gate return (process_excall(svcp, dg)); 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate default: 10447c478bd9Sstevel@tonic-gate #ifndef NDEBUG 10457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10467c478bd9Sstevel@tonic-gate "%s:%d: Unknown dependency grouping %d.\n", __FILE__, 10477c478bd9Sstevel@tonic-gate __LINE__, dg->grouping); 10487c478bd9Sstevel@tonic-gate #endif 10497c478bd9Sstevel@tonic-gate abort(); 10507c478bd9Sstevel@tonic-gate /* NOTREACHED */ 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate /* 10557c478bd9Sstevel@tonic-gate * Returns 10567c478bd9Sstevel@tonic-gate * EINVAL - fmri is not a valid FMRI 10577c478bd9Sstevel@tonic-gate * 0 - the file indicated by fmri is missing 10587c478bd9Sstevel@tonic-gate * 1 - the file indicated by fmri is present 10597c478bd9Sstevel@tonic-gate */ 10607c478bd9Sstevel@tonic-gate static int 10617c478bd9Sstevel@tonic-gate eval_file_dep(const char *fmri) 10627c478bd9Sstevel@tonic-gate { 10637c478bd9Sstevel@tonic-gate const char *path; 10647c478bd9Sstevel@tonic-gate struct stat st; 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate if (strncmp(fmri, "file:", sizeof ("file:") - 1) != 0) 10677c478bd9Sstevel@tonic-gate return (EINVAL); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate path = fmri + (sizeof ("file:") - 1); 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate if (path[0] != '/') 10727c478bd9Sstevel@tonic-gate return (EINVAL); 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if (path[1] == '/') { 10757c478bd9Sstevel@tonic-gate path += 2; 10767c478bd9Sstevel@tonic-gate if (strncmp(path, "localhost/", sizeof ("localhost/") - 1) == 0) 10777c478bd9Sstevel@tonic-gate path += sizeof ("localhost") - 1; 10787c478bd9Sstevel@tonic-gate else if (path[0] != '/') 10797c478bd9Sstevel@tonic-gate return (EINVAL); 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate return (stat(path, &st) == 0 ? 1 : 0); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate static void 10867c478bd9Sstevel@tonic-gate process_file_dg(inst_t *svcp, struct dependency_group *dg) 10877c478bd9Sstevel@tonic-gate { 10887c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 10897c478bd9Sstevel@tonic-gate struct dependency *d, **deps; 10907c478bd9Sstevel@tonic-gate int r, i = 0, any_satisfied = 0; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate if (dg->grouping == DGG_REQANY) { 10937c478bd9Sstevel@tonic-gate deps = calloc(uu_list_numnodes(dg->entities), sizeof (*deps)); 10947c478bd9Sstevel@tonic-gate if (deps == NULL) 10957c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(dg->entities, UU_WALK_ROBUST); 10997c478bd9Sstevel@tonic-gate if (walk == NULL) 11007c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate while ((d = uu_list_walk_next(walk)) != NULL) { 11037c478bd9Sstevel@tonic-gate r = eval_file_dep(d->fmri); 11047c478bd9Sstevel@tonic-gate if (r == EINVAL) { 11057c478bd9Sstevel@tonic-gate /* LINTED */ 11067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, emsg_invalid_dep, svcp->svcname, 11077c478bd9Sstevel@tonic-gate svcp->instname, d->fmri); 11087c478bd9Sstevel@tonic-gate continue; 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate assert(r == 0 || r == 1); 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate switch (dg->grouping) { 11147c478bd9Sstevel@tonic-gate case DGG_REQALL: 11157c478bd9Sstevel@tonic-gate case DGG_OPTALL: 11167c478bd9Sstevel@tonic-gate if (r == 0) { 11177c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 11187c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 11197c478bd9Sstevel@tonic-gate assert(r == 0); 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate break; 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate case DGG_REQANY: 11247c478bd9Sstevel@tonic-gate if (r == 1) 11257c478bd9Sstevel@tonic-gate any_satisfied = 1; 11267c478bd9Sstevel@tonic-gate else 11277c478bd9Sstevel@tonic-gate deps[i++] = d; 11287c478bd9Sstevel@tonic-gate break; 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate case DGG_EXCALL: 11317c478bd9Sstevel@tonic-gate if (r == 1) { 11327c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, d); 11337c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, d); 11347c478bd9Sstevel@tonic-gate assert(r == 0); 11357c478bd9Sstevel@tonic-gate } 11367c478bd9Sstevel@tonic-gate break; 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate default: 11397c478bd9Sstevel@tonic-gate #ifndef NDEBUG 11407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: Unknown grouping %d.\n", 11417c478bd9Sstevel@tonic-gate __FILE__, __LINE__, dg->grouping); 11427c478bd9Sstevel@tonic-gate #endif 11437c478bd9Sstevel@tonic-gate abort(); 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate uu_list_walk_end(walk); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate if (dg->grouping != DGG_REQANY) 11507c478bd9Sstevel@tonic-gate return; 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate if (!any_satisfied) { 1153d87bb7dbSrm88369 while (--i >= 0) { 11547c478bd9Sstevel@tonic-gate uu_list_remove(dg->entities, deps[i]); 11557c478bd9Sstevel@tonic-gate r = uu_list_append(svcp->baddeps, deps[i]); 11567c478bd9Sstevel@tonic-gate assert(r == 0); 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate free(deps); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate /* 11647c478bd9Sstevel@tonic-gate * Populate the causes list of svcp. This function should not return with 11657c478bd9Sstevel@tonic-gate * causes empty. 11667c478bd9Sstevel@tonic-gate */ 11677c478bd9Sstevel@tonic-gate static int 11687c478bd9Sstevel@tonic-gate determine_causes(inst_t *svcp, void *canfailp) 11697c478bd9Sstevel@tonic-gate { 11707c478bd9Sstevel@tonic-gate struct dependency_group *dg; 11717c478bd9Sstevel@tonic-gate int r; 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate if (svcp->active) { 11747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Dependency cycle detected:\n" 11757c478bd9Sstevel@tonic-gate " svc:/%s:%s\n"), svcp->svcname, svcp->instname); 11767c478bd9Sstevel@tonic-gate return ((int)canfailp != 0 ? UU_WALK_ERROR : UU_WALK_NEXT); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate if (svcp->causes != NULL) 11807c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate svcp->causes = uu_list_create(svcptrs, svcp, UU_LIST_DEBUG); 11837c478bd9Sstevel@tonic-gate svcp->baddeps = uu_list_create(deps, svcp, UU_LIST_DEBUG); 11847c478bd9Sstevel@tonic-gate if (svcp->causes == NULL || svcp->baddeps == NULL) 11857c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate if (inst_running(svcp) || 11887c478bd9Sstevel@tonic-gate strcmp(svcp->state, SCF_STATE_STRING_UNINIT) == 0) { 11897c478bd9Sstevel@tonic-gate /* 11907c478bd9Sstevel@tonic-gate * If we're running, add a self-pointer in case we're 11917c478bd9Sstevel@tonic-gate * excluding another service. 11927c478bd9Sstevel@tonic-gate */ 11937c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 11947c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) { 11987c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 11997c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 12007c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) { 12047c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 1205*2e1a9474SLiane Praza if (svcp->enabled != 0) 12067c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) != 0) { 12127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 12137c478bd9Sstevel@tonic-gate gettext("svc:/%s:%s has invalid state \"%s\".\n"), 12147c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname, svcp->state); 12157c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 12167c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 12177c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate if (strcmp(svcp->next_state, SCF_STATE_STRING_NONE) != 0) { 12217c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 12227c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 12237c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate svcp->active = 1; 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate /* 12297c478bd9Sstevel@tonic-gate * Dependency analysis can add elements to our baddeps list (absent 12307c478bd9Sstevel@tonic-gate * dependency, unsatisfied file dependency), or to our cause list 12317c478bd9Sstevel@tonic-gate * (unsatisfied dependency). 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate for (dg = uu_list_first(svcp->dependencies); 12347c478bd9Sstevel@tonic-gate dg != NULL; 12357c478bd9Sstevel@tonic-gate dg = uu_list_next(svcp->dependencies, dg)) { 12367c478bd9Sstevel@tonic-gate if (strcmp(dg->type, "path") == 0) { 12377c478bd9Sstevel@tonic-gate process_file_dg(svcp, dg); 12387c478bd9Sstevel@tonic-gate } else if (strcmp(dg->type, "service") == 0) { 12397c478bd9Sstevel@tonic-gate int r; 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate r = process_svc_dg(svcp, dg); 12427c478bd9Sstevel@tonic-gate if (r != 0) { 12437c478bd9Sstevel@tonic-gate assert(r == ELOOP); 12447c478bd9Sstevel@tonic-gate svcp->active = 0; 12457c478bd9Sstevel@tonic-gate return ((int)canfailp != 0 ? 12467c478bd9Sstevel@tonic-gate UU_WALK_ERROR : UU_WALK_NEXT); 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate } else { 12497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("svc:/%s:%s has " 12507c478bd9Sstevel@tonic-gate "dependency group with invalid type \"%s\".\n"), 12517c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname, dg->type); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate if (uu_list_numnodes(svcp->causes) == 0) { 12567c478bd9Sstevel@tonic-gate if (uu_list_numnodes(svcp->baddeps) > 0) { 12577c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 12587c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 12597c478bd9Sstevel@tonic-gate } else { 12607c478bd9Sstevel@tonic-gate inst_t *restarter; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate r = get_fmri(svcp->restarter, NULL, &restarter); 12637c478bd9Sstevel@tonic-gate if (r == 0 && !inst_running(restarter)) { 12647c478bd9Sstevel@tonic-gate r = add_causes(svcp, restarter); 12657c478bd9Sstevel@tonic-gate if (r != 0) { 12667c478bd9Sstevel@tonic-gate assert(r == ELOOP); 12677c478bd9Sstevel@tonic-gate svcp->active = 0; 12687c478bd9Sstevel@tonic-gate return ((int)canfailp != 0 ? 12697c478bd9Sstevel@tonic-gate UU_WALK_ERROR : UU_WALK_NEXT); 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate } else { 12727c478bd9Sstevel@tonic-gate svcp->restarter_bad = r; 12737c478bd9Sstevel@tonic-gate add_svcptr(svcp->causes, svcp); 12747c478bd9Sstevel@tonic-gate add_svcptr(g_causes, svcp); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate assert(uu_list_numnodes(svcp->causes) > 0); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate svcp->active = 0; 12827c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate static void 12867c478bd9Sstevel@tonic-gate determine_all_causes(void) 12877c478bd9Sstevel@tonic-gate { 12887c478bd9Sstevel@tonic-gate svc_t *svcp; 12897c478bd9Sstevel@tonic-gate int i; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate for (i = 0; i < SVC_HASH_NBUCKETS; ++i) { 12927c478bd9Sstevel@tonic-gate for (svcp = services[i]; svcp != NULL; svcp = svcp->next) 12937c478bd9Sstevel@tonic-gate (void) uu_list_walk(svcp->instances, 12947c478bd9Sstevel@tonic-gate (uu_walk_fn_t *)determine_causes, 0, 0); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* 12997c478bd9Sstevel@tonic-gate * Returns 13007c478bd9Sstevel@tonic-gate * 0 - success 13017c478bd9Sstevel@tonic-gate * ELOOP - dependency cycle detected 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate static int 13047c478bd9Sstevel@tonic-gate determine_impact(inst_t *ip) 13057c478bd9Sstevel@tonic-gate { 13067c478bd9Sstevel@tonic-gate struct svcptr *idsp, *spp, *copy; 13077c478bd9Sstevel@tonic-gate uu_list_index_t idx; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate if (ip->active) { 13107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Dependency cycle detected:\n" 13117c478bd9Sstevel@tonic-gate " svc:/%s:%s\n"), ip->svcname, ip->instname); 13127c478bd9Sstevel@tonic-gate return (ELOOP); 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate if (ip->impact != NULL) 13167c478bd9Sstevel@tonic-gate return (0); 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate ip->impact = uu_list_create(svcptrs, ip, UU_LIST_DEBUG); 13197c478bd9Sstevel@tonic-gate if (ip->impact == NULL) 13207c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 13217c478bd9Sstevel@tonic-gate ip->active = 1; 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate for (idsp = uu_list_first(ip->impact_dependents); 13247c478bd9Sstevel@tonic-gate idsp != NULL; 13257c478bd9Sstevel@tonic-gate idsp = uu_list_next(ip->impact_dependents, idsp)) { 13267c478bd9Sstevel@tonic-gate if (determine_impact(idsp->svcp) != 0) { 13277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " svc:/%s:%s\n", 13287c478bd9Sstevel@tonic-gate ip->svcname, ip->instname); 13297c478bd9Sstevel@tonic-gate return (ELOOP); 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate add_svcptr(ip->impact, idsp->svcp); 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate for (spp = uu_list_first(idsp->svcp->impact); 13357c478bd9Sstevel@tonic-gate spp != NULL; 13367c478bd9Sstevel@tonic-gate spp = uu_list_next(idsp->svcp->impact, spp)) { 13377c478bd9Sstevel@tonic-gate if (uu_list_find(ip->impact, spp, NULL, &idx) != NULL) 13387c478bd9Sstevel@tonic-gate continue; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate copy = safe_malloc(sizeof (*copy)); 13417c478bd9Sstevel@tonic-gate copy->svcp = spp->svcp; 13427c478bd9Sstevel@tonic-gate copy->next_hop = NULL; 13437c478bd9Sstevel@tonic-gate uu_list_node_init(copy, ©->node, svcptrs); 13447c478bd9Sstevel@tonic-gate uu_list_insert(ip->impact, copy, idx); 13457c478bd9Sstevel@tonic-gate } 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate ip->active = 0; 13497c478bd9Sstevel@tonic-gate return (0); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate /* 13537c478bd9Sstevel@tonic-gate * Printing routines. 13547c478bd9Sstevel@tonic-gate */ 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate static void 13577c478bd9Sstevel@tonic-gate check_msgbase(void) 13587c478bd9Sstevel@tonic-gate { 13597c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, SCF_SERVICE_STARTD, NULL, NULL, g_inst, 13607c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) { 13617c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 13627c478bd9Sstevel@tonic-gate scfdie(); 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate return; 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(g_inst, NULL, "msg", g_pg) != 0) { 13687c478bd9Sstevel@tonic-gate switch (scf_error()) { 13697c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 13707c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13717c478bd9Sstevel@tonic-gate return; 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate default: 13747c478bd9Sstevel@tonic-gate scfdie(); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate if (scf_pg_get_property(g_pg, "base", g_prop) != 0) { 13797c478bd9Sstevel@tonic-gate switch (scf_error()) { 13807c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 13817c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13827c478bd9Sstevel@tonic-gate return; 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate default: 13857c478bd9Sstevel@tonic-gate scfdie(); 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate if (scf_property_get_value(g_prop, g_val) != 0) { 13907c478bd9Sstevel@tonic-gate switch (scf_error()) { 13917c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 13927c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 13933eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 13947c478bd9Sstevel@tonic-gate g_msgbase = NULL; 13957c478bd9Sstevel@tonic-gate return; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13987c478bd9Sstevel@tonic-gate return; 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate default: 14017c478bd9Sstevel@tonic-gate scfdie(); 14027c478bd9Sstevel@tonic-gate } 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, g_value, g_value_sz) < 0) { 14067c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH) 14077c478bd9Sstevel@tonic-gate scfdie(); 14087c478bd9Sstevel@tonic-gate return; 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate g_msgbase = safe_strdup(g_value); 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate static void 14157c478bd9Sstevel@tonic-gate determine_summary(inst_t *ip) 14167c478bd9Sstevel@tonic-gate { 14177c478bd9Sstevel@tonic-gate if (ip->summary != NULL) 14187c478bd9Sstevel@tonic-gate return; 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate if (inst_running(ip)) { 14217c478bd9Sstevel@tonic-gate ip->summary = gettext("is running."); 14227c478bd9Sstevel@tonic-gate return; 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (strcmp(ip->state, SCF_STATE_STRING_UNINIT) == 0) { 14267c478bd9Sstevel@tonic-gate ip->summary = gettext("is uninitialized."); 14277c478bd9Sstevel@tonic-gate } else if (strcmp(ip->state, SCF_STATE_STRING_DISABLED) == 0) { 14287c478bd9Sstevel@tonic-gate if (!ip->temporary) 14297c478bd9Sstevel@tonic-gate ip->summary = gettext("is disabled."); 14307c478bd9Sstevel@tonic-gate else 14317c478bd9Sstevel@tonic-gate ip->summary = gettext("is temporarily disabled."); 14327c478bd9Sstevel@tonic-gate } else if (strcmp(ip->state, SCF_STATE_STRING_OFFLINE) == 0) { 14337c478bd9Sstevel@tonic-gate if (uu_list_numnodes(ip->baddeps) != 0) 14347c478bd9Sstevel@tonic-gate ip->summary = gettext("has missing dependencies."); 14357c478bd9Sstevel@tonic-gate else if (strcmp(ip->next_state, SCF_STATE_STRING_ONLINE) == 0) 14367c478bd9Sstevel@tonic-gate ip->summary = gettext("is starting."); 14377c478bd9Sstevel@tonic-gate else 14387c478bd9Sstevel@tonic-gate ip->summary = gettext("is offline."); 14397c478bd9Sstevel@tonic-gate } else if (strcmp(ip->state, SCF_STATE_STRING_MAINT) == 0) { 14407c478bd9Sstevel@tonic-gate if (strcmp(ip->aux_state, "administrative_request") == 0) { 14417c478bd9Sstevel@tonic-gate ip->summary = gettext("was taken down for maintenace " 14427c478bd9Sstevel@tonic-gate "by an administrator."); 14437c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "dependency_cycle") == 0) { 14447c478bd9Sstevel@tonic-gate ip->summary = gettext("completed a dependency cycle."); 14457c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "fault_threshold_reached") == 14467c478bd9Sstevel@tonic-gate 0) { 14477c478bd9Sstevel@tonic-gate ip->summary = gettext("is not running because " 14487c478bd9Sstevel@tonic-gate "a method failed repeatedly."); 14497c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "invalid_dependency") == 0) { 14507c478bd9Sstevel@tonic-gate ip->summary = gettext("has an invalid dependency."); 14517c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "invalid_restarter") == 0) { 14527c478bd9Sstevel@tonic-gate ip->summary = gettext("has an invalid restarter."); 14537c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "method_failed") == 0) { 14547c478bd9Sstevel@tonic-gate ip->summary = gettext("is not running because " 14557c478bd9Sstevel@tonic-gate "a method failed."); 14567c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "none") == 0) { 14577c478bd9Sstevel@tonic-gate ip->summary = 14587c478bd9Sstevel@tonic-gate gettext("is not running for an unknown reason."); 14597c478bd9Sstevel@tonic-gate } else if (strcmp(ip->aux_state, "restarting_too_quickly") == 14607c478bd9Sstevel@tonic-gate 0) { 14617c478bd9Sstevel@tonic-gate ip->summary = gettext("was restarting too quickly."); 14627c478bd9Sstevel@tonic-gate } else { 14637c478bd9Sstevel@tonic-gate ip->summary = gettext("requires maintenance."); 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate } else { 14667c478bd9Sstevel@tonic-gate ip->summary = gettext("is in an invalid state."); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate static void 14717c478bd9Sstevel@tonic-gate print_method_failure(const inst_t *ip, const char **dcp) 14727c478bd9Sstevel@tonic-gate { 14737c478bd9Sstevel@tonic-gate char buf[50]; 14747c478bd9Sstevel@tonic-gate int stat = ip->start_method_waitstatus; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate if (stat != 0) { 14777c478bd9Sstevel@tonic-gate if (WIFEXITED(stat)) { 14787c478bd9Sstevel@tonic-gate if (WEXITSTATUS(stat) == SMF_EXIT_ERR_CONFIG) { 14797c478bd9Sstevel@tonic-gate (void) strlcpy(buf, gettext( 14807c478bd9Sstevel@tonic-gate "exited with $SMF_EXIT_ERR_CONFIG"), 14817c478bd9Sstevel@tonic-gate sizeof (buf)); 14827c478bd9Sstevel@tonic-gate } else if (WEXITSTATUS(stat) == SMF_EXIT_ERR_FATAL) { 14837c478bd9Sstevel@tonic-gate (void) strlcpy(buf, gettext( 14847c478bd9Sstevel@tonic-gate "exited with $SMF_EXIT_ERR_FATAL"), 14857c478bd9Sstevel@tonic-gate sizeof (buf)); 14867c478bd9Sstevel@tonic-gate } else { 14877c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 14887c478bd9Sstevel@tonic-gate gettext("exited with status %d"), 14897c478bd9Sstevel@tonic-gate WEXITSTATUS(stat)); 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate } else if (WIFSIGNALED(stat)) { 14927c478bd9Sstevel@tonic-gate if (WCOREDUMP(stat)) { 14937c478bd9Sstevel@tonic-gate if (strsignal(WTERMSIG(stat)) != NULL) 14947c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 14957c478bd9Sstevel@tonic-gate gettext("dumped core on %s (%d)"), 14967c478bd9Sstevel@tonic-gate strsignal(WTERMSIG(stat)), 14977c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 14987c478bd9Sstevel@tonic-gate else 14997c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 15007c478bd9Sstevel@tonic-gate gettext("dumped core signal %d"), 15017c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 15027c478bd9Sstevel@tonic-gate } else { 15037c478bd9Sstevel@tonic-gate if (strsignal(WTERMSIG(stat)) != NULL) { 15047c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 15057c478bd9Sstevel@tonic-gate gettext("died on %s (%d)"), 15067c478bd9Sstevel@tonic-gate strsignal(WTERMSIG(stat)), 15077c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 15087c478bd9Sstevel@tonic-gate } else { 15097c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 15107c478bd9Sstevel@tonic-gate gettext("died on signal %d"), 15117c478bd9Sstevel@tonic-gate WTERMSIG(stat)); 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate } 15147c478bd9Sstevel@tonic-gate } else { 15157c478bd9Sstevel@tonic-gate goto fail; 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate if (strcmp(ip->aux_state, "fault_threshold_reached") != 0) 15197c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Start method %s.\n"), 15207c478bd9Sstevel@tonic-gate buf); 15217c478bd9Sstevel@tonic-gate else 15227c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 15237c478bd9Sstevel@tonic-gate "Start method failed repeatedly, last %s.\n"), buf); 15247c478bd9Sstevel@tonic-gate *dcp = DC_STARTFAIL; 15257c478bd9Sstevel@tonic-gate } else { 15267c478bd9Sstevel@tonic-gate fail: 15277c478bd9Sstevel@tonic-gate if (strcmp(ip->aux_state, "fault_threshold_reached") == 0) 15287c478bd9Sstevel@tonic-gate (void) puts(gettext( 15297c478bd9Sstevel@tonic-gate "Reason: Method failed repeatedly.")); 15307c478bd9Sstevel@tonic-gate else 15317c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Method failed.")); 15327c478bd9Sstevel@tonic-gate *dcp = DC_METHFAIL; 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate static void 15377c478bd9Sstevel@tonic-gate print_dependency_reasons(const inst_t *svcp, int verbose) 15387c478bd9Sstevel@tonic-gate { 15397c478bd9Sstevel@tonic-gate struct dependency *d; 15407c478bd9Sstevel@tonic-gate struct svcptr *spp; 15417c478bd9Sstevel@tonic-gate const char *dc; 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate /* 15447c478bd9Sstevel@tonic-gate * If we couldn't determine why the service is offline, then baddeps 15457c478bd9Sstevel@tonic-gate * will be empty and causes will have a pointer to self. 15467c478bd9Sstevel@tonic-gate */ 15477c478bd9Sstevel@tonic-gate if (uu_list_numnodes(svcp->baddeps) == 0 && 15487c478bd9Sstevel@tonic-gate uu_list_numnodes(svcp->causes) == 1) { 15497c478bd9Sstevel@tonic-gate spp = uu_list_first(svcp->causes); 15507c478bd9Sstevel@tonic-gate if (spp->svcp == svcp) { 15517c478bd9Sstevel@tonic-gate switch (svcp->restarter_bad) { 15527c478bd9Sstevel@tonic-gate case 0: 15537c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Unknown.")); 15547c478bd9Sstevel@tonic-gate dc = DC_UNKNOWN; 15557c478bd9Sstevel@tonic-gate break; 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate case EINVAL: 15587c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 15597c478bd9Sstevel@tonic-gate "Restarter \"%s\" is invalid.\n"), 15607c478bd9Sstevel@tonic-gate svcp->restarter); 15617c478bd9Sstevel@tonic-gate dc = DC_RSTRINVALID; 15627c478bd9Sstevel@tonic-gate break; 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate case ENOENT: 15657c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 15667c478bd9Sstevel@tonic-gate "Restarter \"%s\" does not exist.\n"), 15677c478bd9Sstevel@tonic-gate svcp->restarter); 15687c478bd9Sstevel@tonic-gate dc = DC_RSTRABSENT; 15697c478bd9Sstevel@tonic-gate break; 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate default: 15727c478bd9Sstevel@tonic-gate #ifndef NDEBUG 15737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: Bad " 15747c478bd9Sstevel@tonic-gate "restarter_bad value %d. Aborting.\n", 15757c478bd9Sstevel@tonic-gate __FILE__, __LINE__, svcp->restarter_bad); 15767c478bd9Sstevel@tonic-gate #endif 15777c478bd9Sstevel@tonic-gate abort(); 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate if (g_msgbase) 15817c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), 15827c478bd9Sstevel@tonic-gate g_msgbase, dc); 15837c478bd9Sstevel@tonic-gate return; 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate for (d = uu_list_first(svcp->baddeps); 15887c478bd9Sstevel@tonic-gate d != NULL; 15897c478bd9Sstevel@tonic-gate d = uu_list_next(svcp->baddeps, d)) { 15907c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Dependency %s is absent.\n"), 15917c478bd9Sstevel@tonic-gate d->fmri); 15927c478bd9Sstevel@tonic-gate if (g_msgbase) 15937c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), g_msgbase, 15947c478bd9Sstevel@tonic-gate DC_DEPABSENT); 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate for (spp = uu_list_first(svcp->causes); 15987c478bd9Sstevel@tonic-gate spp != NULL && spp->svcp != svcp; 15997c478bd9Sstevel@tonic-gate spp = uu_list_next(svcp->causes, spp)) { 16007c478bd9Sstevel@tonic-gate determine_summary(spp->svcp); 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate if (inst_running(spp->svcp)) { 16037c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 16047c478bd9Sstevel@tonic-gate "Service svc:/%s:%s is running.\n"), 16057c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname); 16067c478bd9Sstevel@tonic-gate dc = DC_DEPRUNNING; 16077c478bd9Sstevel@tonic-gate } else { 16087c478bd9Sstevel@tonic-gate if (snprintf(NULL, 0, 16097c478bd9Sstevel@tonic-gate gettext("Reason: Service svc:/%s:%s %s"), 16107c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname, 16117c478bd9Sstevel@tonic-gate spp->svcp->summary) <= 80) { 16127c478bd9Sstevel@tonic-gate (void) printf(gettext( 16137c478bd9Sstevel@tonic-gate "Reason: Service svc:/%s:%s %s\n"), 16147c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname, 16157c478bd9Sstevel@tonic-gate spp->svcp->summary); 16167c478bd9Sstevel@tonic-gate } else { 16177c478bd9Sstevel@tonic-gate (void) printf(gettext( 16187c478bd9Sstevel@tonic-gate "Reason: Service svc:/%s:%s\n" 16197c478bd9Sstevel@tonic-gate " %s\n"), spp->svcp->svcname, 16207c478bd9Sstevel@tonic-gate spp->svcp->instname, spp->svcp->summary); 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate dc = DC_DEPOTHER; 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate if (g_msgbase != NULL) 16277c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), g_msgbase, dc); 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate if (verbose) { 16307c478bd9Sstevel@tonic-gate inst_t *pp; 16317c478bd9Sstevel@tonic-gate int indent; 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate (void) printf(gettext(" Path: svc:/%s:%s\n"), 16347c478bd9Sstevel@tonic-gate svcp->svcname, svcp->instname); 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate indent = 1; 16377c478bd9Sstevel@tonic-gate for (pp = spp->next_hop; ; ) { 16387c478bd9Sstevel@tonic-gate struct svcptr *tmp; 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate (void) printf(gettext("%6s %*ssvc:/%s:%s\n"), 16417c478bd9Sstevel@tonic-gate "", indent++ * 2, "", pp->svcname, 16427c478bd9Sstevel@tonic-gate pp->instname); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate if (pp == spp->svcp) 16457c478bd9Sstevel@tonic-gate break; 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate /* set pp to next_hop of cause with same svcp */ 16487c478bd9Sstevel@tonic-gate tmp = uu_list_find(pp->causes, spp, NULL, NULL); 16497c478bd9Sstevel@tonic-gate pp = tmp->next_hop; 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate } 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate static void 16567c478bd9Sstevel@tonic-gate print_reasons(const inst_t *svcp, int verbose) 16577c478bd9Sstevel@tonic-gate { 16587c478bd9Sstevel@tonic-gate int r; 16597c478bd9Sstevel@tonic-gate const char *dc = NULL; 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_ONLINE) == 0) 16627c478bd9Sstevel@tonic-gate return; 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate if (strcmp(svcp->state, SCF_STATE_STRING_UNINIT) == 0) { 16657c478bd9Sstevel@tonic-gate inst_t *rsp; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate r = get_fmri(svcp->restarter, NULL, &rsp); 16687c478bd9Sstevel@tonic-gate switch (r) { 16697c478bd9Sstevel@tonic-gate case 0: 16707c478bd9Sstevel@tonic-gate if (rsp != NULL) 16717c478bd9Sstevel@tonic-gate break; 16727c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate case EINVAL: 16757c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 16767c478bd9Sstevel@tonic-gate "Restarter \"%s\" is invalid.\n"), svcp->restarter); 16777c478bd9Sstevel@tonic-gate dc = DC_RSTRINVALID; 16787c478bd9Sstevel@tonic-gate goto diagcode; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate case ENOENT: 16817c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: " 16827c478bd9Sstevel@tonic-gate "Restarter \"%s\" does not exist.\n"), 16837c478bd9Sstevel@tonic-gate svcp->restarter); 16847c478bd9Sstevel@tonic-gate dc = DC_RSTRABSENT; 16857c478bd9Sstevel@tonic-gate goto diagcode; 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate default: 16887c478bd9Sstevel@tonic-gate bad_error("get_fmri", r); 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate if (inst_running(rsp)) { 16927c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Restarter %s " 16937c478bd9Sstevel@tonic-gate "has not initialized service state.\n"), 16947c478bd9Sstevel@tonic-gate svcp->restarter); 16957c478bd9Sstevel@tonic-gate dc = DC_UNINIT; 16967c478bd9Sstevel@tonic-gate } else { 16977c478bd9Sstevel@tonic-gate (void) printf(gettext( 16987c478bd9Sstevel@tonic-gate "Reason: Restarter %s is not running.\n"), 16997c478bd9Sstevel@tonic-gate svcp->restarter); 17007c478bd9Sstevel@tonic-gate dc = DC_RSTRDEAD; 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) { 17047c478bd9Sstevel@tonic-gate if (!svcp->temporary) { 17057c478bd9Sstevel@tonic-gate (void) puts(gettext( 17067c478bd9Sstevel@tonic-gate "Reason: Disabled by an administrator.")); 17077c478bd9Sstevel@tonic-gate dc = DC_DISABLED; 17087c478bd9Sstevel@tonic-gate } else { 17097c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: " 17107c478bd9Sstevel@tonic-gate "Temporarily disabled by an administrator.")); 17117c478bd9Sstevel@tonic-gate dc = DC_TEMPDISABLED; 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) { 17157c478bd9Sstevel@tonic-gate if (strcmp(svcp->aux_state, "administrative_request") == 0) { 17167c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: " 17177c478bd9Sstevel@tonic-gate "Maintenance requested by an administrator.")); 17187c478bd9Sstevel@tonic-gate dc = DC_ADMINMAINT; 17197c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "dependency_cycle") == 0) { 17207c478bd9Sstevel@tonic-gate (void) puts(gettext( 17217c478bd9Sstevel@tonic-gate "Reason: Completes a dependency cycle.")); 17227c478bd9Sstevel@tonic-gate dc = DC_DEPCYCLE; 17237c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "fault_threshold_reached") == 17247c478bd9Sstevel@tonic-gate 0) { 17257c478bd9Sstevel@tonic-gate print_method_failure(svcp, &dc); 17267c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "invalid_dependency") == 0) { 17277c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Has invalid dependency.")); 17287c478bd9Sstevel@tonic-gate dc = DC_INVALIDDEP; 17297c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "invalid_restarter") == 0) { 17307c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Restarter \"%s\" is " 17317c478bd9Sstevel@tonic-gate "invalid.\n"), svcp->restarter); 17327c478bd9Sstevel@tonic-gate dc = DC_RSTRINVALID; 17337c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "method_failed") == 0) { 17347c478bd9Sstevel@tonic-gate print_method_failure(svcp, &dc); 17357c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "restarting_too_quickly") == 17367c478bd9Sstevel@tonic-gate 0) { 17377c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Restarting too quickly.")); 17387c478bd9Sstevel@tonic-gate dc = DC_TOOQUICKLY; 17397c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->aux_state, "none") == 0) { 17407c478bd9Sstevel@tonic-gate (void) printf(gettext( 17417c478bd9Sstevel@tonic-gate "Reason: Restarter %s gave no explanation.\n"), 17427c478bd9Sstevel@tonic-gate svcp->restarter); 17437c478bd9Sstevel@tonic-gate dc = DC_NONE; 17447c478bd9Sstevel@tonic-gate } else { 17457c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Unknown.")); 17467c478bd9Sstevel@tonic-gate dc = DC_UNKNOWN; 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) == 0) { 17507c478bd9Sstevel@tonic-gate if (strcmp(svcp->next_state, SCF_STATE_STRING_ONLINE) == 0) { 17517c478bd9Sstevel@tonic-gate (void) puts(gettext( 17527c478bd9Sstevel@tonic-gate "Reason: Start method is running.")); 17537c478bd9Sstevel@tonic-gate dc = DC_STARTING; 17547c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->next_state, SCF_STATE_STRING_NONE) == 17557c478bd9Sstevel@tonic-gate 0) { 17567c478bd9Sstevel@tonic-gate print_dependency_reasons(svcp, verbose); 17577c478bd9Sstevel@tonic-gate /* Function prints diagcodes. */ 17587c478bd9Sstevel@tonic-gate return; 17597c478bd9Sstevel@tonic-gate } else { 17607c478bd9Sstevel@tonic-gate (void) printf(gettext( 17617c478bd9Sstevel@tonic-gate "Reason: Transitioning to state %s.\n"), 17627c478bd9Sstevel@tonic-gate svcp->next_state); 17637c478bd9Sstevel@tonic-gate dc = DC_TRANSITION; 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate } else if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0) { 17677c478bd9Sstevel@tonic-gate (void) puts(gettext("Reason: Degraded by an administrator.")); 17687c478bd9Sstevel@tonic-gate dc = DC_ADMINDEGR; 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate } else { 17717c478bd9Sstevel@tonic-gate (void) printf(gettext("Reason: Not in valid state (%s).\n"), 17727c478bd9Sstevel@tonic-gate svcp->state); 17737c478bd9Sstevel@tonic-gate dc = DC_INVALIDSTATE; 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate diagcode: 17777c478bd9Sstevel@tonic-gate if (g_msgbase != NULL) 17787c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s%s\n"), g_msgbase, dc); 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate static void 17827c478bd9Sstevel@tonic-gate print_manpage(int verbose) 17837c478bd9Sstevel@tonic-gate { 17847c478bd9Sstevel@tonic-gate static char *title = NULL; 17857c478bd9Sstevel@tonic-gate static char *section = NULL; 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate if (title == NULL) { 17887c478bd9Sstevel@tonic-gate title = safe_malloc(g_value_sz); 17897c478bd9Sstevel@tonic-gate section = safe_malloc(g_value_sz); 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_TITLE, SCF_TYPE_ASTRING, 17937c478bd9Sstevel@tonic-gate (void *)title, g_value_sz, 0) != 0) 17947c478bd9Sstevel@tonic-gate return; 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_SECTION, 17977c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, (void *)section, g_value_sz, 0) != 0) 17987c478bd9Sstevel@tonic-gate return; 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate if (!verbose) { 18017c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s(%s)\n"), title, section); 18027c478bd9Sstevel@tonic-gate return; 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_MANPATH, SCF_TYPE_ASTRING, 18067c478bd9Sstevel@tonic-gate (void *)g_value, g_value_sz, 0) != 0) 18077c478bd9Sstevel@tonic-gate return; 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate if (strcmp(g_value, ":default") == 0) { 18107c478bd9Sstevel@tonic-gate assert(sizeof (DEFAULT_MAN_PATH) < g_value_sz); 18117c478bd9Sstevel@tonic-gate (void) strcpy(g_value, DEFAULT_MAN_PATH); 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: man -M %s -s %s %s\n"), g_value, 18157c478bd9Sstevel@tonic-gate section, title); 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate static void 18197c478bd9Sstevel@tonic-gate print_doclink() 18207c478bd9Sstevel@tonic-gate { 18217c478bd9Sstevel@tonic-gate static char *uri = NULL; 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate if (uri == NULL) { 18247c478bd9Sstevel@tonic-gate uri = safe_malloc(g_value_sz); 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_URI, SCF_TYPE_ASTRING, 18287c478bd9Sstevel@tonic-gate (void *)uri, g_value_sz, 0) != 0) 18297c478bd9Sstevel@tonic-gate return; 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s\n"), uri); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate /* 18367c478bd9Sstevel@tonic-gate * Returns 18377c478bd9Sstevel@tonic-gate * 0 - success 18387c478bd9Sstevel@tonic-gate * 1 - inst was deleted 18397c478bd9Sstevel@tonic-gate */ 18407c478bd9Sstevel@tonic-gate static int 18417c478bd9Sstevel@tonic-gate print_docs(scf_instance_t *inst, int verbose) 18427c478bd9Sstevel@tonic-gate { 18437c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 18447c478bd9Sstevel@tonic-gate int r; 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", g_snap) != 0) { 18477c478bd9Sstevel@tonic-gate switch (scf_error()) { 18487c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 18497c478bd9Sstevel@tonic-gate break; 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 18527c478bd9Sstevel@tonic-gate return (1); 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate default: 18557c478bd9Sstevel@tonic-gate scfdie(); 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate 18587c478bd9Sstevel@tonic-gate snap = NULL; 18597c478bd9Sstevel@tonic-gate } else { 18607c478bd9Sstevel@tonic-gate snap = g_snap; 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(g_iter, inst, snap, 18647c478bd9Sstevel@tonic-gate SCF_GROUP_TEMPLATE) != 0) { 18657c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 18667c478bd9Sstevel@tonic-gate scfdie(); 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate return (1); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate for (;;) { 18727c478bd9Sstevel@tonic-gate r = scf_iter_next_pg(g_iter, g_pg); 18737c478bd9Sstevel@tonic-gate if (r == 0) 18747c478bd9Sstevel@tonic-gate break; 18757c478bd9Sstevel@tonic-gate if (r != 1) { 18767c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 18777c478bd9Sstevel@tonic-gate scfdie(); 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate return (1); 18807c478bd9Sstevel@tonic-gate } 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate if (scf_pg_get_name(g_pg, g_fmri, g_fmri_sz) < 0) { 18837c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_DELETED) 18847c478bd9Sstevel@tonic-gate scfdie(); 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate continue; 18877c478bd9Sstevel@tonic-gate } 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate if (strncmp(g_fmri, SCF_PG_TM_MAN_PREFIX, 18907c478bd9Sstevel@tonic-gate strlen(SCF_PG_TM_MAN_PREFIX)) == 0) { 18917c478bd9Sstevel@tonic-gate print_manpage(verbose); 18927c478bd9Sstevel@tonic-gate continue; 18937c478bd9Sstevel@tonic-gate } 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate if (strncmp(g_fmri, SCF_PG_TM_DOC_PREFIX, 18967c478bd9Sstevel@tonic-gate strlen(SCF_PG_TM_DOC_PREFIX)) == 0) { 18977c478bd9Sstevel@tonic-gate print_doclink(); 18987c478bd9Sstevel@tonic-gate continue; 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate return (0); 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate 19047c478bd9Sstevel@tonic-gate static void 19057c478bd9Sstevel@tonic-gate print_logs(scf_instance_t *inst) 19067c478bd9Sstevel@tonic-gate { 19077c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, g_pg) != 0) 19087c478bd9Sstevel@tonic-gate return; 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_ALT_LOGFILE, 19117c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, (void *)g_value, g_value_sz, 0) == 0) 19127c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s\n"), g_value); 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate if (pg_get_single_val(g_pg, SCF_PROPERTY_LOGFILE, 19157c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, (void *)g_value, g_value_sz, 0) == 0) 19167c478bd9Sstevel@tonic-gate (void) printf(gettext(" See: %s\n"), g_value); 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate static int first = 1; 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate /* 19227c478bd9Sstevel@tonic-gate * Explain why the given service is in the state it's in. 19237c478bd9Sstevel@tonic-gate */ 19247c478bd9Sstevel@tonic-gate static void 19257c478bd9Sstevel@tonic-gate print_service(inst_t *svcp, int verbose) 19267c478bd9Sstevel@tonic-gate { 19277c478bd9Sstevel@tonic-gate struct svcptr *spp; 19287c478bd9Sstevel@tonic-gate time_t stime; 19297c478bd9Sstevel@tonic-gate char *timebuf; 19307c478bd9Sstevel@tonic-gate size_t tbsz; 19317c478bd9Sstevel@tonic-gate struct tm *tmp; 19327c478bd9Sstevel@tonic-gate int deleted = 0; 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate if (first) 19357c478bd9Sstevel@tonic-gate first = 0; 19367c478bd9Sstevel@tonic-gate else 19377c478bd9Sstevel@tonic-gate (void) putchar('\n'); 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate (void) printf(gettext("svc:/%s:%s"), svcp->svcname, svcp->instname); 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate if (scf_scope_get_service(g_local_scope, svcp->svcname, g_svc) != 0) { 19427c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 19437c478bd9Sstevel@tonic-gate scfdie(); 19447c478bd9Sstevel@tonic-gate deleted = 1; 19457c478bd9Sstevel@tonic-gate } else if (scf_service_get_instance(g_svc, svcp->instname, g_inst) != 19467c478bd9Sstevel@tonic-gate 0) { 19477c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 19487c478bd9Sstevel@tonic-gate scfdie(); 19497c478bd9Sstevel@tonic-gate deleted = 1; 19507c478bd9Sstevel@tonic-gate } 19517c478bd9Sstevel@tonic-gate 19527c478bd9Sstevel@tonic-gate if (!deleted) { 19537c478bd9Sstevel@tonic-gate if (inst_get_single_val(g_inst, SCF_PG_TM_COMMON_NAME, locale, 19547c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, g_value, g_value_sz, 0, 0, 1) == 0) 19557c478bd9Sstevel@tonic-gate /* EMPTY */; 19567c478bd9Sstevel@tonic-gate else if (inst_get_single_val(g_inst, SCF_PG_TM_COMMON_NAME, "C", 19577c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, g_value, g_value_sz, 0, 0, 1) != 0) 19587c478bd9Sstevel@tonic-gate (void) strcpy(g_value, "?"); 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate (void) printf(gettext(" (%s)\n"), g_value); 19617c478bd9Sstevel@tonic-gate } else { 19627c478bd9Sstevel@tonic-gate (void) putchar('\n'); 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate stime = svcp->stime.tv_sec; 19667c478bd9Sstevel@tonic-gate tmp = localtime(&stime); 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate for (tbsz = 50; ; tbsz *= 2) { 19697c478bd9Sstevel@tonic-gate timebuf = safe_malloc(tbsz); 19707c478bd9Sstevel@tonic-gate if (strftime(timebuf, tbsz, NULL, tmp) != 0) 19717c478bd9Sstevel@tonic-gate break; 19727c478bd9Sstevel@tonic-gate free(timebuf); 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate (void) printf(gettext(" State: %s since %s\n"), svcp->state, timebuf); 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate free(timebuf); 19787c478bd9Sstevel@tonic-gate 19797c478bd9Sstevel@tonic-gate /* Reasons */ 19807c478bd9Sstevel@tonic-gate print_reasons(svcp, verbose); 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate if (!deleted) 19837c478bd9Sstevel@tonic-gate deleted = print_docs(g_inst, verbose); 19847c478bd9Sstevel@tonic-gate if (!deleted) 19857c478bd9Sstevel@tonic-gate print_logs(g_inst); 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate (void) determine_impact(svcp); 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate switch (uu_list_numnodes(svcp->impact)) { 19907c478bd9Sstevel@tonic-gate case 0: 19917c478bd9Sstevel@tonic-gate if (inst_running(svcp)) 19927c478bd9Sstevel@tonic-gate (void) puts(gettext("Impact: None.")); 19937c478bd9Sstevel@tonic-gate else 19947c478bd9Sstevel@tonic-gate (void) puts(gettext( 19957c478bd9Sstevel@tonic-gate "Impact: This service is not running.")); 19967c478bd9Sstevel@tonic-gate break; 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate case 1: 19997c478bd9Sstevel@tonic-gate if (!verbose) 20007c478bd9Sstevel@tonic-gate (void) puts(gettext("Impact: 1 dependent service " 20017c478bd9Sstevel@tonic-gate "is not running. (Use -v for list.)")); 20027c478bd9Sstevel@tonic-gate else 20037c478bd9Sstevel@tonic-gate (void) puts(gettext( 20047c478bd9Sstevel@tonic-gate "Impact: 1 dependent service is not running:")); 20057c478bd9Sstevel@tonic-gate break; 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate default: 20087c478bd9Sstevel@tonic-gate if (!verbose) 20097c478bd9Sstevel@tonic-gate (void) printf(gettext("Impact: %d dependent services " 20107c478bd9Sstevel@tonic-gate "are not running. (Use -v for list.)\n"), 20117c478bd9Sstevel@tonic-gate uu_list_numnodes(svcp->impact)); 20127c478bd9Sstevel@tonic-gate else 20137c478bd9Sstevel@tonic-gate (void) printf(gettext( 20147c478bd9Sstevel@tonic-gate "Impact: %d dependent services are not running:\n"), 20157c478bd9Sstevel@tonic-gate uu_list_numnodes(svcp->impact)); 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate if (verbose) { 20197c478bd9Sstevel@tonic-gate for (spp = uu_list_first(svcp->impact); 20207c478bd9Sstevel@tonic-gate spp != NULL; 20217c478bd9Sstevel@tonic-gate spp = uu_list_next(svcp->impact, spp)) 20227c478bd9Sstevel@tonic-gate (void) printf(gettext(" svc:/%s:%s\n"), 20237c478bd9Sstevel@tonic-gate spp->svcp->svcname, spp->svcp->instname); 20247c478bd9Sstevel@tonic-gate } 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate /* 20287c478bd9Sstevel@tonic-gate * Top level routine. 20297c478bd9Sstevel@tonic-gate */ 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate static int 20327c478bd9Sstevel@tonic-gate impact_compar(const void *a, const void *b) 20337c478bd9Sstevel@tonic-gate { 20347c478bd9Sstevel@tonic-gate int n, m; 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate n = uu_list_numnodes((*(inst_t **)a)->impact); 20377c478bd9Sstevel@tonic-gate m = uu_list_numnodes((*(inst_t **)b)->impact); 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate return (m - n); 20407c478bd9Sstevel@tonic-gate } 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate static int 20437c478bd9Sstevel@tonic-gate print_service_cb(void *verbose, scf_walkinfo_t *wip) 20447c478bd9Sstevel@tonic-gate { 20457c478bd9Sstevel@tonic-gate int r; 20467c478bd9Sstevel@tonic-gate inst_t *ip; 20477c478bd9Sstevel@tonic-gate 20487c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate r = get_fmri(wip->fmri, NULL, &ip); 20517c478bd9Sstevel@tonic-gate assert(r != EINVAL); 20527c478bd9Sstevel@tonic-gate if (r == ENOENT) 20537c478bd9Sstevel@tonic-gate return (0); 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate assert(r == 0); 20567c478bd9Sstevel@tonic-gate assert(ip != NULL); 20577c478bd9Sstevel@tonic-gate 20587c478bd9Sstevel@tonic-gate print_service(ip, (int)verbose); 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate return (0); 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate void 20647c478bd9Sstevel@tonic-gate explain(int verbose, int argc, char **argv) 20657c478bd9Sstevel@tonic-gate { 20667c478bd9Sstevel@tonic-gate /* Initialize globals. */ 20677c478bd9Sstevel@tonic-gate x_init(); 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate /* Walk the graph and populate services with inst_t's */ 20707c478bd9Sstevel@tonic-gate load_services(); 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate /* Populate causes for services. */ 20737c478bd9Sstevel@tonic-gate determine_all_causes(); 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate if (argc > 0) { 20767c478bd9Sstevel@tonic-gate scf_error_t err; 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate check_msgbase(); 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate /* Call print_service() for each operand. */ 20817c478bd9Sstevel@tonic-gate 20827c478bd9Sstevel@tonic-gate err = scf_walk_fmri(h, argc, argv, SCF_WALK_MULTIPLE, 20837c478bd9Sstevel@tonic-gate print_service_cb, (void *)verbose, &exit_status, uu_warn); 20847c478bd9Sstevel@tonic-gate if (err != 0) { 20857c478bd9Sstevel@tonic-gate uu_warn(gettext( 20867c478bd9Sstevel@tonic-gate "failed to iterate over instances: %s\n"), 20877c478bd9Sstevel@tonic-gate scf_strerror(err)); 20887c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 20897c478bd9Sstevel@tonic-gate } 20907c478bd9Sstevel@tonic-gate } else { 20917c478bd9Sstevel@tonic-gate struct svcptr *spp; 20927c478bd9Sstevel@tonic-gate int n, i; 20937c478bd9Sstevel@tonic-gate inst_t **ary; 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate /* Sort g_causes. */ 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate n = uu_list_numnodes(g_causes); 20987c478bd9Sstevel@tonic-gate if (n == 0) 20997c478bd9Sstevel@tonic-gate return; 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate check_msgbase(); 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate ary = calloc(n, sizeof (*ary)); 21047c478bd9Sstevel@tonic-gate if (ary == NULL) 21057c478bd9Sstevel@tonic-gate uu_die(emsg_nomem); 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate i = 0; 21087c478bd9Sstevel@tonic-gate for (spp = uu_list_first(g_causes); 21097c478bd9Sstevel@tonic-gate spp != NULL; 21107c478bd9Sstevel@tonic-gate spp = uu_list_next(g_causes, spp)) { 21117c478bd9Sstevel@tonic-gate (void) determine_impact(spp->svcp); 21127c478bd9Sstevel@tonic-gate ary[i++] = spp->svcp; 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate qsort(ary, n, sizeof (*ary), impact_compar); 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate /* Call print_service() for each service. */ 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate for (i = 0; i < n; ++i) 21207c478bd9Sstevel@tonic-gate print_service(ary[i], verbose); 21217c478bd9Sstevel@tonic-gate } 21227c478bd9Sstevel@tonic-gate } 2123