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