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