1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 23*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate * svcs - display attributes of service instances 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * We have two output formats and six instance selection mechanisms. The 32*7c478bd9Sstevel@tonic-gate * primary output format is a line of attributes (selected by -o), possibly 33*7c478bd9Sstevel@tonic-gate * followed by process description lines (if -p is specified), for each 34*7c478bd9Sstevel@tonic-gate * instance selected. The columns available to display are described by the 35*7c478bd9Sstevel@tonic-gate * struct column columns array. The columns to actually display are kept in 36*7c478bd9Sstevel@tonic-gate * the opt_columns array as indicies into the columns array. The selection 37*7c478bd9Sstevel@tonic-gate * mechanisms available for this format are service FMRIs (selects all child 38*7c478bd9Sstevel@tonic-gate * instances), instance FMRIs, instance FMRI glob patterns, instances with 39*7c478bd9Sstevel@tonic-gate * a certain restarter (-R), dependencies of instances (-d), and dependents of 40*7c478bd9Sstevel@tonic-gate * instances (-D). Since the lines must be sorted (per -sS), we'll just stick 41*7c478bd9Sstevel@tonic-gate * each into a data structure and print them in order when we're done. To 42*7c478bd9Sstevel@tonic-gate * avoid listing the same instance twice (when -d and -D aren't given), we'll 43*7c478bd9Sstevel@tonic-gate * use a hash table of FMRIs to record that we've listed (added to the tree) 44*7c478bd9Sstevel@tonic-gate * an instance. 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * The secondary output format (-l "long") is a paragraph of text for the 47*7c478bd9Sstevel@tonic-gate * services or instances selected. Not needing to be sorted, it's implemented 48*7c478bd9Sstevel@tonic-gate * by just calling print_detailed() for each FMRI given. 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include "svcs.h" 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* Get the byteorder macros to ease sorting. */ 54*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 55*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 56*7c478bd9Sstevel@tonic-gate #include <inttypes.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include <sys/contract.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/ctfs.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #include <assert.h> 63*7c478bd9Sstevel@tonic-gate #include <ctype.h> 64*7c478bd9Sstevel@tonic-gate #include <errno.h> 65*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 66*7c478bd9Sstevel@tonic-gate #include <fnmatch.h> 67*7c478bd9Sstevel@tonic-gate #include <libcontract.h> 68*7c478bd9Sstevel@tonic-gate #include <libcontract_priv.h> 69*7c478bd9Sstevel@tonic-gate #include <libintl.h> 70*7c478bd9Sstevel@tonic-gate #include <libscf.h> 71*7c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 72*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 73*7c478bd9Sstevel@tonic-gate #include <locale.h> 74*7c478bd9Sstevel@tonic-gate #include <procfs.h> 75*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 76*7c478bd9Sstevel@tonic-gate #include <stdio.h> 77*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 78*7c478bd9Sstevel@tonic-gate #include <strings.h> 79*7c478bd9Sstevel@tonic-gate #include <time.h> 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN 83*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD" 84*7c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #define LEGACY_SCHEME "lrc:" 87*7c478bd9Sstevel@tonic-gate #define LEGACY_UNKNOWN "unknown" 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate /* Flags for pg_get_single_val() */ 90*7c478bd9Sstevel@tonic-gate #define EMPTY_OK 0x01 91*7c478bd9Sstevel@tonic-gate #define MULTI_OK 0x02 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * An AVL-storable node for output lines and the keys to sort them by. 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate struct avl_string { 98*7c478bd9Sstevel@tonic-gate uu_avl_node_t node; 99*7c478bd9Sstevel@tonic-gate char *key; 100*7c478bd9Sstevel@tonic-gate char *str; 101*7c478bd9Sstevel@tonic-gate }; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * For lists of parsed restarter FMRIs. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate struct pfmri_list { 107*7c478bd9Sstevel@tonic-gate const char *scope; 108*7c478bd9Sstevel@tonic-gate const char *service; 109*7c478bd9Sstevel@tonic-gate const char *instance; 110*7c478bd9Sstevel@tonic-gate struct pfmri_list *next; 111*7c478bd9Sstevel@tonic-gate }; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * Globals 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 118*7c478bd9Sstevel@tonic-gate static scf_propertygroup_t *g_pg; 119*7c478bd9Sstevel@tonic-gate static scf_property_t *g_prop; 120*7c478bd9Sstevel@tonic-gate static scf_value_t *g_val; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate static size_t line_sz; /* Bytes in the header line. */ 123*7c478bd9Sstevel@tonic-gate static size_t sortkey_sz; /* Bytes in sort keys. */ 124*7c478bd9Sstevel@tonic-gate static uu_avl_pool_t *lines_pool; 125*7c478bd9Sstevel@tonic-gate static uu_avl_t *lines; /* Output lines. */ 126*7c478bd9Sstevel@tonic-gate int exit_status; 127*7c478bd9Sstevel@tonic-gate ssize_t max_scf_name_length; 128*7c478bd9Sstevel@tonic-gate ssize_t max_scf_value_length; 129*7c478bd9Sstevel@tonic-gate ssize_t max_scf_fmri_length; 130*7c478bd9Sstevel@tonic-gate static time_t now; 131*7c478bd9Sstevel@tonic-gate static struct pfmri_list *restarters = NULL; 132*7c478bd9Sstevel@tonic-gate static int first_paragraph = 1; /* For -l mode. */ 133*7c478bd9Sstevel@tonic-gate static char *common_name_buf; /* Sized for maximal length value. */ 134*7c478bd9Sstevel@tonic-gate char *locale; /* Current locale. */ 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* Options */ 137*7c478bd9Sstevel@tonic-gate static int *opt_columns = NULL; /* Indices into columns to display. */ 138*7c478bd9Sstevel@tonic-gate static int opt_cnum = 0; 139*7c478bd9Sstevel@tonic-gate static int opt_processes = 0; /* Print processes? */ 140*7c478bd9Sstevel@tonic-gate static int *opt_sort = NULL; /* Indices into columns to sort. */ 141*7c478bd9Sstevel@tonic-gate static int opt_snum = 0; 142*7c478bd9Sstevel@tonic-gate static int opt_nstate_shown = 0; /* Will nstate be shown? */ 143*7c478bd9Sstevel@tonic-gate static int opt_verbose = 0; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* Minimize string constants. */ 146*7c478bd9Sstevel@tonic-gate static const char * const scf_property_state = SCF_PROPERTY_STATE; 147*7c478bd9Sstevel@tonic-gate static const char * const scf_property_next_state = SCF_PROPERTY_NEXT_STATE; 148*7c478bd9Sstevel@tonic-gate static const char * const scf_property_contract = SCF_PROPERTY_CONTRACT; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* 152*7c478bd9Sstevel@tonic-gate * Utility functions 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * For unexpected libscf errors. The ending newline is necessary to keep 157*7c478bd9Sstevel@tonic-gate * uu_die() from appending the errno error. 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 160*7c478bd9Sstevel@tonic-gate void 161*7c478bd9Sstevel@tonic-gate do_scfdie(const char *file, int line) 162*7c478bd9Sstevel@tonic-gate { 163*7c478bd9Sstevel@tonic-gate uu_die(gettext("%s:%d: Unexpected libscf error: %s. Exiting.\n"), 164*7c478bd9Sstevel@tonic-gate file, line, scf_strerror(scf_error())); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate #else 167*7c478bd9Sstevel@tonic-gate void 168*7c478bd9Sstevel@tonic-gate scfdie(void) 169*7c478bd9Sstevel@tonic-gate { 170*7c478bd9Sstevel@tonic-gate uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"), 171*7c478bd9Sstevel@tonic-gate scf_strerror(scf_error())); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate #endif 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate void * 176*7c478bd9Sstevel@tonic-gate safe_malloc(size_t sz) 177*7c478bd9Sstevel@tonic-gate { 178*7c478bd9Sstevel@tonic-gate void *ptr; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate ptr = malloc(sz); 181*7c478bd9Sstevel@tonic-gate if (ptr == NULL) 182*7c478bd9Sstevel@tonic-gate uu_die(gettext("Out of memory")); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate return (ptr); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate char * 188*7c478bd9Sstevel@tonic-gate safe_strdup(const char *str) 189*7c478bd9Sstevel@tonic-gate { 190*7c478bd9Sstevel@tonic-gate char *cp; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate cp = strdup(str); 193*7c478bd9Sstevel@tonic-gate if (cp == NULL) 194*7c478bd9Sstevel@tonic-gate uu_die(gettext("Out of memory.\n")); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate return (cp); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate static void 200*7c478bd9Sstevel@tonic-gate sanitize_locale(char *locale) 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate for (; *locale != '\0'; locale++) 203*7c478bd9Sstevel@tonic-gate if (!isalnum(*locale)) 204*7c478bd9Sstevel@tonic-gate *locale = '_'; 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * FMRI hashtable. For uniquifing listings. 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate struct ht_elem { 212*7c478bd9Sstevel@tonic-gate const char *fmri; 213*7c478bd9Sstevel@tonic-gate struct ht_elem *next; 214*7c478bd9Sstevel@tonic-gate }; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate static struct ht_elem **ht_buckets; 217*7c478bd9Sstevel@tonic-gate static uint_t ht_buckets_num; 218*7c478bd9Sstevel@tonic-gate static uint_t ht_num; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate static void 221*7c478bd9Sstevel@tonic-gate ht_init() 222*7c478bd9Sstevel@tonic-gate { 223*7c478bd9Sstevel@tonic-gate ht_buckets_num = 8; 224*7c478bd9Sstevel@tonic-gate ht_buckets = safe_malloc(sizeof (*ht_buckets) * ht_buckets_num); 225*7c478bd9Sstevel@tonic-gate bzero(ht_buckets, sizeof (*ht_buckets) * ht_buckets_num); 226*7c478bd9Sstevel@tonic-gate ht_num = 0; 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate static uint_t 230*7c478bd9Sstevel@tonic-gate ht_hash_fmri(const char *fmri) 231*7c478bd9Sstevel@tonic-gate { 232*7c478bd9Sstevel@tonic-gate uint_t h = 0, g; 233*7c478bd9Sstevel@tonic-gate const char *p, *k; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* All FMRIs begin with svc:/, so skip that part. */ 236*7c478bd9Sstevel@tonic-gate assert(strncmp(fmri, "svc:/", sizeof ("svc:/") - 1) == 0); 237*7c478bd9Sstevel@tonic-gate k = fmri + sizeof ("svc:/") - 1; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * Generic hash function from uts/common/os/modhash.c. 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate for (p = k; *p != '\0'; ++p) { 243*7c478bd9Sstevel@tonic-gate h = (h << 4) + *p; 244*7c478bd9Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) { 245*7c478bd9Sstevel@tonic-gate h ^= (g >> 24); 246*7c478bd9Sstevel@tonic-gate h ^= g; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate return (h); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate static void 254*7c478bd9Sstevel@tonic-gate ht_grow() 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate uint_t new_ht_buckets_num; 257*7c478bd9Sstevel@tonic-gate struct ht_elem **new_ht_buckets; 258*7c478bd9Sstevel@tonic-gate int i; 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate new_ht_buckets_num = ht_buckets_num * 2; 261*7c478bd9Sstevel@tonic-gate assert(new_ht_buckets_num > ht_buckets_num); 262*7c478bd9Sstevel@tonic-gate new_ht_buckets = 263*7c478bd9Sstevel@tonic-gate safe_malloc(sizeof (*new_ht_buckets) * new_ht_buckets_num); 264*7c478bd9Sstevel@tonic-gate bzero(new_ht_buckets, sizeof (*new_ht_buckets) * new_ht_buckets_num); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate for (i = 0; i < ht_buckets_num; ++i) { 267*7c478bd9Sstevel@tonic-gate struct ht_elem *elem, *next; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate for (elem = ht_buckets[i]; elem != NULL; elem = next) { 270*7c478bd9Sstevel@tonic-gate uint_t h; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate next = elem->next; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate h = ht_hash_fmri(elem->fmri); 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate elem->next = 277*7c478bd9Sstevel@tonic-gate new_ht_buckets[h & (new_ht_buckets_num - 1)]; 278*7c478bd9Sstevel@tonic-gate new_ht_buckets[h & (new_ht_buckets_num - 1)] = elem; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate free(ht_buckets); 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate ht_buckets = new_ht_buckets; 285*7c478bd9Sstevel@tonic-gate ht_buckets_num = new_ht_buckets_num; 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * Add an FMRI to the hash table. Returns 1 if it was already there, 290*7c478bd9Sstevel@tonic-gate * 0 otherwise. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate static int 293*7c478bd9Sstevel@tonic-gate ht_add(const char *fmri) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate uint_t h; 296*7c478bd9Sstevel@tonic-gate struct ht_elem *elem; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate h = ht_hash_fmri(fmri); 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate elem = ht_buckets[h & (ht_buckets_num - 1)]; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate for (; elem != NULL; elem = elem->next) { 303*7c478bd9Sstevel@tonic-gate if (strcmp(elem->fmri, fmri) == 0) 304*7c478bd9Sstevel@tonic-gate return (1); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* Grow when average chain length is over 3. */ 308*7c478bd9Sstevel@tonic-gate if (ht_num > 3 * ht_buckets_num) 309*7c478bd9Sstevel@tonic-gate ht_grow(); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate ++ht_num; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate elem = safe_malloc(sizeof (*elem)); 314*7c478bd9Sstevel@tonic-gate elem->fmri = strdup(fmri); 315*7c478bd9Sstevel@tonic-gate elem->next = ht_buckets[h & (ht_buckets_num - 1)]; 316*7c478bd9Sstevel@tonic-gate ht_buckets[h & (ht_buckets_num - 1)] = elem; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate return (0); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * Convenience libscf wrapper functions. 325*7c478bd9Sstevel@tonic-gate */ 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * Get the single value of the named property in the given property group, 329*7c478bd9Sstevel@tonic-gate * which must have type ty, and put it in *vp. If ty is SCF_TYPE_ASTRING, vp 330*7c478bd9Sstevel@tonic-gate * is taken to be a char **, and sz is the size of the buffer. sz is unused 331*7c478bd9Sstevel@tonic-gate * otherwise. Return 0 on success, -1 if the property doesn't exist, has the 332*7c478bd9Sstevel@tonic-gate * wrong type, or doesn't have a single value. If flags has EMPTY_OK, don't 333*7c478bd9Sstevel@tonic-gate * complain if the property has no values (but return nonzero). If flags has 334*7c478bd9Sstevel@tonic-gate * MULTI_OK and the property has multiple values, succeed with E2BIG. 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate int 337*7c478bd9Sstevel@tonic-gate pg_get_single_val(scf_propertygroup_t *pg, const char *propname, scf_type_t ty, 338*7c478bd9Sstevel@tonic-gate void *vp, size_t sz, uint_t flags) 339*7c478bd9Sstevel@tonic-gate { 340*7c478bd9Sstevel@tonic-gate char *buf; 341*7c478bd9Sstevel@tonic-gate size_t buf_sz; 342*7c478bd9Sstevel@tonic-gate int ret = -1, r; 343*7c478bd9Sstevel@tonic-gate boolean_t multi = B_FALSE; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate assert((flags & ~(EMPTY_OK | MULTI_OK)) == 0); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, propname, g_prop) == -1) { 348*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 349*7c478bd9Sstevel@tonic-gate scfdie(); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate goto out; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate if (scf_property_is_type(g_prop, ty) != SCF_SUCCESS) { 355*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_TYPE_MISMATCH) 356*7c478bd9Sstevel@tonic-gate goto misconfigured; 357*7c478bd9Sstevel@tonic-gate scfdie(); 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(g_prop, g_val) != SCF_SUCCESS) { 361*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 362*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 363*7c478bd9Sstevel@tonic-gate if (flags & EMPTY_OK) 364*7c478bd9Sstevel@tonic-gate goto out; 365*7c478bd9Sstevel@tonic-gate goto misconfigured; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 368*7c478bd9Sstevel@tonic-gate if (flags & MULTI_OK) { 369*7c478bd9Sstevel@tonic-gate multi = B_TRUE; 370*7c478bd9Sstevel@tonic-gate break; 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate goto misconfigured; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate default: 375*7c478bd9Sstevel@tonic-gate scfdie(); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate switch (ty) { 380*7c478bd9Sstevel@tonic-gate case SCF_TYPE_ASTRING: 381*7c478bd9Sstevel@tonic-gate r = scf_value_get_astring(g_val, vp, sz) > 0 ? SCF_SUCCESS : -1; 382*7c478bd9Sstevel@tonic-gate break; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate case SCF_TYPE_BOOLEAN: 385*7c478bd9Sstevel@tonic-gate r = scf_value_get_boolean(g_val, (uint8_t *)vp); 386*7c478bd9Sstevel@tonic-gate break; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate case SCF_TYPE_COUNT: 389*7c478bd9Sstevel@tonic-gate r = scf_value_get_count(g_val, (uint64_t *)vp); 390*7c478bd9Sstevel@tonic-gate break; 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate case SCF_TYPE_INTEGER: 393*7c478bd9Sstevel@tonic-gate r = scf_value_get_integer(g_val, (int64_t *)vp); 394*7c478bd9Sstevel@tonic-gate break; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate case SCF_TYPE_TIME: { 397*7c478bd9Sstevel@tonic-gate int64_t sec; 398*7c478bd9Sstevel@tonic-gate int32_t ns; 399*7c478bd9Sstevel@tonic-gate r = scf_value_get_time(g_val, &sec, &ns); 400*7c478bd9Sstevel@tonic-gate ((struct timeval *)vp)->tv_sec = sec; 401*7c478bd9Sstevel@tonic-gate ((struct timeval *)vp)->tv_usec = ns / 1000; 402*7c478bd9Sstevel@tonic-gate break; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate case SCF_TYPE_USTRING: 406*7c478bd9Sstevel@tonic-gate r = scf_value_get_ustring(g_val, vp, sz) > 0 ? SCF_SUCCESS : -1; 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate default: 410*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 411*7c478bd9Sstevel@tonic-gate uu_warn("%s:%d: Unknown type %d.\n", __FILE__, __LINE__, ty); 412*7c478bd9Sstevel@tonic-gate #endif 413*7c478bd9Sstevel@tonic-gate abort(); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate if (r != SCF_SUCCESS) 416*7c478bd9Sstevel@tonic-gate scfdie(); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate ret = multi ? E2BIG : 0; 419*7c478bd9Sstevel@tonic-gate goto out; 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate misconfigured: 422*7c478bd9Sstevel@tonic-gate buf_sz = max_scf_fmri_length + 1; 423*7c478bd9Sstevel@tonic-gate buf = safe_malloc(buf_sz); 424*7c478bd9Sstevel@tonic-gate if (scf_property_to_fmri(g_prop, buf, buf_sz) == -1) 425*7c478bd9Sstevel@tonic-gate scfdie(); 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Property \"%s\" is misconfigured.\n"), buf); 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate free(buf); 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate out: 432*7c478bd9Sstevel@tonic-gate return (ret); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate static scf_snapshot_t * 436*7c478bd9Sstevel@tonic-gate get_running_snapshot(scf_instance_t *inst) 437*7c478bd9Sstevel@tonic-gate { 438*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate snap = scf_snapshot_create(h); 441*7c478bd9Sstevel@tonic-gate if (snap == NULL) 442*7c478bd9Sstevel@tonic-gate scfdie(); 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate if (scf_instance_get_snapshot(inst, "running", snap) == 0) 445*7c478bd9Sstevel@tonic-gate return (snap); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 448*7c478bd9Sstevel@tonic-gate scfdie(); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 451*7c478bd9Sstevel@tonic-gate return (NULL); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* 455*7c478bd9Sstevel@tonic-gate * As pg_get_single_val(), except look the property group up in an 456*7c478bd9Sstevel@tonic-gate * instance. If "use_running" is set, and the running snapshot exists, 457*7c478bd9Sstevel@tonic-gate * do a composed lookup there. Otherwise, do an (optionally composed) 458*7c478bd9Sstevel@tonic-gate * lookup on the current values. Note that lookups using snapshots are 459*7c478bd9Sstevel@tonic-gate * always composed. 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate int 462*7c478bd9Sstevel@tonic-gate inst_get_single_val(scf_instance_t *inst, const char *pgname, 463*7c478bd9Sstevel@tonic-gate const char *propname, scf_type_t ty, void *vp, size_t sz, uint_t flags, 464*7c478bd9Sstevel@tonic-gate int use_running, int composed) 465*7c478bd9Sstevel@tonic-gate { 466*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap = NULL; 467*7c478bd9Sstevel@tonic-gate int r; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (use_running) 470*7c478bd9Sstevel@tonic-gate snap = get_running_snapshot(inst); 471*7c478bd9Sstevel@tonic-gate if (composed || use_running) 472*7c478bd9Sstevel@tonic-gate r = scf_instance_get_pg_composed(inst, snap, pgname, g_pg); 473*7c478bd9Sstevel@tonic-gate else 474*7c478bd9Sstevel@tonic-gate r = scf_instance_get_pg(inst, pgname, g_pg); 475*7c478bd9Sstevel@tonic-gate if (snap) 476*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 477*7c478bd9Sstevel@tonic-gate if (r == -1) 478*7c478bd9Sstevel@tonic-gate return (-1); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate r = pg_get_single_val(g_pg, propname, ty, vp, sz, flags); 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate return (r); 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate static int 486*7c478bd9Sstevel@tonic-gate instance_enabled(scf_instance_t *inst, boolean_t temp) 487*7c478bd9Sstevel@tonic-gate { 488*7c478bd9Sstevel@tonic-gate uint8_t b; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate if (inst_get_single_val(inst, 491*7c478bd9Sstevel@tonic-gate temp ? SCF_PG_GENERAL_OVR : SCF_PG_GENERAL, SCF_PROPERTY_ENABLED, 492*7c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN, &b, 0, 0, 0, 0) != 0) 493*7c478bd9Sstevel@tonic-gate return (-1); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate return (b ? 1 : 0); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* 499*7c478bd9Sstevel@tonic-gate * Get a string property from the restarter property group of the given 500*7c478bd9Sstevel@tonic-gate * instance. Return an empty string on normal problems. 501*7c478bd9Sstevel@tonic-gate */ 502*7c478bd9Sstevel@tonic-gate static void 503*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(scf_instance_t *inst, const char *pname, 504*7c478bd9Sstevel@tonic-gate char *buf, size_t buf_sz) 505*7c478bd9Sstevel@tonic-gate { 506*7c478bd9Sstevel@tonic-gate if (inst_get_single_val(inst, SCF_PG_RESTARTER, pname, 507*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, buf, buf_sz, 0, 0, 1) != 0) 508*7c478bd9Sstevel@tonic-gate *buf = '\0'; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate static int 512*7c478bd9Sstevel@tonic-gate get_restarter_time_prop(scf_instance_t *inst, const char *pname, 513*7c478bd9Sstevel@tonic-gate struct timeval *tvp, int ok_if_empty) 514*7c478bd9Sstevel@tonic-gate { 515*7c478bd9Sstevel@tonic-gate int r; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate r = inst_get_single_val(inst, SCF_PG_RESTARTER, pname, SCF_TYPE_TIME, 518*7c478bd9Sstevel@tonic-gate tvp, NULL, ok_if_empty ? EMPTY_OK : 0, 0, 1); 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate return (r == 0 ? 0 : -1); 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate static int 524*7c478bd9Sstevel@tonic-gate get_restarter_count_prop(scf_instance_t *inst, const char *pname, uint64_t *cp, 525*7c478bd9Sstevel@tonic-gate uint_t flags) 526*7c478bd9Sstevel@tonic-gate { 527*7c478bd9Sstevel@tonic-gate return (inst_get_single_val(inst, SCF_PG_RESTARTER, pname, 528*7c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT, cp, 0, flags, 0, 1)); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate * Generic functions 534*7c478bd9Sstevel@tonic-gate */ 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate static int 537*7c478bd9Sstevel@tonic-gate propvals_to_pids(scf_propertygroup_t *pg, const char *pname, pid_t **pidsp, 538*7c478bd9Sstevel@tonic-gate uint_t *np, scf_property_t *prop, scf_value_t *val, scf_iter_t *iter) 539*7c478bd9Sstevel@tonic-gate { 540*7c478bd9Sstevel@tonic-gate scf_type_t ty; 541*7c478bd9Sstevel@tonic-gate int r, fd, err; 542*7c478bd9Sstevel@tonic-gate uint64_t c; 543*7c478bd9Sstevel@tonic-gate ct_stathdl_t ctst; 544*7c478bd9Sstevel@tonic-gate pid_t *pids; 545*7c478bd9Sstevel@tonic-gate uint_t m; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) != 0) { 548*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 549*7c478bd9Sstevel@tonic-gate scfdie(); 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate return (ENOENT); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != 0) 555*7c478bd9Sstevel@tonic-gate scfdie(); 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_COUNT) 558*7c478bd9Sstevel@tonic-gate return (EINVAL); 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) 561*7c478bd9Sstevel@tonic-gate scfdie(); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate for (;;) { 564*7c478bd9Sstevel@tonic-gate r = scf_iter_next_value(iter, val); 565*7c478bd9Sstevel@tonic-gate if (r == -1) 566*7c478bd9Sstevel@tonic-gate scfdie(); 567*7c478bd9Sstevel@tonic-gate if (r == 0) 568*7c478bd9Sstevel@tonic-gate break; 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate if (scf_value_get_count(val, &c) != 0) 571*7c478bd9Sstevel@tonic-gate scfdie(); 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate fd = contract_open(c, NULL, "status", O_RDONLY); 574*7c478bd9Sstevel@tonic-gate if (fd < 0) 575*7c478bd9Sstevel@tonic-gate continue; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate err = ct_status_read(fd, CTD_ALL, &ctst); 578*7c478bd9Sstevel@tonic-gate if (err != 0) { 579*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Could not read status of contract " 580*7c478bd9Sstevel@tonic-gate "%ld: %s.\n"), c, strerror(err)); 581*7c478bd9Sstevel@tonic-gate (void) close(fd); 582*7c478bd9Sstevel@tonic-gate continue; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate (void) close(fd); 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate r = ct_pr_status_get_members(ctst, &pids, &m); 588*7c478bd9Sstevel@tonic-gate assert(r == 0); 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate if (m == 0) { 591*7c478bd9Sstevel@tonic-gate ct_status_free(ctst); 592*7c478bd9Sstevel@tonic-gate continue; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate *pidsp = realloc(*pidsp, (*np + m) * sizeof (*pidsp)); 596*7c478bd9Sstevel@tonic-gate if (*pidsp == NULL) 597*7c478bd9Sstevel@tonic-gate uu_die(gettext("Out of memory")); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate bcopy(pids, *pidsp + *np, m * sizeof (*pids)); 600*7c478bd9Sstevel@tonic-gate *np += m; 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate ct_status_free(ctst); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate return (0); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate static int 609*7c478bd9Sstevel@tonic-gate instance_processes(scf_instance_t *inst, pid_t **pids, uint_t *np) 610*7c478bd9Sstevel@tonic-gate { 611*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 612*7c478bd9Sstevel@tonic-gate int ret; 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 615*7c478bd9Sstevel@tonic-gate scfdie(); 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, SCF_PG_RESTARTER, g_pg) == 0) { 618*7c478bd9Sstevel@tonic-gate *pids = NULL; 619*7c478bd9Sstevel@tonic-gate *np = 0; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate (void) propvals_to_pids(g_pg, scf_property_contract, pids, np, 622*7c478bd9Sstevel@tonic-gate g_prop, g_val, iter); 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate (void) propvals_to_pids(g_pg, SCF_PROPERTY_TRANSIENT_CONTRACT, 625*7c478bd9Sstevel@tonic-gate pids, np, g_prop, g_val, iter); 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate ret = 0; 628*7c478bd9Sstevel@tonic-gate } else { 629*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 630*7c478bd9Sstevel@tonic-gate scfdie(); 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate ret = -1; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate return (ret); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate static int 641*7c478bd9Sstevel@tonic-gate get_psinfo(pid_t pid, psinfo_t *psip) 642*7c478bd9Sstevel@tonic-gate { 643*7c478bd9Sstevel@tonic-gate char path[100]; 644*7c478bd9Sstevel@tonic-gate int fd; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "/proc/%lu/psinfo", pid); 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate fd = open64(path, O_RDONLY); 649*7c478bd9Sstevel@tonic-gate if (fd < 0) 650*7c478bd9Sstevel@tonic-gate return (-1); 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if (read(fd, psip, sizeof (*psip)) < 0) 653*7c478bd9Sstevel@tonic-gate uu_die(gettext("Could not read info for process %lu"), pid); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate (void) close(fd); 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate return (0); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* 663*7c478bd9Sstevel@tonic-gate * Column sprint and sortkey functions 664*7c478bd9Sstevel@tonic-gate */ 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate struct column { 667*7c478bd9Sstevel@tonic-gate const char *name; 668*7c478bd9Sstevel@tonic-gate int width; 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate /* 671*7c478bd9Sstevel@tonic-gate * This function should write the value for the column into buf, and 672*7c478bd9Sstevel@tonic-gate * grow or allocate buf accordingly. It should always write at least 673*7c478bd9Sstevel@tonic-gate * width bytes, blanking unused bytes with spaces. If the field is 674*7c478bd9Sstevel@tonic-gate * greater than the column width we allow it to overlap other columns. 675*7c478bd9Sstevel@tonic-gate * In particular, it shouldn't write any null bytes. (Though an extra 676*7c478bd9Sstevel@tonic-gate * null byte past the end is currently tolerated.) If the property 677*7c478bd9Sstevel@tonic-gate * group is non-NULL, then we are dealing with a legacy service. 678*7c478bd9Sstevel@tonic-gate */ 679*7c478bd9Sstevel@tonic-gate void (*sprint)(char **, scf_walkinfo_t *); 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate int sortkey_width; 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate /* 684*7c478bd9Sstevel@tonic-gate * This function should write sortkey_width bytes into buf which will 685*7c478bd9Sstevel@tonic-gate * cause memcmp() to sort it properly. (Unlike sprint() above, 686*7c478bd9Sstevel@tonic-gate * however, an extra null byte may overrun the buffer.) The second 687*7c478bd9Sstevel@tonic-gate * argument controls whether the results are sorted in forward or 688*7c478bd9Sstevel@tonic-gate * reverse order. 689*7c478bd9Sstevel@tonic-gate */ 690*7c478bd9Sstevel@tonic-gate void (*get_sortkey)(char *, int, scf_walkinfo_t *); 691*7c478bd9Sstevel@tonic-gate }; 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate static void 694*7c478bd9Sstevel@tonic-gate reverse_bytes(char *buf, size_t len) 695*7c478bd9Sstevel@tonic-gate { 696*7c478bd9Sstevel@tonic-gate int i; 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; ++i) 699*7c478bd9Sstevel@tonic-gate buf[i] = ~buf[i]; 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* CTID */ 703*7c478bd9Sstevel@tonic-gate #define CTID_COLUMN_WIDTH 6 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate static void 706*7c478bd9Sstevel@tonic-gate sprint_ctid(char **buf, scf_walkinfo_t *wip) 707*7c478bd9Sstevel@tonic-gate { 708*7c478bd9Sstevel@tonic-gate int r; 709*7c478bd9Sstevel@tonic-gate uint64_t c; 710*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + CTID_COLUMN_WIDTH + 2; 711*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate if (wip->pg != NULL) 714*7c478bd9Sstevel@tonic-gate r = pg_get_single_val(wip->pg, scf_property_contract, 715*7c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT, &c, 0, EMPTY_OK | MULTI_OK); 716*7c478bd9Sstevel@tonic-gate else 717*7c478bd9Sstevel@tonic-gate r = get_restarter_count_prop(wip->inst, scf_property_contract, 718*7c478bd9Sstevel@tonic-gate &c, EMPTY_OK | MULTI_OK); 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate if (r == 0) 721*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%*lu ", 722*7c478bd9Sstevel@tonic-gate *buf ? *buf : "", CTID_COLUMN_WIDTH, (ctid_t)c); 723*7c478bd9Sstevel@tonic-gate else if (r == E2BIG) 724*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%*lu* ", 725*7c478bd9Sstevel@tonic-gate *buf ? *buf : "", CTID_COLUMN_WIDTH - 1, (ctid_t)c); 726*7c478bd9Sstevel@tonic-gate else 727*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%*s ", 728*7c478bd9Sstevel@tonic-gate *buf ? *buf : "", CTID_COLUMN_WIDTH, "-"); 729*7c478bd9Sstevel@tonic-gate if (*buf) 730*7c478bd9Sstevel@tonic-gate free(*buf); 731*7c478bd9Sstevel@tonic-gate *buf = newbuf; 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate #define CTID_SORTKEY_WIDTH (sizeof (uint64_t)) 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate static void 737*7c478bd9Sstevel@tonic-gate sortkey_ctid(char *buf, int reverse, scf_walkinfo_t *wip) 738*7c478bd9Sstevel@tonic-gate { 739*7c478bd9Sstevel@tonic-gate int r; 740*7c478bd9Sstevel@tonic-gate uint64_t c; 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (wip->pg != NULL) 743*7c478bd9Sstevel@tonic-gate r = pg_get_single_val(wip->pg, scf_property_contract, 744*7c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT, &c, 0, EMPTY_OK); 745*7c478bd9Sstevel@tonic-gate else 746*7c478bd9Sstevel@tonic-gate r = get_restarter_count_prop(wip->inst, scf_property_contract, 747*7c478bd9Sstevel@tonic-gate &c, EMPTY_OK); 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate if (r == 0) { 750*7c478bd9Sstevel@tonic-gate /* 751*7c478bd9Sstevel@tonic-gate * Use the id itself, but it must be big-endian for this to 752*7c478bd9Sstevel@tonic-gate * work. 753*7c478bd9Sstevel@tonic-gate */ 754*7c478bd9Sstevel@tonic-gate c = BE_64(c); 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate bcopy(&c, buf, CTID_SORTKEY_WIDTH); 757*7c478bd9Sstevel@tonic-gate } else { 758*7c478bd9Sstevel@tonic-gate bzero(buf, CTID_SORTKEY_WIDTH); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate if (reverse) 762*7c478bd9Sstevel@tonic-gate reverse_bytes(buf, CTID_SORTKEY_WIDTH); 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate /* DESC */ 766*7c478bd9Sstevel@tonic-gate #define DESC_COLUMN_WIDTH 100 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate static void 769*7c478bd9Sstevel@tonic-gate sprint_desc(char **buf, scf_walkinfo_t *wip) 770*7c478bd9Sstevel@tonic-gate { 771*7c478bd9Sstevel@tonic-gate char *x; 772*7c478bd9Sstevel@tonic-gate size_t newsize; 773*7c478bd9Sstevel@tonic-gate char *newbuf; 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate if (common_name_buf == NULL) 776*7c478bd9Sstevel@tonic-gate common_name_buf = safe_malloc(max_scf_value_length + 1); 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate bzero(common_name_buf, max_scf_value_length + 1); 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate if (wip->pg != NULL) { 781*7c478bd9Sstevel@tonic-gate common_name_buf[0] = '-'; 782*7c478bd9Sstevel@tonic-gate } else if (inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, locale, 783*7c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0, 784*7c478bd9Sstevel@tonic-gate 1, 1) == -1 && 785*7c478bd9Sstevel@tonic-gate inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, "C", 786*7c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0, 787*7c478bd9Sstevel@tonic-gate 1, 1) == -1) { 788*7c478bd9Sstevel@tonic-gate common_name_buf[0] = '-'; 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate /* 792*7c478bd9Sstevel@tonic-gate * Collapse multi-line tm_common_name values into a single line. 793*7c478bd9Sstevel@tonic-gate */ 794*7c478bd9Sstevel@tonic-gate for (x = common_name_buf; *x != '\0'; x++) 795*7c478bd9Sstevel@tonic-gate if (*x == '\n') 796*7c478bd9Sstevel@tonic-gate *x = ' '; 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate if (strlen(common_name_buf) > DESC_COLUMN_WIDTH) 799*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + 800*7c478bd9Sstevel@tonic-gate strlen(common_name_buf) + 1; 801*7c478bd9Sstevel@tonic-gate else 802*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + DESC_COLUMN_WIDTH + 1; 803*7c478bd9Sstevel@tonic-gate newbuf = safe_malloc(newsize); 804*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 805*7c478bd9Sstevel@tonic-gate DESC_COLUMN_WIDTH, common_name_buf); 806*7c478bd9Sstevel@tonic-gate if (*buf) 807*7c478bd9Sstevel@tonic-gate free(*buf); 808*7c478bd9Sstevel@tonic-gate *buf = newbuf; 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 812*7c478bd9Sstevel@tonic-gate static void 813*7c478bd9Sstevel@tonic-gate sortkey_desc(char *buf, int reverse, scf_walkinfo_t *wip) 814*7c478bd9Sstevel@tonic-gate { 815*7c478bd9Sstevel@tonic-gate bzero(buf, DESC_COLUMN_WIDTH); 816*7c478bd9Sstevel@tonic-gate } 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate /* State columns (STATE, NSTATE, S, N, SN, STA, NSTA) */ 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate static char 821*7c478bd9Sstevel@tonic-gate state_to_char(const char *state) 822*7c478bd9Sstevel@tonic-gate { 823*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0) 824*7c478bd9Sstevel@tonic-gate return ('u'); 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0) 827*7c478bd9Sstevel@tonic-gate return ('0'); 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0) 830*7c478bd9Sstevel@tonic-gate return ('1'); 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) 833*7c478bd9Sstevel@tonic-gate return ('m'); 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0) 836*7c478bd9Sstevel@tonic-gate return ('d'); 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0) 839*7c478bd9Sstevel@tonic-gate return ('D'); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_LEGACY) == 0) 842*7c478bd9Sstevel@tonic-gate return ('L'); 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate return ('?'); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* Return true if inst is transitioning. */ 848*7c478bd9Sstevel@tonic-gate static int 849*7c478bd9Sstevel@tonic-gate transitioning(scf_instance_t *inst) 850*7c478bd9Sstevel@tonic-gate { 851*7c478bd9Sstevel@tonic-gate char nstate_name[MAX_SCF_STATE_STRING_SZ]; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(inst, scf_property_next_state, nstate_name, 854*7c478bd9Sstevel@tonic-gate sizeof (nstate_name)); 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate return (state_to_char(nstate_name) != '?'); 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 860*7c478bd9Sstevel@tonic-gate static void 861*7c478bd9Sstevel@tonic-gate sortkey_states(const char *pname, char *buf, int reverse, scf_walkinfo_t *wip) 862*7c478bd9Sstevel@tonic-gate { 863*7c478bd9Sstevel@tonic-gate char state_name[MAX_SCF_STATE_STRING_SZ]; 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate /* 866*7c478bd9Sstevel@tonic-gate * Lower numbers are printed first, so these are arranged from least 867*7c478bd9Sstevel@tonic-gate * interesting ("legacy run") to most interesting (unknown). 868*7c478bd9Sstevel@tonic-gate */ 869*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 870*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, pname, state_name, 871*7c478bd9Sstevel@tonic-gate sizeof (state_name)); 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate if (strcmp(state_name, SCF_STATE_STRING_ONLINE) == 0) 874*7c478bd9Sstevel@tonic-gate *buf = 2; 875*7c478bd9Sstevel@tonic-gate else if (strcmp(state_name, SCF_STATE_STRING_DEGRADED) == 0) 876*7c478bd9Sstevel@tonic-gate *buf = 3; 877*7c478bd9Sstevel@tonic-gate else if (strcmp(state_name, SCF_STATE_STRING_OFFLINE) == 0) 878*7c478bd9Sstevel@tonic-gate *buf = 4; 879*7c478bd9Sstevel@tonic-gate else if (strcmp(state_name, SCF_STATE_STRING_MAINT) == 0) 880*7c478bd9Sstevel@tonic-gate *buf = 5; 881*7c478bd9Sstevel@tonic-gate else if (strcmp(state_name, SCF_STATE_STRING_DISABLED) == 0) 882*7c478bd9Sstevel@tonic-gate *buf = 1; 883*7c478bd9Sstevel@tonic-gate else if (strcmp(state_name, SCF_STATE_STRING_UNINIT) == 0) 884*7c478bd9Sstevel@tonic-gate *buf = 6; 885*7c478bd9Sstevel@tonic-gate else 886*7c478bd9Sstevel@tonic-gate *buf = 7; 887*7c478bd9Sstevel@tonic-gate } else 888*7c478bd9Sstevel@tonic-gate *buf = 0; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate if (reverse) 891*7c478bd9Sstevel@tonic-gate *buf = 255 - *buf; 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate static void 895*7c478bd9Sstevel@tonic-gate sprint_state(char **buf, scf_walkinfo_t *wip) 896*7c478bd9Sstevel@tonic-gate { 897*7c478bd9Sstevel@tonic-gate char state_name[MAX_SCF_STATE_STRING_SZ + 1]; 898*7c478bd9Sstevel@tonic-gate size_t newsize; 899*7c478bd9Sstevel@tonic-gate char *newbuf; 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 902*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_state, 903*7c478bd9Sstevel@tonic-gate state_name, sizeof (state_name)); 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* Don't print blank fields, to ease parsing. */ 906*7c478bd9Sstevel@tonic-gate if (state_name[0] == '\0') { 907*7c478bd9Sstevel@tonic-gate state_name[0] = '-'; 908*7c478bd9Sstevel@tonic-gate state_name[1] = '\0'; 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate if (!opt_nstate_shown && transitioning(wip->inst)) { 912*7c478bd9Sstevel@tonic-gate /* Append an asterisk if nstate is valid. */ 913*7c478bd9Sstevel@tonic-gate (void) strcat(state_name, "*"); 914*7c478bd9Sstevel@tonic-gate } 915*7c478bd9Sstevel@tonic-gate } else 916*7c478bd9Sstevel@tonic-gate (void) strcpy(state_name, SCF_STATE_STRING_LEGACY); 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + MAX_SCF_STATE_STRING_SZ + 2; 919*7c478bd9Sstevel@tonic-gate newbuf = safe_malloc(newsize); 920*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 921*7c478bd9Sstevel@tonic-gate MAX_SCF_STATE_STRING_SZ + 1, state_name); 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate if (*buf) 924*7c478bd9Sstevel@tonic-gate free(*buf); 925*7c478bd9Sstevel@tonic-gate *buf = newbuf; 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate static void 929*7c478bd9Sstevel@tonic-gate sortkey_state(char *buf, int reverse, scf_walkinfo_t *wip) 930*7c478bd9Sstevel@tonic-gate { 931*7c478bd9Sstevel@tonic-gate sortkey_states(scf_property_state, buf, reverse, wip); 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate static void 935*7c478bd9Sstevel@tonic-gate sprint_nstate(char **buf, scf_walkinfo_t *wip) 936*7c478bd9Sstevel@tonic-gate { 937*7c478bd9Sstevel@tonic-gate char next_state_name[MAX_SCF_STATE_STRING_SZ]; 938*7c478bd9Sstevel@tonic-gate boolean_t blank = 0; 939*7c478bd9Sstevel@tonic-gate size_t newsize; 940*7c478bd9Sstevel@tonic-gate char *newbuf; 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 943*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_next_state, 944*7c478bd9Sstevel@tonic-gate next_state_name, sizeof (next_state_name)); 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate /* Don't print blank fields, to ease parsing. */ 947*7c478bd9Sstevel@tonic-gate if (next_state_name[0] == '\0' || 948*7c478bd9Sstevel@tonic-gate strcmp(next_state_name, SCF_STATE_STRING_NONE) == 0) 949*7c478bd9Sstevel@tonic-gate blank = 1; 950*7c478bd9Sstevel@tonic-gate } else 951*7c478bd9Sstevel@tonic-gate blank = 1; 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (blank) { 954*7c478bd9Sstevel@tonic-gate next_state_name[0] = '-'; 955*7c478bd9Sstevel@tonic-gate next_state_name[1] = '\0'; 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + MAX_SCF_STATE_STRING_SZ + 1; 959*7c478bd9Sstevel@tonic-gate newbuf = safe_malloc(newsize); 960*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 961*7c478bd9Sstevel@tonic-gate MAX_SCF_STATE_STRING_SZ - 1, next_state_name); 962*7c478bd9Sstevel@tonic-gate if (*buf) 963*7c478bd9Sstevel@tonic-gate free(*buf); 964*7c478bd9Sstevel@tonic-gate *buf = newbuf; 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate static void 968*7c478bd9Sstevel@tonic-gate sortkey_nstate(char *buf, int reverse, scf_walkinfo_t *wip) 969*7c478bd9Sstevel@tonic-gate { 970*7c478bd9Sstevel@tonic-gate sortkey_states(scf_property_next_state, buf, reverse, wip); 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate static void 974*7c478bd9Sstevel@tonic-gate sprint_s(char **buf, scf_walkinfo_t *wip) 975*7c478bd9Sstevel@tonic-gate { 976*7c478bd9Sstevel@tonic-gate char tmp[3]; 977*7c478bd9Sstevel@tonic-gate char state_name[MAX_SCF_STATE_STRING_SZ]; 978*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + 4; 979*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 982*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_state, 983*7c478bd9Sstevel@tonic-gate state_name, sizeof (state_name)); 984*7c478bd9Sstevel@tonic-gate tmp[0] = state_to_char(state_name); 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate if (!opt_nstate_shown && transitioning(wip->inst)) 987*7c478bd9Sstevel@tonic-gate tmp[1] = '*'; 988*7c478bd9Sstevel@tonic-gate else 989*7c478bd9Sstevel@tonic-gate tmp[1] = ' '; 990*7c478bd9Sstevel@tonic-gate } else { 991*7c478bd9Sstevel@tonic-gate tmp[0] = 'L'; 992*7c478bd9Sstevel@tonic-gate tmp[1] = ' '; 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate tmp[2] = ' '; 995*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s", *buf ? *buf : "", 996*7c478bd9Sstevel@tonic-gate 3, tmp); 997*7c478bd9Sstevel@tonic-gate if (*buf) 998*7c478bd9Sstevel@tonic-gate free(*buf); 999*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1000*7c478bd9Sstevel@tonic-gate } 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate static void 1003*7c478bd9Sstevel@tonic-gate sprint_n(char **buf, scf_walkinfo_t *wip) 1004*7c478bd9Sstevel@tonic-gate { 1005*7c478bd9Sstevel@tonic-gate char tmp[2]; 1006*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + 3; 1007*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1008*7c478bd9Sstevel@tonic-gate char nstate_name[MAX_SCF_STATE_STRING_SZ]; 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 1011*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_next_state, 1012*7c478bd9Sstevel@tonic-gate nstate_name, sizeof (nstate_name)); 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate if (strcmp(nstate_name, SCF_STATE_STRING_NONE) == 0) 1015*7c478bd9Sstevel@tonic-gate tmp[0] = '-'; 1016*7c478bd9Sstevel@tonic-gate else 1017*7c478bd9Sstevel@tonic-gate tmp[0] = state_to_char(nstate_name); 1018*7c478bd9Sstevel@tonic-gate } else 1019*7c478bd9Sstevel@tonic-gate tmp[0] = '-'; 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1022*7c478bd9Sstevel@tonic-gate 2, tmp); 1023*7c478bd9Sstevel@tonic-gate if (*buf) 1024*7c478bd9Sstevel@tonic-gate free(*buf); 1025*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1026*7c478bd9Sstevel@tonic-gate } 1027*7c478bd9Sstevel@tonic-gate 1028*7c478bd9Sstevel@tonic-gate static void 1029*7c478bd9Sstevel@tonic-gate sprint_sn(char **buf, scf_walkinfo_t *wip) 1030*7c478bd9Sstevel@tonic-gate { 1031*7c478bd9Sstevel@tonic-gate char tmp[3]; 1032*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + 4; 1033*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1034*7c478bd9Sstevel@tonic-gate char nstate_name[MAX_SCF_STATE_STRING_SZ]; 1035*7c478bd9Sstevel@tonic-gate char state_name[MAX_SCF_STATE_STRING_SZ]; 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 1038*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_state, 1039*7c478bd9Sstevel@tonic-gate state_name, sizeof (state_name)); 1040*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_next_state, 1041*7c478bd9Sstevel@tonic-gate nstate_name, sizeof (nstate_name)); 1042*7c478bd9Sstevel@tonic-gate tmp[0] = state_to_char(state_name); 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate if (strcmp(nstate_name, SCF_STATE_STRING_NONE) == 0) 1045*7c478bd9Sstevel@tonic-gate tmp[1] = '-'; 1046*7c478bd9Sstevel@tonic-gate else 1047*7c478bd9Sstevel@tonic-gate tmp[1] = state_to_char(nstate_name); 1048*7c478bd9Sstevel@tonic-gate } else { 1049*7c478bd9Sstevel@tonic-gate tmp[0] = 'L'; 1050*7c478bd9Sstevel@tonic-gate tmp[1] = '-'; 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate tmp[2] = ' '; 1054*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1055*7c478bd9Sstevel@tonic-gate 3, tmp); 1056*7c478bd9Sstevel@tonic-gate if (*buf) 1057*7c478bd9Sstevel@tonic-gate free(*buf); 1058*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1062*7c478bd9Sstevel@tonic-gate static void 1063*7c478bd9Sstevel@tonic-gate sortkey_sn(char *buf, int reverse, scf_walkinfo_t *wip) 1064*7c478bd9Sstevel@tonic-gate { 1065*7c478bd9Sstevel@tonic-gate sortkey_state(buf, reverse, wip); 1066*7c478bd9Sstevel@tonic-gate sortkey_nstate(buf + 1, reverse, wip); 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate static const char * 1070*7c478bd9Sstevel@tonic-gate state_abbrev(const char *state) 1071*7c478bd9Sstevel@tonic-gate { 1072*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0) 1073*7c478bd9Sstevel@tonic-gate return ("UN"); 1074*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0) 1075*7c478bd9Sstevel@tonic-gate return ("OFF"); 1076*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0) 1077*7c478bd9Sstevel@tonic-gate return ("ON"); 1078*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) 1079*7c478bd9Sstevel@tonic-gate return ("MNT"); 1080*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0) 1081*7c478bd9Sstevel@tonic-gate return ("DIS"); 1082*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0) 1083*7c478bd9Sstevel@tonic-gate return ("DGD"); 1084*7c478bd9Sstevel@tonic-gate if (strcmp(state, SCF_STATE_STRING_LEGACY) == 0) 1085*7c478bd9Sstevel@tonic-gate return ("LRC"); 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate return ("?"); 1088*7c478bd9Sstevel@tonic-gate } 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate static void 1091*7c478bd9Sstevel@tonic-gate sprint_sta(char **buf, scf_walkinfo_t *wip) 1092*7c478bd9Sstevel@tonic-gate { 1093*7c478bd9Sstevel@tonic-gate char state_name[MAX_SCF_STATE_STRING_SZ]; 1094*7c478bd9Sstevel@tonic-gate char sta[5]; 1095*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + 6; 1096*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) 1099*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_state, 1100*7c478bd9Sstevel@tonic-gate state_name, sizeof (state_name)); 1101*7c478bd9Sstevel@tonic-gate else 1102*7c478bd9Sstevel@tonic-gate (void) strcpy(state_name, SCF_STATE_STRING_LEGACY); 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate (void) strcpy(sta, state_abbrev(state_name)); 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL && !opt_nstate_shown && transitioning(wip->inst)) 1107*7c478bd9Sstevel@tonic-gate (void) strcat(sta, "*"); 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-4s ", *buf ? *buf : "", sta); 1110*7c478bd9Sstevel@tonic-gate if (*buf) 1111*7c478bd9Sstevel@tonic-gate free(*buf); 1112*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate static void 1116*7c478bd9Sstevel@tonic-gate sprint_nsta(char **buf, scf_walkinfo_t *wip) 1117*7c478bd9Sstevel@tonic-gate { 1118*7c478bd9Sstevel@tonic-gate char state_name[MAX_SCF_STATE_STRING_SZ]; 1119*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + 6; 1120*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) 1123*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(wip->inst, scf_property_next_state, 1124*7c478bd9Sstevel@tonic-gate state_name, sizeof (state_name)); 1125*7c478bd9Sstevel@tonic-gate else 1126*7c478bd9Sstevel@tonic-gate (void) strcpy(state_name, SCF_STATE_STRING_NONE); 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate if (strcmp(state_name, SCF_STATE_STRING_NONE) == 0) 1129*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-4s ", *buf ? *buf : "", 1130*7c478bd9Sstevel@tonic-gate "-"); 1131*7c478bd9Sstevel@tonic-gate else 1132*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-4s ", *buf ? *buf : "", 1133*7c478bd9Sstevel@tonic-gate state_abbrev(state_name)); 1134*7c478bd9Sstevel@tonic-gate if (*buf) 1135*7c478bd9Sstevel@tonic-gate free(*buf); 1136*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1137*7c478bd9Sstevel@tonic-gate } 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate /* FMRI */ 1140*7c478bd9Sstevel@tonic-gate #define FMRI_COLUMN_WIDTH 50 1141*7c478bd9Sstevel@tonic-gate static void 1142*7c478bd9Sstevel@tonic-gate sprint_fmri(char **buf, scf_walkinfo_t *wip) 1143*7c478bd9Sstevel@tonic-gate { 1144*7c478bd9Sstevel@tonic-gate char *fmri_buf = safe_malloc(max_scf_fmri_length + 1); 1145*7c478bd9Sstevel@tonic-gate size_t newsize; 1146*7c478bd9Sstevel@tonic-gate char *newbuf; 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 1149*7c478bd9Sstevel@tonic-gate if (scf_instance_to_fmri(wip->inst, fmri_buf, 1150*7c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1) == -1) 1151*7c478bd9Sstevel@tonic-gate scfdie(); 1152*7c478bd9Sstevel@tonic-gate } else { 1153*7c478bd9Sstevel@tonic-gate (void) strcpy(fmri_buf, LEGACY_SCHEME); 1154*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(wip->pg, SCF_LEGACY_PROPERTY_NAME, 1155*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, fmri_buf + sizeof (LEGACY_SCHEME) - 1, 1156*7c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1 - (sizeof (LEGACY_SCHEME) - 1), 1157*7c478bd9Sstevel@tonic-gate 0) != 0) 1158*7c478bd9Sstevel@tonic-gate (void) strcat(fmri_buf, LEGACY_UNKNOWN); 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate if (strlen(fmri_buf) > FMRI_COLUMN_WIDTH) 1162*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + strlen(fmri_buf) + 2; 1163*7c478bd9Sstevel@tonic-gate else 1164*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + FMRI_COLUMN_WIDTH + 2; 1165*7c478bd9Sstevel@tonic-gate newbuf = safe_malloc(newsize); 1166*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1167*7c478bd9Sstevel@tonic-gate FMRI_COLUMN_WIDTH, fmri_buf); 1168*7c478bd9Sstevel@tonic-gate free(fmri_buf); 1169*7c478bd9Sstevel@tonic-gate if (*buf) 1170*7c478bd9Sstevel@tonic-gate free(*buf); 1171*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate static void 1175*7c478bd9Sstevel@tonic-gate sortkey_fmri(char *buf, int reverse, scf_walkinfo_t *wip) 1176*7c478bd9Sstevel@tonic-gate { 1177*7c478bd9Sstevel@tonic-gate char *tmp = NULL; 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate sprint_fmri(&tmp, wip); 1180*7c478bd9Sstevel@tonic-gate bcopy(tmp, buf, FMRI_COLUMN_WIDTH); 1181*7c478bd9Sstevel@tonic-gate free(tmp); 1182*7c478bd9Sstevel@tonic-gate if (reverse) 1183*7c478bd9Sstevel@tonic-gate reverse_bytes(buf, FMRI_COLUMN_WIDTH); 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate /* Component columns */ 1187*7c478bd9Sstevel@tonic-gate #define COMPONENT_COLUMN_WIDTH 20 1188*7c478bd9Sstevel@tonic-gate static void 1189*7c478bd9Sstevel@tonic-gate sprint_scope(char **buf, scf_walkinfo_t *wip) 1190*7c478bd9Sstevel@tonic-gate { 1191*7c478bd9Sstevel@tonic-gate char *scope_buf = safe_malloc(max_scf_name_length + 1); 1192*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + COMPONENT_COLUMN_WIDTH + 2; 1193*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate assert(wip->scope != NULL); 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate if (scf_scope_get_name(wip->scope, scope_buf, max_scf_name_length) < 0) 1198*7c478bd9Sstevel@tonic-gate scfdie(); 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1201*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH, scope_buf); 1202*7c478bd9Sstevel@tonic-gate if (*buf) 1203*7c478bd9Sstevel@tonic-gate free(*buf); 1204*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1205*7c478bd9Sstevel@tonic-gate free(scope_buf); 1206*7c478bd9Sstevel@tonic-gate } 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate static void 1209*7c478bd9Sstevel@tonic-gate sortkey_scope(char *buf, int reverse, scf_walkinfo_t *wip) 1210*7c478bd9Sstevel@tonic-gate { 1211*7c478bd9Sstevel@tonic-gate char *tmp = NULL; 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate sprint_scope(&tmp, wip); 1214*7c478bd9Sstevel@tonic-gate bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH); 1215*7c478bd9Sstevel@tonic-gate free(tmp); 1216*7c478bd9Sstevel@tonic-gate if (reverse) 1217*7c478bd9Sstevel@tonic-gate reverse_bytes(buf, COMPONENT_COLUMN_WIDTH); 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate static void 1221*7c478bd9Sstevel@tonic-gate sprint_service(char **buf, scf_walkinfo_t *wip) 1222*7c478bd9Sstevel@tonic-gate { 1223*7c478bd9Sstevel@tonic-gate char *svc_buf = safe_malloc(max_scf_name_length + 1); 1224*7c478bd9Sstevel@tonic-gate char *newbuf; 1225*7c478bd9Sstevel@tonic-gate size_t newsize; 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 1228*7c478bd9Sstevel@tonic-gate if (scf_service_get_name(wip->svc, svc_buf, 1229*7c478bd9Sstevel@tonic-gate max_scf_name_length + 1) < 0) 1230*7c478bd9Sstevel@tonic-gate scfdie(); 1231*7c478bd9Sstevel@tonic-gate } else { 1232*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(wip->pg, "name", SCF_TYPE_ASTRING, 1233*7c478bd9Sstevel@tonic-gate svc_buf, max_scf_name_length + 1, EMPTY_OK) != 0) 1234*7c478bd9Sstevel@tonic-gate (void) strcpy(svc_buf, LEGACY_UNKNOWN); 1235*7c478bd9Sstevel@tonic-gate } 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate if (strlen(svc_buf) > COMPONENT_COLUMN_WIDTH) 1239*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + strlen(svc_buf) + 2; 1240*7c478bd9Sstevel@tonic-gate else 1241*7c478bd9Sstevel@tonic-gate newsize = (*buf ? strlen(*buf) : 0) + 1242*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH + 2; 1243*7c478bd9Sstevel@tonic-gate newbuf = safe_malloc(newsize); 1244*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1245*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH, svc_buf); 1246*7c478bd9Sstevel@tonic-gate free(svc_buf); 1247*7c478bd9Sstevel@tonic-gate if (*buf) 1248*7c478bd9Sstevel@tonic-gate free(*buf); 1249*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1250*7c478bd9Sstevel@tonic-gate } 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate static void 1253*7c478bd9Sstevel@tonic-gate sortkey_service(char *buf, int reverse, scf_walkinfo_t *wip) 1254*7c478bd9Sstevel@tonic-gate { 1255*7c478bd9Sstevel@tonic-gate char *tmp = NULL; 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate sprint_service(&tmp, wip); 1258*7c478bd9Sstevel@tonic-gate bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH); 1259*7c478bd9Sstevel@tonic-gate free(tmp); 1260*7c478bd9Sstevel@tonic-gate if (reverse) 1261*7c478bd9Sstevel@tonic-gate reverse_bytes(buf, COMPONENT_COLUMN_WIDTH); 1262*7c478bd9Sstevel@tonic-gate } 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate /* INST */ 1265*7c478bd9Sstevel@tonic-gate static void 1266*7c478bd9Sstevel@tonic-gate sprint_instance(char **buf, scf_walkinfo_t *wip) 1267*7c478bd9Sstevel@tonic-gate { 1268*7c478bd9Sstevel@tonic-gate char *tmp = safe_malloc(max_scf_name_length + 1); 1269*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + COMPONENT_COLUMN_WIDTH + 2; 1270*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 1273*7c478bd9Sstevel@tonic-gate if (scf_instance_get_name(wip->inst, tmp, 1274*7c478bd9Sstevel@tonic-gate max_scf_name_length + 1) < 0) 1275*7c478bd9Sstevel@tonic-gate scfdie(); 1276*7c478bd9Sstevel@tonic-gate } else { 1277*7c478bd9Sstevel@tonic-gate tmp[0] = '-'; 1278*7c478bd9Sstevel@tonic-gate tmp[1] = '\0'; 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1282*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH, tmp); 1283*7c478bd9Sstevel@tonic-gate if (*buf) 1284*7c478bd9Sstevel@tonic-gate free(*buf); 1285*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1286*7c478bd9Sstevel@tonic-gate free(tmp); 1287*7c478bd9Sstevel@tonic-gate } 1288*7c478bd9Sstevel@tonic-gate 1289*7c478bd9Sstevel@tonic-gate static void 1290*7c478bd9Sstevel@tonic-gate sortkey_instance(char *buf, int reverse, scf_walkinfo_t *wip) 1291*7c478bd9Sstevel@tonic-gate { 1292*7c478bd9Sstevel@tonic-gate char *tmp = NULL; 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate sprint_instance(&tmp, wip); 1295*7c478bd9Sstevel@tonic-gate bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH); 1296*7c478bd9Sstevel@tonic-gate free(tmp); 1297*7c478bd9Sstevel@tonic-gate if (reverse) 1298*7c478bd9Sstevel@tonic-gate reverse_bytes(buf, COMPONENT_COLUMN_WIDTH); 1299*7c478bd9Sstevel@tonic-gate } 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate /* STIME */ 1302*7c478bd9Sstevel@tonic-gate #define STIME_COLUMN_WIDTH 8 1303*7c478bd9Sstevel@tonic-gate #define FORMAT_TIME "%k:%M:%S" 1304*7c478bd9Sstevel@tonic-gate #define FORMAT_DATE "%b_%d " 1305*7c478bd9Sstevel@tonic-gate #define FORMAT_YEAR "%Y " 1306*7c478bd9Sstevel@tonic-gate 1307*7c478bd9Sstevel@tonic-gate static void 1308*7c478bd9Sstevel@tonic-gate sprint_stime(char **buf, scf_walkinfo_t *wip) 1309*7c478bd9Sstevel@tonic-gate { 1310*7c478bd9Sstevel@tonic-gate int r; 1311*7c478bd9Sstevel@tonic-gate struct timeval tv; 1312*7c478bd9Sstevel@tonic-gate time_t then; 1313*7c478bd9Sstevel@tonic-gate struct tm *tm; 1314*7c478bd9Sstevel@tonic-gate char st_buf[STIME_COLUMN_WIDTH + 1]; 1315*7c478bd9Sstevel@tonic-gate size_t newsize = (*buf ? strlen(*buf) : 0) + STIME_COLUMN_WIDTH + 2; 1316*7c478bd9Sstevel@tonic-gate char *newbuf = safe_malloc(newsize); 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) { 1319*7c478bd9Sstevel@tonic-gate r = get_restarter_time_prop(wip->inst, 1320*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0); 1321*7c478bd9Sstevel@tonic-gate } else { 1322*7c478bd9Sstevel@tonic-gate r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP, 1323*7c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, &tv, NULL, 0); 1324*7c478bd9Sstevel@tonic-gate } 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate if (r != 0) { 1327*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s", *buf ? *buf : "", 1328*7c478bd9Sstevel@tonic-gate STIME_COLUMN_WIDTH + 1, "?"); 1329*7c478bd9Sstevel@tonic-gate return; 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate then = (time_t)tv.tv_sec; 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate tm = localtime(&then); 1335*7c478bd9Sstevel@tonic-gate /* 1336*7c478bd9Sstevel@tonic-gate * Print time if started within the past 24 hours, print date 1337*7c478bd9Sstevel@tonic-gate * if within the past 12 months, print year if started greater than 1338*7c478bd9Sstevel@tonic-gate * 12 months ago. 1339*7c478bd9Sstevel@tonic-gate */ 1340*7c478bd9Sstevel@tonic-gate if (now - then < 24 * 60 * 60) 1341*7c478bd9Sstevel@tonic-gate (void) strftime(st_buf, sizeof (st_buf), gettext(FORMAT_TIME), 1342*7c478bd9Sstevel@tonic-gate tm); 1343*7c478bd9Sstevel@tonic-gate else if (now - then < 12 * 30 * 24 * 60 * 60) 1344*7c478bd9Sstevel@tonic-gate (void) strftime(st_buf, sizeof (st_buf), gettext(FORMAT_DATE), 1345*7c478bd9Sstevel@tonic-gate tm); 1346*7c478bd9Sstevel@tonic-gate else 1347*7c478bd9Sstevel@tonic-gate (void) strftime(st_buf, sizeof (st_buf), gettext(FORMAT_YEAR), 1348*7c478bd9Sstevel@tonic-gate tm); 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "", 1351*7c478bd9Sstevel@tonic-gate STIME_COLUMN_WIDTH + 1, st_buf); 1352*7c478bd9Sstevel@tonic-gate if (*buf) 1353*7c478bd9Sstevel@tonic-gate free(*buf); 1354*7c478bd9Sstevel@tonic-gate *buf = newbuf; 1355*7c478bd9Sstevel@tonic-gate } 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate #define STIME_SORTKEY_WIDTH (sizeof (uint64_t) + sizeof (uint32_t)) 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1360*7c478bd9Sstevel@tonic-gate static void 1361*7c478bd9Sstevel@tonic-gate sortkey_stime(char *buf, int reverse, scf_walkinfo_t *wip) 1362*7c478bd9Sstevel@tonic-gate { 1363*7c478bd9Sstevel@tonic-gate struct timeval tv; 1364*7c478bd9Sstevel@tonic-gate int r; 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL) 1367*7c478bd9Sstevel@tonic-gate r = get_restarter_time_prop(wip->inst, 1368*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0); 1369*7c478bd9Sstevel@tonic-gate else 1370*7c478bd9Sstevel@tonic-gate r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP, 1371*7c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, &tv, NULL, 0); 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate if (r == 0) { 1374*7c478bd9Sstevel@tonic-gate int64_t sec; 1375*7c478bd9Sstevel@tonic-gate int32_t us; 1376*7c478bd9Sstevel@tonic-gate 1377*7c478bd9Sstevel@tonic-gate /* Stick it straight into the buffer. */ 1378*7c478bd9Sstevel@tonic-gate sec = tv.tv_sec; 1379*7c478bd9Sstevel@tonic-gate us = tv.tv_usec; 1380*7c478bd9Sstevel@tonic-gate 1381*7c478bd9Sstevel@tonic-gate sec = BE_64(sec); 1382*7c478bd9Sstevel@tonic-gate us = BE_32(us); 1383*7c478bd9Sstevel@tonic-gate bcopy(&sec, buf, sizeof (sec)); 1384*7c478bd9Sstevel@tonic-gate bcopy(&us, buf + sizeof (sec), sizeof (us)); 1385*7c478bd9Sstevel@tonic-gate } else { 1386*7c478bd9Sstevel@tonic-gate bzero(buf, STIME_SORTKEY_WIDTH); 1387*7c478bd9Sstevel@tonic-gate } 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate if (reverse) 1390*7c478bd9Sstevel@tonic-gate reverse_bytes(buf, STIME_SORTKEY_WIDTH); 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate /* 1395*7c478bd9Sstevel@tonic-gate * Information about columns which can be displayed. If you add something, 1396*7c478bd9Sstevel@tonic-gate * check MAX_COLUMN_NAME_LENGTH_STR & update description_of_column() below. 1397*7c478bd9Sstevel@tonic-gate */ 1398*7c478bd9Sstevel@tonic-gate static const struct column columns[] = { 1399*7c478bd9Sstevel@tonic-gate { "CTID", CTID_COLUMN_WIDTH, sprint_ctid, 1400*7c478bd9Sstevel@tonic-gate CTID_SORTKEY_WIDTH, sortkey_ctid }, 1401*7c478bd9Sstevel@tonic-gate { "DESC", DESC_COLUMN_WIDTH, sprint_desc, 1402*7c478bd9Sstevel@tonic-gate DESC_COLUMN_WIDTH, sortkey_desc }, 1403*7c478bd9Sstevel@tonic-gate { "FMRI", FMRI_COLUMN_WIDTH, sprint_fmri, 1404*7c478bd9Sstevel@tonic-gate FMRI_COLUMN_WIDTH, sortkey_fmri }, 1405*7c478bd9Sstevel@tonic-gate { "INST", COMPONENT_COLUMN_WIDTH, sprint_instance, 1406*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH, sortkey_instance }, 1407*7c478bd9Sstevel@tonic-gate { "N", 1, sprint_n, 1, sortkey_nstate }, 1408*7c478bd9Sstevel@tonic-gate { "NSTA", 4, sprint_nsta, 1, sortkey_nstate }, 1409*7c478bd9Sstevel@tonic-gate { "NSTATE", MAX_SCF_STATE_STRING_SZ - 1, sprint_nstate, 1410*7c478bd9Sstevel@tonic-gate 1, sortkey_nstate }, 1411*7c478bd9Sstevel@tonic-gate { "S", 2, sprint_s, 1, sortkey_state }, 1412*7c478bd9Sstevel@tonic-gate { "SCOPE", COMPONENT_COLUMN_WIDTH, sprint_scope, 1413*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH, sortkey_scope }, 1414*7c478bd9Sstevel@tonic-gate { "SN", 2, sprint_sn, 2, sortkey_sn }, 1415*7c478bd9Sstevel@tonic-gate { "SVC", COMPONENT_COLUMN_WIDTH, sprint_service, 1416*7c478bd9Sstevel@tonic-gate COMPONENT_COLUMN_WIDTH, sortkey_service }, 1417*7c478bd9Sstevel@tonic-gate { "STA", 4, sprint_sta, 1, sortkey_state }, 1418*7c478bd9Sstevel@tonic-gate { "STATE", MAX_SCF_STATE_STRING_SZ - 1 + 1, sprint_state, 1419*7c478bd9Sstevel@tonic-gate 1, sortkey_state }, 1420*7c478bd9Sstevel@tonic-gate { "STIME", STIME_COLUMN_WIDTH, sprint_stime, 1421*7c478bd9Sstevel@tonic-gate STIME_SORTKEY_WIDTH, sortkey_stime }, 1422*7c478bd9Sstevel@tonic-gate }; 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate #define MAX_COLUMN_NAME_LENGTH_STR "6" 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate static const int ncolumns = sizeof (columns) / sizeof (columns[0]); 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate /* 1429*7c478bd9Sstevel@tonic-gate * Necessary thanks to gettext() & xgettext. 1430*7c478bd9Sstevel@tonic-gate */ 1431*7c478bd9Sstevel@tonic-gate static const char * 1432*7c478bd9Sstevel@tonic-gate description_of_column(int c) 1433*7c478bd9Sstevel@tonic-gate { 1434*7c478bd9Sstevel@tonic-gate const char *s = NULL; 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate switch (c) { 1437*7c478bd9Sstevel@tonic-gate case 0: 1438*7c478bd9Sstevel@tonic-gate s = gettext("contract ID for service (see contract(4))"); 1439*7c478bd9Sstevel@tonic-gate break; 1440*7c478bd9Sstevel@tonic-gate case 1: 1441*7c478bd9Sstevel@tonic-gate s = gettext("human-readable description of the service"); 1442*7c478bd9Sstevel@tonic-gate break; 1443*7c478bd9Sstevel@tonic-gate case 2: 1444*7c478bd9Sstevel@tonic-gate s = gettext("Fault Managed Resource Identifier for service"); 1445*7c478bd9Sstevel@tonic-gate break; 1446*7c478bd9Sstevel@tonic-gate case 3: 1447*7c478bd9Sstevel@tonic-gate s = gettext("portion of the FMRI indicating service instance"); 1448*7c478bd9Sstevel@tonic-gate break; 1449*7c478bd9Sstevel@tonic-gate case 4: 1450*7c478bd9Sstevel@tonic-gate s = gettext("abbreviation for next state (if in transition)"); 1451*7c478bd9Sstevel@tonic-gate break; 1452*7c478bd9Sstevel@tonic-gate case 5: 1453*7c478bd9Sstevel@tonic-gate s = gettext("abbreviation for next state (if in transition)"); 1454*7c478bd9Sstevel@tonic-gate break; 1455*7c478bd9Sstevel@tonic-gate case 6: 1456*7c478bd9Sstevel@tonic-gate s = gettext("name for next state (if in transition)"); 1457*7c478bd9Sstevel@tonic-gate break; 1458*7c478bd9Sstevel@tonic-gate case 7: 1459*7c478bd9Sstevel@tonic-gate s = gettext("abbreviation for current state"); 1460*7c478bd9Sstevel@tonic-gate break; 1461*7c478bd9Sstevel@tonic-gate case 8: 1462*7c478bd9Sstevel@tonic-gate s = gettext("name for scope associated with service"); 1463*7c478bd9Sstevel@tonic-gate break; 1464*7c478bd9Sstevel@tonic-gate case 9: 1465*7c478bd9Sstevel@tonic-gate s = gettext("abbreviation for current state and next state"); 1466*7c478bd9Sstevel@tonic-gate break; 1467*7c478bd9Sstevel@tonic-gate case 10: 1468*7c478bd9Sstevel@tonic-gate s = gettext("portion of the FMRI representing service name"); 1469*7c478bd9Sstevel@tonic-gate break; 1470*7c478bd9Sstevel@tonic-gate case 11: 1471*7c478bd9Sstevel@tonic-gate s = gettext("abbreviation for current state"); 1472*7c478bd9Sstevel@tonic-gate break; 1473*7c478bd9Sstevel@tonic-gate case 12: 1474*7c478bd9Sstevel@tonic-gate s = gettext("name for current state"); 1475*7c478bd9Sstevel@tonic-gate break; 1476*7c478bd9Sstevel@tonic-gate case 13: 1477*7c478bd9Sstevel@tonic-gate s = gettext("time of last state change"); 1478*7c478bd9Sstevel@tonic-gate break; 1479*7c478bd9Sstevel@tonic-gate } 1480*7c478bd9Sstevel@tonic-gate 1481*7c478bd9Sstevel@tonic-gate assert(s != NULL); 1482*7c478bd9Sstevel@tonic-gate return (s); 1483*7c478bd9Sstevel@tonic-gate } 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate 1486*7c478bd9Sstevel@tonic-gate static void 1487*7c478bd9Sstevel@tonic-gate print_usage(const char *progname, FILE *f, boolean_t do_exit) 1488*7c478bd9Sstevel@tonic-gate { 1489*7c478bd9Sstevel@tonic-gate (void) fprintf(f, gettext( 1490*7c478bd9Sstevel@tonic-gate "Usage: %1$s [-aHpv] [-o col[,col ... ]] [-R restarter] " 1491*7c478bd9Sstevel@tonic-gate "[-sS col] [<service> ...]\n" 1492*7c478bd9Sstevel@tonic-gate " %1$s -d | -D [-Hpv] [-o col[,col ... ]] [-sS col] " 1493*7c478bd9Sstevel@tonic-gate "[<service> ...]\n" 1494*7c478bd9Sstevel@tonic-gate " %1$s -l <service> ...\n" 1495*7c478bd9Sstevel@tonic-gate " %1$s -x [-v] [<service> ...]\n" 1496*7c478bd9Sstevel@tonic-gate " %1$s -?\n"), progname); 1497*7c478bd9Sstevel@tonic-gate 1498*7c478bd9Sstevel@tonic-gate if (do_exit) 1499*7c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE); 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate 1502*7c478bd9Sstevel@tonic-gate #define argserr(progname) print_usage(progname, stderr, B_TRUE) 1503*7c478bd9Sstevel@tonic-gate 1504*7c478bd9Sstevel@tonic-gate static void 1505*7c478bd9Sstevel@tonic-gate print_help(const char *progname) 1506*7c478bd9Sstevel@tonic-gate { 1507*7c478bd9Sstevel@tonic-gate int i; 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate print_usage(progname, stdout, B_FALSE); 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\n" 1512*7c478bd9Sstevel@tonic-gate "\t-a list all service instances rather than " 1513*7c478bd9Sstevel@tonic-gate "only those that are enabled\n" 1514*7c478bd9Sstevel@tonic-gate "\t-d list dependencies of the specified service(s)\n" 1515*7c478bd9Sstevel@tonic-gate "\t-D list dependents of the specified service(s)\n" 1516*7c478bd9Sstevel@tonic-gate "\t-H omit header line from output\n" 1517*7c478bd9Sstevel@tonic-gate "\t-l list detailed information about the specified service(s)\n" 1518*7c478bd9Sstevel@tonic-gate "\t-o list only the specified columns in the output\n" 1519*7c478bd9Sstevel@tonic-gate "\t-p list process IDs and names associated with each service\n" 1520*7c478bd9Sstevel@tonic-gate "\t-R list only those services with the specified restarter\n" 1521*7c478bd9Sstevel@tonic-gate "\t-s sort output in ascending order by the specified column(s)\n" 1522*7c478bd9Sstevel@tonic-gate "\t-S sort output in descending order by the specified column(s)\n" 1523*7c478bd9Sstevel@tonic-gate "\t-v list verbose information appropriate to the type of output\n" 1524*7c478bd9Sstevel@tonic-gate "\t-x explain the status of services that might require maintenance,\n" 1525*7c478bd9Sstevel@tonic-gate "\t or explain the status of the specified service(s)\n" 1526*7c478bd9Sstevel@tonic-gate "\n\t" 1527*7c478bd9Sstevel@tonic-gate "Services can be specified using an FMRI, abbreviation, or fnmatch(5)\n" 1528*7c478bd9Sstevel@tonic-gate "\tpattern, as shown in these examples for svc:/network/smtp:sendmail\n" 1529*7c478bd9Sstevel@tonic-gate "\n" 1530*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] svc:/network/smtp:sendmail\n" 1531*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] network/smtp:sendmail\n" 1532*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] network/*mail\n" 1533*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] network/smtp\n" 1534*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] smtp:sendmail\n" 1535*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] smtp\n" 1536*7c478bd9Sstevel@tonic-gate "\t%1$s [opts] sendmail\n" 1537*7c478bd9Sstevel@tonic-gate "\n\t" 1538*7c478bd9Sstevel@tonic-gate "Columns for output or sorting can be specified using these names:\n" 1539*7c478bd9Sstevel@tonic-gate "\n"), progname); 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate for (i = 0; i < ncolumns; i++) { 1542*7c478bd9Sstevel@tonic-gate (void) printf("\t%-" MAX_COLUMN_NAME_LENGTH_STR "s %s\n", 1543*7c478bd9Sstevel@tonic-gate columns[i].name, description_of_column(i)); 1544*7c478bd9Sstevel@tonic-gate } 1545*7c478bd9Sstevel@tonic-gate } 1546*7c478bd9Sstevel@tonic-gate 1547*7c478bd9Sstevel@tonic-gate 1548*7c478bd9Sstevel@tonic-gate /* 1549*7c478bd9Sstevel@tonic-gate * A getsubopt()-like function which returns an index into the columns table. 1550*7c478bd9Sstevel@tonic-gate * On success, *optionp is set to point to the next sub-option, or the 1551*7c478bd9Sstevel@tonic-gate * terminating null if there are none. 1552*7c478bd9Sstevel@tonic-gate */ 1553*7c478bd9Sstevel@tonic-gate static int 1554*7c478bd9Sstevel@tonic-gate getcolumnopt(char **optionp) 1555*7c478bd9Sstevel@tonic-gate { 1556*7c478bd9Sstevel@tonic-gate char *str = *optionp, *cp; 1557*7c478bd9Sstevel@tonic-gate int i; 1558*7c478bd9Sstevel@tonic-gate 1559*7c478bd9Sstevel@tonic-gate assert(optionp != NULL); 1560*7c478bd9Sstevel@tonic-gate assert(*optionp != NULL); 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate cp = strchr(*optionp, ','); 1563*7c478bd9Sstevel@tonic-gate if (cp != NULL) 1564*7c478bd9Sstevel@tonic-gate *cp = '\0'; 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate for (i = 0; i < ncolumns; ++i) { 1567*7c478bd9Sstevel@tonic-gate if (strcasecmp(str, columns[i].name) == 0) { 1568*7c478bd9Sstevel@tonic-gate if (cp != NULL) 1569*7c478bd9Sstevel@tonic-gate *optionp = cp + 1; 1570*7c478bd9Sstevel@tonic-gate else 1571*7c478bd9Sstevel@tonic-gate *optionp = strchr(*optionp, '\0'); 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate return (i); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate } 1576*7c478bd9Sstevel@tonic-gate 1577*7c478bd9Sstevel@tonic-gate return (-1); 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate static void 1581*7c478bd9Sstevel@tonic-gate print_header() 1582*7c478bd9Sstevel@tonic-gate { 1583*7c478bd9Sstevel@tonic-gate int i; 1584*7c478bd9Sstevel@tonic-gate char *line_buf, *cp; 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate line_buf = safe_malloc(line_sz); 1587*7c478bd9Sstevel@tonic-gate cp = line_buf; 1588*7c478bd9Sstevel@tonic-gate for (i = 0; i < opt_cnum; ++i) { 1589*7c478bd9Sstevel@tonic-gate const struct column * const colp = &columns[opt_columns[i]]; 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate (void) snprintf(cp, colp->width + 1, "%-*s", colp->width, 1592*7c478bd9Sstevel@tonic-gate colp->name); 1593*7c478bd9Sstevel@tonic-gate cp += colp->width; 1594*7c478bd9Sstevel@tonic-gate *cp++ = ' '; 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate 1597*7c478bd9Sstevel@tonic-gate /* Trim the trailing whitespace */ 1598*7c478bd9Sstevel@tonic-gate --cp; 1599*7c478bd9Sstevel@tonic-gate while (*cp == ' ') 1600*7c478bd9Sstevel@tonic-gate --cp; 1601*7c478bd9Sstevel@tonic-gate *(cp+1) = '\0'; 1602*7c478bd9Sstevel@tonic-gate (void) puts(line_buf); 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate free(line_buf); 1605*7c478bd9Sstevel@tonic-gate } 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate /* 1610*7c478bd9Sstevel@tonic-gate * Long listing (-l) functions. 1611*7c478bd9Sstevel@tonic-gate */ 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate static int 1614*7c478bd9Sstevel@tonic-gate pidcmp(const void *l, const void *r) 1615*7c478bd9Sstevel@tonic-gate { 1616*7c478bd9Sstevel@tonic-gate pid_t lp = *(pid_t *)l, rp = *(pid_t *)r; 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate if (lp < rp) 1619*7c478bd9Sstevel@tonic-gate return (-1); 1620*7c478bd9Sstevel@tonic-gate if (lp > rp) 1621*7c478bd9Sstevel@tonic-gate return (1); 1622*7c478bd9Sstevel@tonic-gate return (0); 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate /* 1626*7c478bd9Sstevel@tonic-gate * This is the strlen() of the longest label ("description"), plus intercolumn 1627*7c478bd9Sstevel@tonic-gate * space. 1628*7c478bd9Sstevel@tonic-gate */ 1629*7c478bd9Sstevel@tonic-gate #define DETAILED_WIDTH (11 + 2) 1630*7c478bd9Sstevel@tonic-gate 1631*7c478bd9Sstevel@tonic-gate static void 1632*7c478bd9Sstevel@tonic-gate detailed_list_processes(scf_instance_t *inst) 1633*7c478bd9Sstevel@tonic-gate { 1634*7c478bd9Sstevel@tonic-gate uint64_t c; 1635*7c478bd9Sstevel@tonic-gate pid_t *pids; 1636*7c478bd9Sstevel@tonic-gate uint_t i, n; 1637*7c478bd9Sstevel@tonic-gate psinfo_t psi; 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate if (get_restarter_count_prop(inst, scf_property_contract, &c, 1640*7c478bd9Sstevel@tonic-gate EMPTY_OK) != 0) 1641*7c478bd9Sstevel@tonic-gate return; 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate if (instance_processes(inst, &pids, &n) != 0) 1644*7c478bd9Sstevel@tonic-gate return; 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate qsort(pids, n, sizeof (*pids), pidcmp); 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; ++i) { 1649*7c478bd9Sstevel@tonic-gate (void) printf("%-*s%lu", DETAILED_WIDTH, gettext("process"), 1650*7c478bd9Sstevel@tonic-gate pids[i]); 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate if (get_psinfo(pids[i], &psi) == 0) 1653*7c478bd9Sstevel@tonic-gate (void) printf(" %.*s", PRARGSZ, psi.pr_psargs); 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1656*7c478bd9Sstevel@tonic-gate } 1657*7c478bd9Sstevel@tonic-gate 1658*7c478bd9Sstevel@tonic-gate free(pids); 1659*7c478bd9Sstevel@tonic-gate } 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate /* 1662*7c478bd9Sstevel@tonic-gate * Determines the state of a dependency. If the FMRI specifies a file, then we 1663*7c478bd9Sstevel@tonic-gate * fake up a state based on whether we can access the file. 1664*7c478bd9Sstevel@tonic-gate */ 1665*7c478bd9Sstevel@tonic-gate static void 1666*7c478bd9Sstevel@tonic-gate get_fmri_state(char *fmri, char *state, size_t state_sz) 1667*7c478bd9Sstevel@tonic-gate { 1668*7c478bd9Sstevel@tonic-gate char *lfmri; 1669*7c478bd9Sstevel@tonic-gate const char *svc_name, *inst_name, *pg_name, *path; 1670*7c478bd9Sstevel@tonic-gate scf_service_t *svc; 1671*7c478bd9Sstevel@tonic-gate scf_instance_t *inst; 1672*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate lfmri = safe_strdup(fmri); 1675*7c478bd9Sstevel@tonic-gate 1676*7c478bd9Sstevel@tonic-gate /* 1677*7c478bd9Sstevel@tonic-gate * Check for file:// dependencies 1678*7c478bd9Sstevel@tonic-gate */ 1679*7c478bd9Sstevel@tonic-gate if (scf_parse_file_fmri(lfmri, NULL, &path) == SCF_SUCCESS) { 1680*7c478bd9Sstevel@tonic-gate struct stat64 statbuf; 1681*7c478bd9Sstevel@tonic-gate const char *msg; 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate if (stat64(path, &statbuf) == 0) 1684*7c478bd9Sstevel@tonic-gate msg = "online"; 1685*7c478bd9Sstevel@tonic-gate else if (errno == ENOENT) 1686*7c478bd9Sstevel@tonic-gate msg = "absent"; 1687*7c478bd9Sstevel@tonic-gate else 1688*7c478bd9Sstevel@tonic-gate msg = "unknown"; 1689*7c478bd9Sstevel@tonic-gate 1690*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, msg, state_sz); 1691*7c478bd9Sstevel@tonic-gate return; 1692*7c478bd9Sstevel@tonic-gate } 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate /* 1695*7c478bd9Sstevel@tonic-gate * scf_parse_file_fmri() may have overwritten part of the string, so 1696*7c478bd9Sstevel@tonic-gate * copy it back. 1697*7c478bd9Sstevel@tonic-gate */ 1698*7c478bd9Sstevel@tonic-gate (void) strcpy(lfmri, fmri); 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(lfmri, NULL, &svc_name, &inst_name, 1701*7c478bd9Sstevel@tonic-gate &pg_name, NULL) != SCF_SUCCESS) { 1702*7c478bd9Sstevel@tonic-gate free(lfmri); 1703*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "invalid", state_sz); 1704*7c478bd9Sstevel@tonic-gate return; 1705*7c478bd9Sstevel@tonic-gate } 1706*7c478bd9Sstevel@tonic-gate 1707*7c478bd9Sstevel@tonic-gate free(lfmri); 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate if (svc_name == NULL || pg_name != NULL) { 1710*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "invalid", state_sz); 1711*7c478bd9Sstevel@tonic-gate return; 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate 1714*7c478bd9Sstevel@tonic-gate if (inst_name != NULL) { 1715*7c478bd9Sstevel@tonic-gate /* instance: get state */ 1716*7c478bd9Sstevel@tonic-gate inst = scf_instance_create(h); 1717*7c478bd9Sstevel@tonic-gate if (inst == NULL) 1718*7c478bd9Sstevel@tonic-gate scfdie(); 1719*7c478bd9Sstevel@tonic-gate 1720*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst, NULL, 1721*7c478bd9Sstevel@tonic-gate NULL, SCF_DECODE_FMRI_EXACT) == SCF_SUCCESS) 1722*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(inst, scf_property_state, 1723*7c478bd9Sstevel@tonic-gate state, state_sz); 1724*7c478bd9Sstevel@tonic-gate else { 1725*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1726*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1727*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "invalid", state_sz); 1728*7c478bd9Sstevel@tonic-gate break; 1729*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1730*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "absent", state_sz); 1731*7c478bd9Sstevel@tonic-gate break; 1732*7c478bd9Sstevel@tonic-gate 1733*7c478bd9Sstevel@tonic-gate default: 1734*7c478bd9Sstevel@tonic-gate scfdie(); 1735*7c478bd9Sstevel@tonic-gate } 1736*7c478bd9Sstevel@tonic-gate } 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 1739*7c478bd9Sstevel@tonic-gate return; 1740*7c478bd9Sstevel@tonic-gate } 1741*7c478bd9Sstevel@tonic-gate 1742*7c478bd9Sstevel@tonic-gate /* 1743*7c478bd9Sstevel@tonic-gate * service: If only one instance, use that state. Otherwise, say 1744*7c478bd9Sstevel@tonic-gate * "multiple". 1745*7c478bd9Sstevel@tonic-gate */ 1746*7c478bd9Sstevel@tonic-gate if ((svc = scf_service_create(h)) == NULL || 1747*7c478bd9Sstevel@tonic-gate (inst = scf_instance_create(h)) == NULL || 1748*7c478bd9Sstevel@tonic-gate (iter = scf_iter_create(h)) == NULL) 1749*7c478bd9Sstevel@tonic-gate scfdie(); 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, fmri, NULL, svc, NULL, NULL, NULL, 1752*7c478bd9Sstevel@tonic-gate SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) { 1753*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1754*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1755*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "invalid", state_sz); 1756*7c478bd9Sstevel@tonic-gate goto out; 1757*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1758*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "absent", state_sz); 1759*7c478bd9Sstevel@tonic-gate goto out; 1760*7c478bd9Sstevel@tonic-gate 1761*7c478bd9Sstevel@tonic-gate default: 1762*7c478bd9Sstevel@tonic-gate scfdie(); 1763*7c478bd9Sstevel@tonic-gate } 1764*7c478bd9Sstevel@tonic-gate } 1765*7c478bd9Sstevel@tonic-gate 1766*7c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iter, svc) != SCF_SUCCESS) 1767*7c478bd9Sstevel@tonic-gate scfdie(); 1768*7c478bd9Sstevel@tonic-gate 1769*7c478bd9Sstevel@tonic-gate switch (scf_iter_next_instance(iter, inst)) { 1770*7c478bd9Sstevel@tonic-gate case 0: 1771*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "absent", state_sz); 1772*7c478bd9Sstevel@tonic-gate goto out; 1773*7c478bd9Sstevel@tonic-gate 1774*7c478bd9Sstevel@tonic-gate case 1: 1775*7c478bd9Sstevel@tonic-gate break; 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate default: 1778*7c478bd9Sstevel@tonic-gate scfdie(); 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate /* Get the state in case this is the only instance. */ 1782*7c478bd9Sstevel@tonic-gate get_restarter_string_prop(inst, scf_property_state, state, state_sz); 1783*7c478bd9Sstevel@tonic-gate 1784*7c478bd9Sstevel@tonic-gate switch (scf_iter_next_instance(iter, inst)) { 1785*7c478bd9Sstevel@tonic-gate case 0: 1786*7c478bd9Sstevel@tonic-gate break; 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate case 1: 1789*7c478bd9Sstevel@tonic-gate /* Nope, multiple instances. */ 1790*7c478bd9Sstevel@tonic-gate (void) strlcpy(state, "multiple", state_sz); 1791*7c478bd9Sstevel@tonic-gate goto out; 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate default: 1794*7c478bd9Sstevel@tonic-gate scfdie(); 1795*7c478bd9Sstevel@tonic-gate } 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate out: 1798*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 1799*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 1800*7c478bd9Sstevel@tonic-gate scf_service_destroy(svc); 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate 1803*7c478bd9Sstevel@tonic-gate static void 1804*7c478bd9Sstevel@tonic-gate print_detailed_dependency(scf_propertygroup_t *pg) 1805*7c478bd9Sstevel@tonic-gate { 1806*7c478bd9Sstevel@tonic-gate scf_property_t *eprop; 1807*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 1808*7c478bd9Sstevel@tonic-gate scf_type_t ty; 1809*7c478bd9Sstevel@tonic-gate char *val_buf; 1810*7c478bd9Sstevel@tonic-gate int i; 1811*7c478bd9Sstevel@tonic-gate 1812*7c478bd9Sstevel@tonic-gate if ((eprop = scf_property_create(h)) == NULL || 1813*7c478bd9Sstevel@tonic-gate (iter = scf_iter_create(h)) == NULL) 1814*7c478bd9Sstevel@tonic-gate scfdie(); 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate val_buf = safe_malloc(max_scf_value_length + 1); 1817*7c478bd9Sstevel@tonic-gate 1818*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, eprop) != 1819*7c478bd9Sstevel@tonic-gate SCF_SUCCESS || 1820*7c478bd9Sstevel@tonic-gate scf_property_type(eprop, &ty) != SCF_SUCCESS || 1821*7c478bd9Sstevel@tonic-gate ty != SCF_TYPE_FMRI) 1822*7c478bd9Sstevel@tonic-gate return; 1823*7c478bd9Sstevel@tonic-gate 1824*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", DETAILED_WIDTH, gettext("dependency")); 1825*7c478bd9Sstevel@tonic-gate 1826*7c478bd9Sstevel@tonic-gate /* Print the grouping */ 1827*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(pg, SCF_PROPERTY_GROUPING, SCF_TYPE_ASTRING, 1828*7c478bd9Sstevel@tonic-gate val_buf, max_scf_value_length + 1, 0) == 0) 1829*7c478bd9Sstevel@tonic-gate (void) fputs(val_buf, stdout); 1830*7c478bd9Sstevel@tonic-gate else 1831*7c478bd9Sstevel@tonic-gate (void) putchar('?'); 1832*7c478bd9Sstevel@tonic-gate 1833*7c478bd9Sstevel@tonic-gate (void) putchar('/'); 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(pg, SCF_PROPERTY_RESTART_ON, SCF_TYPE_ASTRING, 1836*7c478bd9Sstevel@tonic-gate val_buf, max_scf_value_length + 1, 0) == 0) 1837*7c478bd9Sstevel@tonic-gate (void) fputs(val_buf, stdout); 1838*7c478bd9Sstevel@tonic-gate else 1839*7c478bd9Sstevel@tonic-gate (void) putchar('?'); 1840*7c478bd9Sstevel@tonic-gate 1841*7c478bd9Sstevel@tonic-gate /* Print the dependency entities. */ 1842*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, eprop) == -1) 1843*7c478bd9Sstevel@tonic-gate scfdie(); 1844*7c478bd9Sstevel@tonic-gate 1845*7c478bd9Sstevel@tonic-gate while ((i = scf_iter_next_value(iter, g_val)) == 1) { 1846*7c478bd9Sstevel@tonic-gate char state[MAX_SCF_STATE_STRING_SZ]; 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, val_buf, 1849*7c478bd9Sstevel@tonic-gate max_scf_value_length + 1) < 0) 1850*7c478bd9Sstevel@tonic-gate scfdie(); 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate (void) putchar(' '); 1853*7c478bd9Sstevel@tonic-gate (void) fputs(val_buf, stdout); 1854*7c478bd9Sstevel@tonic-gate 1855*7c478bd9Sstevel@tonic-gate /* Print the state. */ 1856*7c478bd9Sstevel@tonic-gate state[0] = '-'; 1857*7c478bd9Sstevel@tonic-gate state[1] = '\0'; 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate get_fmri_state(val_buf, state, sizeof (state)); 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate (void) printf(" (%s)", state); 1862*7c478bd9Sstevel@tonic-gate } 1863*7c478bd9Sstevel@tonic-gate if (i == -1) 1864*7c478bd9Sstevel@tonic-gate scfdie(); 1865*7c478bd9Sstevel@tonic-gate 1866*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate free(val_buf); 1869*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 1870*7c478bd9Sstevel@tonic-gate scf_property_destroy(eprop); 1871*7c478bd9Sstevel@tonic-gate } 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1874*7c478bd9Sstevel@tonic-gate static int 1875*7c478bd9Sstevel@tonic-gate print_detailed(void *unused, scf_walkinfo_t *wip) 1876*7c478bd9Sstevel@tonic-gate { 1877*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 1878*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *rpg; 1879*7c478bd9Sstevel@tonic-gate scf_iter_t *pg_iter; 1880*7c478bd9Sstevel@tonic-gate 1881*7c478bd9Sstevel@tonic-gate char *buf; 1882*7c478bd9Sstevel@tonic-gate char *timebuf; 1883*7c478bd9Sstevel@tonic-gate size_t tbsz; 1884*7c478bd9Sstevel@tonic-gate int ret; 1885*7c478bd9Sstevel@tonic-gate uint64_t c; 1886*7c478bd9Sstevel@tonic-gate int temp, perm; 1887*7c478bd9Sstevel@tonic-gate struct timeval tv; 1888*7c478bd9Sstevel@tonic-gate time_t stime; 1889*7c478bd9Sstevel@tonic-gate struct tm *tmp; 1890*7c478bd9Sstevel@tonic-gate 1891*7c478bd9Sstevel@tonic-gate const char * const fmt = "%-*s%s\n"; 1892*7c478bd9Sstevel@tonic-gate 1893*7c478bd9Sstevel@tonic-gate assert(wip->pg == NULL); 1894*7c478bd9Sstevel@tonic-gate 1895*7c478bd9Sstevel@tonic-gate rpg = scf_pg_create(h); 1896*7c478bd9Sstevel@tonic-gate if (rpg == NULL) 1897*7c478bd9Sstevel@tonic-gate scfdie(); 1898*7c478bd9Sstevel@tonic-gate 1899*7c478bd9Sstevel@tonic-gate if (first_paragraph) 1900*7c478bd9Sstevel@tonic-gate first_paragraph = 0; 1901*7c478bd9Sstevel@tonic-gate else 1902*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate buf = safe_malloc(max_scf_fmri_length + 1); 1905*7c478bd9Sstevel@tonic-gate 1906*7c478bd9Sstevel@tonic-gate if (scf_instance_to_fmri(wip->inst, buf, max_scf_fmri_length + 1) != -1) 1907*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, "fmri", buf); 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate if (common_name_buf == NULL) 1910*7c478bd9Sstevel@tonic-gate common_name_buf = safe_malloc(max_scf_value_length + 1); 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate if (inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, locale, 1913*7c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0, 1, 1) 1914*7c478bd9Sstevel@tonic-gate == 0) 1915*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("name"), 1916*7c478bd9Sstevel@tonic-gate common_name_buf); 1917*7c478bd9Sstevel@tonic-gate else if (inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, "C", 1918*7c478bd9Sstevel@tonic-gate SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0, 1, 1) 1919*7c478bd9Sstevel@tonic-gate == 0) 1920*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("name"), 1921*7c478bd9Sstevel@tonic-gate common_name_buf); 1922*7c478bd9Sstevel@tonic-gate 1923*7c478bd9Sstevel@tonic-gate /* 1924*7c478bd9Sstevel@tonic-gate * Synthesize an 'enabled' property that hides the enabled_ovr 1925*7c478bd9Sstevel@tonic-gate * implementation from the user. If the service has been temporarily 1926*7c478bd9Sstevel@tonic-gate * set to a state other than its permanent value, alert the user with 1927*7c478bd9Sstevel@tonic-gate * a '(temporary)' message. 1928*7c478bd9Sstevel@tonic-gate */ 1929*7c478bd9Sstevel@tonic-gate perm = instance_enabled(wip->inst, B_FALSE); 1930*7c478bd9Sstevel@tonic-gate temp = instance_enabled(wip->inst, B_TRUE); 1931*7c478bd9Sstevel@tonic-gate if (temp != -1) { 1932*7c478bd9Sstevel@tonic-gate if (temp != perm) 1933*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-*s%s (temporary)\n"), 1934*7c478bd9Sstevel@tonic-gate DETAILED_WIDTH, gettext("enabled"), 1935*7c478bd9Sstevel@tonic-gate temp ? gettext("true") : gettext("false")); 1936*7c478bd9Sstevel@tonic-gate else 1937*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, 1938*7c478bd9Sstevel@tonic-gate gettext("enabled"), temp ? gettext("true") : 1939*7c478bd9Sstevel@tonic-gate gettext("false")); 1940*7c478bd9Sstevel@tonic-gate } else if (perm != -1) { 1941*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("enabled"), 1942*7c478bd9Sstevel@tonic-gate perm ? gettext("true") : gettext("false")); 1943*7c478bd9Sstevel@tonic-gate } 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate /* 1946*7c478bd9Sstevel@tonic-gate * Property values may be longer than max_scf_fmri_length, but these 1947*7c478bd9Sstevel@tonic-gate * shouldn't be, so we'll just reuse buf. The user can use svcprop if 1948*7c478bd9Sstevel@tonic-gate * he suspects something fishy. 1949*7c478bd9Sstevel@tonic-gate */ 1950*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(wip->inst, SCF_PG_RESTARTER, rpg) != 0) { 1951*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 1952*7c478bd9Sstevel@tonic-gate scfdie(); 1953*7c478bd9Sstevel@tonic-gate 1954*7c478bd9Sstevel@tonic-gate scf_pg_destroy(rpg); 1955*7c478bd9Sstevel@tonic-gate rpg = NULL; 1956*7c478bd9Sstevel@tonic-gate } 1957*7c478bd9Sstevel@tonic-gate 1958*7c478bd9Sstevel@tonic-gate if (rpg) { 1959*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(rpg, scf_property_state, SCF_TYPE_ASTRING, 1960*7c478bd9Sstevel@tonic-gate buf, max_scf_fmri_length + 1, 0) == 0) 1961*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("state"), 1962*7c478bd9Sstevel@tonic-gate buf); 1963*7c478bd9Sstevel@tonic-gate 1964*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(rpg, scf_property_next_state, 1965*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0) 1966*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, 1967*7c478bd9Sstevel@tonic-gate gettext("next_state"), buf); 1968*7c478bd9Sstevel@tonic-gate 1969*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(rpg, SCF_PROPERTY_STATE_TIMESTAMP, 1970*7c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, &tv, NULL, 0) == 0) { 1971*7c478bd9Sstevel@tonic-gate stime = tv.tv_sec; 1972*7c478bd9Sstevel@tonic-gate tmp = localtime(&stime); 1973*7c478bd9Sstevel@tonic-gate for (tbsz = 50; ; tbsz *= 2) { 1974*7c478bd9Sstevel@tonic-gate timebuf = safe_malloc(tbsz); 1975*7c478bd9Sstevel@tonic-gate if (strftime(timebuf, tbsz, NULL, tmp) != 0) 1976*7c478bd9Sstevel@tonic-gate break; 1977*7c478bd9Sstevel@tonic-gate free(timebuf); 1978*7c478bd9Sstevel@tonic-gate } 1979*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, 1980*7c478bd9Sstevel@tonic-gate gettext("state_time"), 1981*7c478bd9Sstevel@tonic-gate timebuf); 1982*7c478bd9Sstevel@tonic-gate free(timebuf); 1983*7c478bd9Sstevel@tonic-gate } 1984*7c478bd9Sstevel@tonic-gate 1985*7c478bd9Sstevel@tonic-gate } 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(rpg, SCF_PROPERTY_ALT_LOGFILE, 1988*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0) 1989*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("alt_logfile"), 1990*7c478bd9Sstevel@tonic-gate buf); 1991*7c478bd9Sstevel@tonic-gate 1992*7c478bd9Sstevel@tonic-gate if (pg_get_single_val(rpg, SCF_PROPERTY_LOGFILE, 1993*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0) 1994*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("logfile"), buf); 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate if (inst_get_single_val(wip->inst, SCF_PG_GENERAL, 1997*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_RESTARTER, SCF_TYPE_ASTRING, buf, 1998*7c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1, 0, 0, 1) == 0) 1999*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("restarter"), buf); 2000*7c478bd9Sstevel@tonic-gate else 2001*7c478bd9Sstevel@tonic-gate (void) printf(fmt, DETAILED_WIDTH, gettext("restarter"), 2002*7c478bd9Sstevel@tonic-gate SCF_SERVICE_STARTD); 2003*7c478bd9Sstevel@tonic-gate 2004*7c478bd9Sstevel@tonic-gate free(buf); 2005*7c478bd9Sstevel@tonic-gate 2006*7c478bd9Sstevel@tonic-gate if (rpg) { 2007*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 2008*7c478bd9Sstevel@tonic-gate 2009*7c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 2010*7c478bd9Sstevel@tonic-gate scfdie(); 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(rpg, scf_property_contract, g_prop) == 2013*7c478bd9Sstevel@tonic-gate 0) { 2014*7c478bd9Sstevel@tonic-gate if (scf_property_is_type(g_prop, SCF_TYPE_COUNT) == 0) { 2015*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", DETAILED_WIDTH, 2016*7c478bd9Sstevel@tonic-gate "contract_id"); 2017*7c478bd9Sstevel@tonic-gate 2018*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, g_prop) != 0) 2019*7c478bd9Sstevel@tonic-gate scfdie(); 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate for (;;) { 2022*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, g_val); 2023*7c478bd9Sstevel@tonic-gate if (ret == -1) 2024*7c478bd9Sstevel@tonic-gate scfdie(); 2025*7c478bd9Sstevel@tonic-gate if (ret == 0) 2026*7c478bd9Sstevel@tonic-gate break; 2027*7c478bd9Sstevel@tonic-gate 2028*7c478bd9Sstevel@tonic-gate if (scf_value_get_count(g_val, &c) != 0) 2029*7c478bd9Sstevel@tonic-gate scfdie(); 2030*7c478bd9Sstevel@tonic-gate (void) printf("%lu ", (ctid_t)c); 2031*7c478bd9Sstevel@tonic-gate } 2032*7c478bd9Sstevel@tonic-gate 2033*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 2034*7c478bd9Sstevel@tonic-gate } else { 2035*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_TYPE_MISMATCH) 2036*7c478bd9Sstevel@tonic-gate scfdie(); 2037*7c478bd9Sstevel@tonic-gate } 2038*7c478bd9Sstevel@tonic-gate } else { 2039*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2040*7c478bd9Sstevel@tonic-gate scfdie(); 2041*7c478bd9Sstevel@tonic-gate } 2042*7c478bd9Sstevel@tonic-gate 2043*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2044*7c478bd9Sstevel@tonic-gate } else { 2045*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2046*7c478bd9Sstevel@tonic-gate scfdie(); 2047*7c478bd9Sstevel@tonic-gate } 2048*7c478bd9Sstevel@tonic-gate 2049*7c478bd9Sstevel@tonic-gate scf_pg_destroy(rpg); 2050*7c478bd9Sstevel@tonic-gate 2051*7c478bd9Sstevel@tonic-gate /* Dependencies. */ 2052*7c478bd9Sstevel@tonic-gate if ((pg_iter = scf_iter_create(h)) == NULL) 2053*7c478bd9Sstevel@tonic-gate scfdie(); 2054*7c478bd9Sstevel@tonic-gate 2055*7c478bd9Sstevel@tonic-gate snap = get_running_snapshot(wip->inst); 2056*7c478bd9Sstevel@tonic-gate 2057*7c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(pg_iter, wip->inst, snap, 2058*7c478bd9Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) != SCF_SUCCESS) 2059*7c478bd9Sstevel@tonic-gate scfdie(); 2060*7c478bd9Sstevel@tonic-gate 2061*7c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_pg(pg_iter, g_pg)) == 1) 2062*7c478bd9Sstevel@tonic-gate print_detailed_dependency(g_pg); 2063*7c478bd9Sstevel@tonic-gate if (ret == -1) 2064*7c478bd9Sstevel@tonic-gate scfdie(); 2065*7c478bd9Sstevel@tonic-gate 2066*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 2067*7c478bd9Sstevel@tonic-gate scf_iter_destroy(pg_iter); 2068*7c478bd9Sstevel@tonic-gate 2069*7c478bd9Sstevel@tonic-gate if (opt_processes) 2070*7c478bd9Sstevel@tonic-gate detailed_list_processes(wip->inst); 2071*7c478bd9Sstevel@tonic-gate 2072*7c478bd9Sstevel@tonic-gate return (0); 2073*7c478bd9Sstevel@tonic-gate } 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate /* 2076*7c478bd9Sstevel@tonic-gate * Append a one-lined description of each process in inst's contract(s) and 2077*7c478bd9Sstevel@tonic-gate * return the augmented string. 2078*7c478bd9Sstevel@tonic-gate */ 2079*7c478bd9Sstevel@tonic-gate static char * 2080*7c478bd9Sstevel@tonic-gate add_processes(char *line, scf_instance_t *inst, scf_propertygroup_t *lpg) 2081*7c478bd9Sstevel@tonic-gate { 2082*7c478bd9Sstevel@tonic-gate pid_t *pids = NULL; 2083*7c478bd9Sstevel@tonic-gate uint_t i, n = 0; 2084*7c478bd9Sstevel@tonic-gate 2085*7c478bd9Sstevel@tonic-gate if (lpg == NULL) { 2086*7c478bd9Sstevel@tonic-gate if (instance_processes(inst, &pids, &n) != 0) 2087*7c478bd9Sstevel@tonic-gate return (line); 2088*7c478bd9Sstevel@tonic-gate } else { 2089*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 2090*7c478bd9Sstevel@tonic-gate 2091*7c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 2092*7c478bd9Sstevel@tonic-gate scfdie(); 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate (void) propvals_to_pids(lpg, scf_property_contract, &pids, &n, 2095*7c478bd9Sstevel@tonic-gate g_prop, g_val, iter); 2096*7c478bd9Sstevel@tonic-gate 2097*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2098*7c478bd9Sstevel@tonic-gate } 2099*7c478bd9Sstevel@tonic-gate 2100*7c478bd9Sstevel@tonic-gate if (n == 0) 2101*7c478bd9Sstevel@tonic-gate return (line); 2102*7c478bd9Sstevel@tonic-gate 2103*7c478bd9Sstevel@tonic-gate qsort(pids, n, sizeof (*pids), pidcmp); 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; ++i) { 2106*7c478bd9Sstevel@tonic-gate char *cp, stime[9]; 2107*7c478bd9Sstevel@tonic-gate psinfo_t psi; 2108*7c478bd9Sstevel@tonic-gate struct tm *tm; 2109*7c478bd9Sstevel@tonic-gate int len = 1 + 15 + 8 + 3 + 6 + 1 + PRFNSZ; 2110*7c478bd9Sstevel@tonic-gate 2111*7c478bd9Sstevel@tonic-gate if (get_psinfo(pids[i], &psi) != 0) 2112*7c478bd9Sstevel@tonic-gate continue; 2113*7c478bd9Sstevel@tonic-gate 2114*7c478bd9Sstevel@tonic-gate line = realloc(line, strlen(line) + len); 2115*7c478bd9Sstevel@tonic-gate if (line == NULL) 2116*7c478bd9Sstevel@tonic-gate uu_die(gettext("Out of memory.\n")); 2117*7c478bd9Sstevel@tonic-gate 2118*7c478bd9Sstevel@tonic-gate cp = strchr(line, '\0'); 2119*7c478bd9Sstevel@tonic-gate 2120*7c478bd9Sstevel@tonic-gate tm = localtime(&psi.pr_start.tv_sec); 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate /* 2123*7c478bd9Sstevel@tonic-gate * Print time if started within the past 24 hours, print date 2124*7c478bd9Sstevel@tonic-gate * if within the past 12 months, print year if started greater 2125*7c478bd9Sstevel@tonic-gate * than 12 months ago. 2126*7c478bd9Sstevel@tonic-gate */ 2127*7c478bd9Sstevel@tonic-gate if (now - psi.pr_start.tv_sec < 24 * 60 * 60) 2128*7c478bd9Sstevel@tonic-gate (void) strftime(stime, sizeof (stime), gettext(FORMAT_TIME), 2129*7c478bd9Sstevel@tonic-gate tm); 2130*7c478bd9Sstevel@tonic-gate else if (now - psi.pr_start.tv_sec < 12 * 30 * 24 * 60 * 60) 2131*7c478bd9Sstevel@tonic-gate (void) strftime(stime, sizeof (stime), gettext(FORMAT_DATE), 2132*7c478bd9Sstevel@tonic-gate tm); 2133*7c478bd9Sstevel@tonic-gate else 2134*7c478bd9Sstevel@tonic-gate (void) strftime(stime, sizeof (stime), gettext(FORMAT_YEAR), 2135*7c478bd9Sstevel@tonic-gate tm); 2136*7c478bd9Sstevel@tonic-gate 2137*7c478bd9Sstevel@tonic-gate (void) snprintf(cp, len, "\n %-8s %6ld %.*s", 2138*7c478bd9Sstevel@tonic-gate stime, pids[i], PRFNSZ, psi.pr_fname); 2139*7c478bd9Sstevel@tonic-gate } 2140*7c478bd9Sstevel@tonic-gate 2141*7c478bd9Sstevel@tonic-gate free(pids); 2142*7c478bd9Sstevel@tonic-gate 2143*7c478bd9Sstevel@tonic-gate return (line); 2144*7c478bd9Sstevel@tonic-gate } 2145*7c478bd9Sstevel@tonic-gate 2146*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2147*7c478bd9Sstevel@tonic-gate static int 2148*7c478bd9Sstevel@tonic-gate list_instance(void *unused, scf_walkinfo_t *wip) 2149*7c478bd9Sstevel@tonic-gate { 2150*7c478bd9Sstevel@tonic-gate struct avl_string *lp; 2151*7c478bd9Sstevel@tonic-gate char *cp; 2152*7c478bd9Sstevel@tonic-gate int i; 2153*7c478bd9Sstevel@tonic-gate uu_avl_index_t idx; 2154*7c478bd9Sstevel@tonic-gate 2155*7c478bd9Sstevel@tonic-gate /* 2156*7c478bd9Sstevel@tonic-gate * If the user has specified a restarter, check for a match first 2157*7c478bd9Sstevel@tonic-gate */ 2158*7c478bd9Sstevel@tonic-gate if (restarters != NULL) { 2159*7c478bd9Sstevel@tonic-gate struct pfmri_list *rest; 2160*7c478bd9Sstevel@tonic-gate int match; 2161*7c478bd9Sstevel@tonic-gate char *restarter_fmri; 2162*7c478bd9Sstevel@tonic-gate const char *scope_name, *svc_name, *inst_name, *pg_name; 2163*7c478bd9Sstevel@tonic-gate 2164*7c478bd9Sstevel@tonic-gate /* legacy services don't have restarters */ 2165*7c478bd9Sstevel@tonic-gate if (wip->pg != NULL) 2166*7c478bd9Sstevel@tonic-gate return (0); 2167*7c478bd9Sstevel@tonic-gate 2168*7c478bd9Sstevel@tonic-gate restarter_fmri = safe_malloc(max_scf_fmri_length + 1); 2169*7c478bd9Sstevel@tonic-gate 2170*7c478bd9Sstevel@tonic-gate if (inst_get_single_val(wip->inst, SCF_PG_GENERAL, 2171*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_RESTARTER, SCF_TYPE_ASTRING, restarter_fmri, 2172*7c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1, 0, 0, 1) != 0) 2173*7c478bd9Sstevel@tonic-gate (void) strcpy(restarter_fmri, SCF_SERVICE_STARTD); 2174*7c478bd9Sstevel@tonic-gate 2175*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(restarter_fmri, &scope_name, &svc_name, 2176*7c478bd9Sstevel@tonic-gate &inst_name, &pg_name, NULL) != SCF_SUCCESS) { 2177*7c478bd9Sstevel@tonic-gate free(restarter_fmri); 2178*7c478bd9Sstevel@tonic-gate return (0); 2179*7c478bd9Sstevel@tonic-gate } 2180*7c478bd9Sstevel@tonic-gate 2181*7c478bd9Sstevel@tonic-gate match = 0; 2182*7c478bd9Sstevel@tonic-gate for (rest = restarters; rest != NULL; rest = rest->next) { 2183*7c478bd9Sstevel@tonic-gate if (strcmp(rest->scope, scope_name) == 0 && 2184*7c478bd9Sstevel@tonic-gate strcmp(rest->service, svc_name) == 0 && 2185*7c478bd9Sstevel@tonic-gate strcmp(rest->instance, inst_name) == 0) 2186*7c478bd9Sstevel@tonic-gate match = 1; 2187*7c478bd9Sstevel@tonic-gate } 2188*7c478bd9Sstevel@tonic-gate 2189*7c478bd9Sstevel@tonic-gate free(restarter_fmri); 2190*7c478bd9Sstevel@tonic-gate 2191*7c478bd9Sstevel@tonic-gate if (!match) 2192*7c478bd9Sstevel@tonic-gate return (0); 2193*7c478bd9Sstevel@tonic-gate } 2194*7c478bd9Sstevel@tonic-gate 2195*7c478bd9Sstevel@tonic-gate if (wip->pg == NULL && ht_buckets != NULL && ht_add(wip->fmri)) { 2196*7c478bd9Sstevel@tonic-gate /* It was already there. */ 2197*7c478bd9Sstevel@tonic-gate return (0); 2198*7c478bd9Sstevel@tonic-gate } 2199*7c478bd9Sstevel@tonic-gate 2200*7c478bd9Sstevel@tonic-gate lp = safe_malloc(sizeof (*lp)); 2201*7c478bd9Sstevel@tonic-gate 2202*7c478bd9Sstevel@tonic-gate lp->str = NULL; 2203*7c478bd9Sstevel@tonic-gate for (i = 0; i < opt_cnum; ++i) { 2204*7c478bd9Sstevel@tonic-gate columns[opt_columns[i]].sprint(&lp->str, wip); 2205*7c478bd9Sstevel@tonic-gate } 2206*7c478bd9Sstevel@tonic-gate cp = lp->str + strlen(lp->str); 2207*7c478bd9Sstevel@tonic-gate cp--; 2208*7c478bd9Sstevel@tonic-gate while (*cp == ' ') 2209*7c478bd9Sstevel@tonic-gate cp--; 2210*7c478bd9Sstevel@tonic-gate *(cp+1) = '\0'; 2211*7c478bd9Sstevel@tonic-gate 2212*7c478bd9Sstevel@tonic-gate /* If we're supposed to list the processes, too, do that now. */ 2213*7c478bd9Sstevel@tonic-gate if (opt_processes) 2214*7c478bd9Sstevel@tonic-gate lp->str = add_processes(lp->str, wip->inst, wip->pg); 2215*7c478bd9Sstevel@tonic-gate 2216*7c478bd9Sstevel@tonic-gate /* Create the sort key. */ 2217*7c478bd9Sstevel@tonic-gate cp = lp->key = safe_malloc(sortkey_sz); 2218*7c478bd9Sstevel@tonic-gate for (i = 0; i < opt_snum; ++i) { 2219*7c478bd9Sstevel@tonic-gate int j = opt_sort[i] & 0xff; 2220*7c478bd9Sstevel@tonic-gate 2221*7c478bd9Sstevel@tonic-gate assert(columns[j].get_sortkey != NULL); 2222*7c478bd9Sstevel@tonic-gate columns[j].get_sortkey(cp, opt_sort[i] & ~0xff, wip); 2223*7c478bd9Sstevel@tonic-gate cp += columns[j].sortkey_width; 2224*7c478bd9Sstevel@tonic-gate } 2225*7c478bd9Sstevel@tonic-gate 2226*7c478bd9Sstevel@tonic-gate /* Insert into AVL tree. */ 2227*7c478bd9Sstevel@tonic-gate uu_avl_node_init(lp, &lp->node, lines_pool); 2228*7c478bd9Sstevel@tonic-gate (void) uu_avl_find(lines, lp, NULL, &idx); 2229*7c478bd9Sstevel@tonic-gate uu_avl_insert(lines, lp, idx); 2230*7c478bd9Sstevel@tonic-gate 2231*7c478bd9Sstevel@tonic-gate return (0); 2232*7c478bd9Sstevel@tonic-gate } 2233*7c478bd9Sstevel@tonic-gate 2234*7c478bd9Sstevel@tonic-gate static int 2235*7c478bd9Sstevel@tonic-gate list_if_enabled(void *unused, scf_walkinfo_t *wip) 2236*7c478bd9Sstevel@tonic-gate { 2237*7c478bd9Sstevel@tonic-gate if (wip->pg != NULL || 2238*7c478bd9Sstevel@tonic-gate instance_enabled(wip->inst, B_FALSE) == 1 || 2239*7c478bd9Sstevel@tonic-gate instance_enabled(wip->inst, B_TRUE) == 1) 2240*7c478bd9Sstevel@tonic-gate return (list_instance(unused, wip)); 2241*7c478bd9Sstevel@tonic-gate 2242*7c478bd9Sstevel@tonic-gate return (0); 2243*7c478bd9Sstevel@tonic-gate } 2244*7c478bd9Sstevel@tonic-gate 2245*7c478bd9Sstevel@tonic-gate /* 2246*7c478bd9Sstevel@tonic-gate * Service FMRI selection: Lookup and call list_instance() for the instances. 2247*7c478bd9Sstevel@tonic-gate * Instance FMRI selection: Lookup and call list_instance(). 2248*7c478bd9Sstevel@tonic-gate * 2249*7c478bd9Sstevel@tonic-gate * Note: This is shoehorned into a walk_dependencies() callback prototype so 2250*7c478bd9Sstevel@tonic-gate * it can be used in list_dependencies. 2251*7c478bd9Sstevel@tonic-gate */ 2252*7c478bd9Sstevel@tonic-gate static int 2253*7c478bd9Sstevel@tonic-gate list_svc_or_inst_fmri(void *complain, scf_walkinfo_t *wip) 2254*7c478bd9Sstevel@tonic-gate { 2255*7c478bd9Sstevel@tonic-gate char *fmri; 2256*7c478bd9Sstevel@tonic-gate const char *svc_name, *inst_name, *pg_name, *save; 2257*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 2258*7c478bd9Sstevel@tonic-gate int ret; 2259*7c478bd9Sstevel@tonic-gate 2260*7c478bd9Sstevel@tonic-gate fmri = safe_strdup(wip->fmri); 2261*7c478bd9Sstevel@tonic-gate 2262*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(fmri, NULL, &svc_name, &inst_name, &pg_name, 2263*7c478bd9Sstevel@tonic-gate NULL) != SCF_SUCCESS) { 2264*7c478bd9Sstevel@tonic-gate if (complain) 2265*7c478bd9Sstevel@tonic-gate uu_warn(gettext("FMRI \"%s\" is invalid.\n"), 2266*7c478bd9Sstevel@tonic-gate wip->fmri); 2267*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2268*7c478bd9Sstevel@tonic-gate free(fmri); 2269*7c478bd9Sstevel@tonic-gate return (0); 2270*7c478bd9Sstevel@tonic-gate } 2271*7c478bd9Sstevel@tonic-gate 2272*7c478bd9Sstevel@tonic-gate /* 2273*7c478bd9Sstevel@tonic-gate * Yes, this invalidates *_name, but we only care whether they're NULL 2274*7c478bd9Sstevel@tonic-gate * or not. 2275*7c478bd9Sstevel@tonic-gate */ 2276*7c478bd9Sstevel@tonic-gate free(fmri); 2277*7c478bd9Sstevel@tonic-gate 2278*7c478bd9Sstevel@tonic-gate if (svc_name == NULL || pg_name != NULL) { 2279*7c478bd9Sstevel@tonic-gate if (complain) 2280*7c478bd9Sstevel@tonic-gate uu_warn(gettext("FMRI \"%s\" does not designate a " 2281*7c478bd9Sstevel@tonic-gate "service or instance.\n"), wip->fmri); 2282*7c478bd9Sstevel@tonic-gate return (0); 2283*7c478bd9Sstevel@tonic-gate } 2284*7c478bd9Sstevel@tonic-gate 2285*7c478bd9Sstevel@tonic-gate if (inst_name != NULL) { 2286*7c478bd9Sstevel@tonic-gate /* instance */ 2287*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, wip->fmri, wip->scope, wip->svc, 2288*7c478bd9Sstevel@tonic-gate wip->inst, NULL, NULL, 0) != SCF_SUCCESS) { 2289*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2290*7c478bd9Sstevel@tonic-gate scfdie(); 2291*7c478bd9Sstevel@tonic-gate 2292*7c478bd9Sstevel@tonic-gate if (complain) 2293*7c478bd9Sstevel@tonic-gate uu_warn(gettext( 2294*7c478bd9Sstevel@tonic-gate "Instance \"%s\" does not exist.\n"), 2295*7c478bd9Sstevel@tonic-gate wip->fmri); 2296*7c478bd9Sstevel@tonic-gate return (0); 2297*7c478bd9Sstevel@tonic-gate } 2298*7c478bd9Sstevel@tonic-gate 2299*7c478bd9Sstevel@tonic-gate return (list_instance(NULL, wip)); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate /* service: Walk the instances. */ 2303*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, wip->fmri, wip->scope, wip->svc, NULL, 2304*7c478bd9Sstevel@tonic-gate NULL, NULL, 0) != SCF_SUCCESS) { 2305*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2306*7c478bd9Sstevel@tonic-gate scfdie(); 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate if (complain) 2309*7c478bd9Sstevel@tonic-gate uu_warn(gettext("Service \"%s\" does not exist.\n"), 2310*7c478bd9Sstevel@tonic-gate wip->fmri); 2311*7c478bd9Sstevel@tonic-gate 2312*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate return (0); 2315*7c478bd9Sstevel@tonic-gate } 2316*7c478bd9Sstevel@tonic-gate 2317*7c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 2318*7c478bd9Sstevel@tonic-gate if (iter == NULL) 2319*7c478bd9Sstevel@tonic-gate scfdie(); 2320*7c478bd9Sstevel@tonic-gate 2321*7c478bd9Sstevel@tonic-gate if (scf_iter_service_instances(iter, wip->svc) != SCF_SUCCESS) 2322*7c478bd9Sstevel@tonic-gate scfdie(); 2323*7c478bd9Sstevel@tonic-gate 2324*7c478bd9Sstevel@tonic-gate if ((fmri = malloc(max_scf_fmri_length + 1)) == NULL) { 2325*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2326*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2327*7c478bd9Sstevel@tonic-gate return (0); 2328*7c478bd9Sstevel@tonic-gate } 2329*7c478bd9Sstevel@tonic-gate 2330*7c478bd9Sstevel@tonic-gate save = wip->fmri; 2331*7c478bd9Sstevel@tonic-gate wip->fmri = fmri; 2332*7c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_instance(iter, wip->inst)) == 1) { 2333*7c478bd9Sstevel@tonic-gate if (scf_instance_to_fmri(wip->inst, fmri, 2334*7c478bd9Sstevel@tonic-gate max_scf_fmri_length + 1) <= 0) 2335*7c478bd9Sstevel@tonic-gate scfdie(); 2336*7c478bd9Sstevel@tonic-gate (void) list_instance(NULL, wip); 2337*7c478bd9Sstevel@tonic-gate } 2338*7c478bd9Sstevel@tonic-gate free(fmri); 2339*7c478bd9Sstevel@tonic-gate wip->fmri = save; 2340*7c478bd9Sstevel@tonic-gate if (ret == -1) 2341*7c478bd9Sstevel@tonic-gate scfdie(); 2342*7c478bd9Sstevel@tonic-gate 2343*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_OK; 2344*7c478bd9Sstevel@tonic-gate 2345*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2346*7c478bd9Sstevel@tonic-gate 2347*7c478bd9Sstevel@tonic-gate return (0); 2348*7c478bd9Sstevel@tonic-gate } 2349*7c478bd9Sstevel@tonic-gate 2350*7c478bd9Sstevel@tonic-gate /* 2351*7c478bd9Sstevel@tonic-gate * Dependency selection: Straightforward since each instance lists the 2352*7c478bd9Sstevel@tonic-gate * services it depends on. 2353*7c478bd9Sstevel@tonic-gate */ 2354*7c478bd9Sstevel@tonic-gate 2355*7c478bd9Sstevel@tonic-gate static void 2356*7c478bd9Sstevel@tonic-gate walk_dependencies(scf_walkinfo_t *wip, scf_walk_callback callback, void *data) 2357*7c478bd9Sstevel@tonic-gate { 2358*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap; 2359*7c478bd9Sstevel@tonic-gate scf_iter_t *iter, *viter; 2360*7c478bd9Sstevel@tonic-gate int ret, vret; 2361*7c478bd9Sstevel@tonic-gate char *dep; 2362*7c478bd9Sstevel@tonic-gate 2363*7c478bd9Sstevel@tonic-gate assert(wip->inst != NULL); 2364*7c478bd9Sstevel@tonic-gate 2365*7c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL || 2366*7c478bd9Sstevel@tonic-gate (viter = scf_iter_create(h)) == NULL) 2367*7c478bd9Sstevel@tonic-gate scfdie(); 2368*7c478bd9Sstevel@tonic-gate 2369*7c478bd9Sstevel@tonic-gate snap = get_running_snapshot(wip->inst); 2370*7c478bd9Sstevel@tonic-gate 2371*7c478bd9Sstevel@tonic-gate if (scf_iter_instance_pgs_typed_composed(iter, wip->inst, snap, 2372*7c478bd9Sstevel@tonic-gate SCF_GROUP_DEPENDENCY) != SCF_SUCCESS) 2373*7c478bd9Sstevel@tonic-gate scfdie(); 2374*7c478bd9Sstevel@tonic-gate 2375*7c478bd9Sstevel@tonic-gate dep = safe_malloc(max_scf_value_length + 1); 2376*7c478bd9Sstevel@tonic-gate 2377*7c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_pg(iter, g_pg)) == 1) { 2378*7c478bd9Sstevel@tonic-gate scf_type_t ty; 2379*7c478bd9Sstevel@tonic-gate 2380*7c478bd9Sstevel@tonic-gate /* Ignore exclude_any dependencies. */ 2381*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(g_pg, SCF_PROPERTY_GROUPING, g_prop) != 2382*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2383*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2384*7c478bd9Sstevel@tonic-gate scfdie(); 2385*7c478bd9Sstevel@tonic-gate 2386*7c478bd9Sstevel@tonic-gate continue; 2387*7c478bd9Sstevel@tonic-gate } 2388*7c478bd9Sstevel@tonic-gate 2389*7c478bd9Sstevel@tonic-gate if (scf_property_type(g_prop, &ty) != SCF_SUCCESS) 2390*7c478bd9Sstevel@tonic-gate scfdie(); 2391*7c478bd9Sstevel@tonic-gate 2392*7c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_ASTRING) 2393*7c478bd9Sstevel@tonic-gate continue; 2394*7c478bd9Sstevel@tonic-gate 2395*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(g_prop, g_val) != SCF_SUCCESS) { 2396*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED) 2397*7c478bd9Sstevel@tonic-gate scfdie(); 2398*7c478bd9Sstevel@tonic-gate 2399*7c478bd9Sstevel@tonic-gate continue; 2400*7c478bd9Sstevel@tonic-gate } 2401*7c478bd9Sstevel@tonic-gate 2402*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, dep, 2403*7c478bd9Sstevel@tonic-gate max_scf_value_length + 1) < 0) 2404*7c478bd9Sstevel@tonic-gate scfdie(); 2405*7c478bd9Sstevel@tonic-gate 2406*7c478bd9Sstevel@tonic-gate if (strcmp(dep, SCF_DEP_EXCLUDE_ALL) == 0) 2407*7c478bd9Sstevel@tonic-gate continue; 2408*7c478bd9Sstevel@tonic-gate 2409*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(g_pg, SCF_PROPERTY_ENTITIES, g_prop) != 2410*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2411*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) 2412*7c478bd9Sstevel@tonic-gate scfdie(); 2413*7c478bd9Sstevel@tonic-gate 2414*7c478bd9Sstevel@tonic-gate continue; 2415*7c478bd9Sstevel@tonic-gate } 2416*7c478bd9Sstevel@tonic-gate 2417*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(viter, g_prop) != SCF_SUCCESS) 2418*7c478bd9Sstevel@tonic-gate scfdie(); 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate while ((vret = scf_iter_next_value(viter, g_val)) == 1) { 2421*7c478bd9Sstevel@tonic-gate if (scf_value_get_astring(g_val, dep, 2422*7c478bd9Sstevel@tonic-gate max_scf_value_length + 1) < 0) 2423*7c478bd9Sstevel@tonic-gate scfdie(); 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate wip->fmri = dep; 2426*7c478bd9Sstevel@tonic-gate if (callback(data, wip) != 0) 2427*7c478bd9Sstevel@tonic-gate goto out; 2428*7c478bd9Sstevel@tonic-gate } 2429*7c478bd9Sstevel@tonic-gate if (vret == -1) 2430*7c478bd9Sstevel@tonic-gate scfdie(); 2431*7c478bd9Sstevel@tonic-gate } 2432*7c478bd9Sstevel@tonic-gate if (ret == -1) 2433*7c478bd9Sstevel@tonic-gate scfdie(); 2434*7c478bd9Sstevel@tonic-gate 2435*7c478bd9Sstevel@tonic-gate out: 2436*7c478bd9Sstevel@tonic-gate scf_iter_destroy(viter); 2437*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2438*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 2439*7c478bd9Sstevel@tonic-gate } 2440*7c478bd9Sstevel@tonic-gate 2441*7c478bd9Sstevel@tonic-gate static int 2442*7c478bd9Sstevel@tonic-gate list_dependencies(void *data, scf_walkinfo_t *wip) 2443*7c478bd9Sstevel@tonic-gate { 2444*7c478bd9Sstevel@tonic-gate walk_dependencies(wip, list_svc_or_inst_fmri, data); 2445*7c478bd9Sstevel@tonic-gate return (0); 2446*7c478bd9Sstevel@tonic-gate } 2447*7c478bd9Sstevel@tonic-gate 2448*7c478bd9Sstevel@tonic-gate 2449*7c478bd9Sstevel@tonic-gate /* 2450*7c478bd9Sstevel@tonic-gate * Dependent selection: The "providing" service's or instance's FMRI is parsed 2451*7c478bd9Sstevel@tonic-gate * into the provider_* variables, the instances are walked, and any instance 2452*7c478bd9Sstevel@tonic-gate * which lists an FMRI which parses to these components is selected. This is 2453*7c478bd9Sstevel@tonic-gate * inefficient in the face of multiple operands, but that should be uncommon. 2454*7c478bd9Sstevel@tonic-gate */ 2455*7c478bd9Sstevel@tonic-gate 2456*7c478bd9Sstevel@tonic-gate static char *provider_scope; 2457*7c478bd9Sstevel@tonic-gate static char *provider_svc; 2458*7c478bd9Sstevel@tonic-gate static char *provider_inst; /* NULL for services */ 2459*7c478bd9Sstevel@tonic-gate 2460*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2461*7c478bd9Sstevel@tonic-gate static int 2462*7c478bd9Sstevel@tonic-gate check_against_provider(void *arg, scf_walkinfo_t *wip) 2463*7c478bd9Sstevel@tonic-gate { 2464*7c478bd9Sstevel@tonic-gate char *cfmri; 2465*7c478bd9Sstevel@tonic-gate const char *scope_name, *svc_name, *inst_name, *pg_name; 2466*7c478bd9Sstevel@tonic-gate int *matchp = arg; 2467*7c478bd9Sstevel@tonic-gate 2468*7c478bd9Sstevel@tonic-gate cfmri = safe_strdup(wip->fmri); 2469*7c478bd9Sstevel@tonic-gate 2470*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(cfmri, &scope_name, &svc_name, &inst_name, 2471*7c478bd9Sstevel@tonic-gate &pg_name, NULL) != SCF_SUCCESS) { 2472*7c478bd9Sstevel@tonic-gate free(cfmri); 2473*7c478bd9Sstevel@tonic-gate return (0); 2474*7c478bd9Sstevel@tonic-gate } 2475*7c478bd9Sstevel@tonic-gate 2476*7c478bd9Sstevel@tonic-gate if (svc_name == NULL || pg_name != NULL) { 2477*7c478bd9Sstevel@tonic-gate free(cfmri); 2478*7c478bd9Sstevel@tonic-gate return (0); 2479*7c478bd9Sstevel@tonic-gate } 2480*7c478bd9Sstevel@tonic-gate 2481*7c478bd9Sstevel@tonic-gate /* 2482*7c478bd9Sstevel@tonic-gate * If the user has specified an instance, then also match dependencies 2483*7c478bd9Sstevel@tonic-gate * on the service itself. 2484*7c478bd9Sstevel@tonic-gate */ 2485*7c478bd9Sstevel@tonic-gate *matchp = (strcmp(provider_scope, scope_name) == 0 && 2486*7c478bd9Sstevel@tonic-gate strcmp(provider_svc, svc_name) == 0 && 2487*7c478bd9Sstevel@tonic-gate (provider_inst == NULL ? (inst_name == NULL) : 2488*7c478bd9Sstevel@tonic-gate (inst_name == NULL || strcmp(provider_inst, inst_name) == 0))); 2489*7c478bd9Sstevel@tonic-gate 2490*7c478bd9Sstevel@tonic-gate free(cfmri); 2491*7c478bd9Sstevel@tonic-gate 2492*7c478bd9Sstevel@tonic-gate /* Stop on matches. */ 2493*7c478bd9Sstevel@tonic-gate return (*matchp); 2494*7c478bd9Sstevel@tonic-gate } 2495*7c478bd9Sstevel@tonic-gate 2496*7c478bd9Sstevel@tonic-gate static int 2497*7c478bd9Sstevel@tonic-gate list_if_dependent(void *unused, scf_walkinfo_t *wip) 2498*7c478bd9Sstevel@tonic-gate { 2499*7c478bd9Sstevel@tonic-gate /* Only proceed if this instance depends on provider_*. */ 2500*7c478bd9Sstevel@tonic-gate int match = 0; 2501*7c478bd9Sstevel@tonic-gate 2502*7c478bd9Sstevel@tonic-gate (void) walk_dependencies(wip, check_against_provider, &match); 2503*7c478bd9Sstevel@tonic-gate 2504*7c478bd9Sstevel@tonic-gate if (match) 2505*7c478bd9Sstevel@tonic-gate return (list_instance(unused, wip)); 2506*7c478bd9Sstevel@tonic-gate 2507*7c478bd9Sstevel@tonic-gate return (0); 2508*7c478bd9Sstevel@tonic-gate } 2509*7c478bd9Sstevel@tonic-gate 2510*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2511*7c478bd9Sstevel@tonic-gate static int 2512*7c478bd9Sstevel@tonic-gate list_dependents(void *unused, scf_walkinfo_t *wip) 2513*7c478bd9Sstevel@tonic-gate { 2514*7c478bd9Sstevel@tonic-gate char *save; 2515*7c478bd9Sstevel@tonic-gate int ret; 2516*7c478bd9Sstevel@tonic-gate 2517*7c478bd9Sstevel@tonic-gate if (scf_scope_get_name(wip->scope, provider_scope, 2518*7c478bd9Sstevel@tonic-gate max_scf_fmri_length) <= 0 || 2519*7c478bd9Sstevel@tonic-gate scf_service_get_name(wip->svc, provider_svc, 2520*7c478bd9Sstevel@tonic-gate max_scf_fmri_length) <= 0) 2521*7c478bd9Sstevel@tonic-gate scfdie(); 2522*7c478bd9Sstevel@tonic-gate 2523*7c478bd9Sstevel@tonic-gate save = provider_inst; 2524*7c478bd9Sstevel@tonic-gate if (wip->inst == NULL) 2525*7c478bd9Sstevel@tonic-gate provider_inst = NULL; 2526*7c478bd9Sstevel@tonic-gate else if (scf_instance_get_name(wip->inst, provider_inst, 2527*7c478bd9Sstevel@tonic-gate max_scf_fmri_length) <= 0) 2528*7c478bd9Sstevel@tonic-gate scfdie(); 2529*7c478bd9Sstevel@tonic-gate 2530*7c478bd9Sstevel@tonic-gate ret = scf_walk_fmri(h, 0, NULL, 0, list_if_dependent, NULL, NULL, 2531*7c478bd9Sstevel@tonic-gate uu_warn); 2532*7c478bd9Sstevel@tonic-gate 2533*7c478bd9Sstevel@tonic-gate provider_inst = save; 2534*7c478bd9Sstevel@tonic-gate 2535*7c478bd9Sstevel@tonic-gate return (ret); 2536*7c478bd9Sstevel@tonic-gate } 2537*7c478bd9Sstevel@tonic-gate 2538*7c478bd9Sstevel@tonic-gate /* 2539*7c478bd9Sstevel@tonic-gate * main() & helpers 2540*7c478bd9Sstevel@tonic-gate */ 2541*7c478bd9Sstevel@tonic-gate 2542*7c478bd9Sstevel@tonic-gate static void 2543*7c478bd9Sstevel@tonic-gate add_sort_column(const char *col, int reverse) 2544*7c478bd9Sstevel@tonic-gate { 2545*7c478bd9Sstevel@tonic-gate int i; 2546*7c478bd9Sstevel@tonic-gate 2547*7c478bd9Sstevel@tonic-gate ++opt_snum; 2548*7c478bd9Sstevel@tonic-gate 2549*7c478bd9Sstevel@tonic-gate opt_sort = realloc(opt_sort, opt_snum * sizeof (*opt_sort)); 2550*7c478bd9Sstevel@tonic-gate if (opt_sort == NULL) 2551*7c478bd9Sstevel@tonic-gate uu_die(gettext("Too many sort criteria: out of memory.\n")); 2552*7c478bd9Sstevel@tonic-gate 2553*7c478bd9Sstevel@tonic-gate for (i = 0; i < ncolumns; ++i) { 2554*7c478bd9Sstevel@tonic-gate if (strcasecmp(col, columns[i].name) == 0) 2555*7c478bd9Sstevel@tonic-gate break; 2556*7c478bd9Sstevel@tonic-gate } 2557*7c478bd9Sstevel@tonic-gate 2558*7c478bd9Sstevel@tonic-gate if (i < ncolumns) 2559*7c478bd9Sstevel@tonic-gate opt_sort[opt_snum - 1] = (reverse ? i | 0x100 : i); 2560*7c478bd9Sstevel@tonic-gate else 2561*7c478bd9Sstevel@tonic-gate uu_die(gettext("Unrecognized sort column \"%s\".\n"), col); 2562*7c478bd9Sstevel@tonic-gate 2563*7c478bd9Sstevel@tonic-gate sortkey_sz += columns[i].sortkey_width; 2564*7c478bd9Sstevel@tonic-gate } 2565*7c478bd9Sstevel@tonic-gate 2566*7c478bd9Sstevel@tonic-gate static void 2567*7c478bd9Sstevel@tonic-gate add_restarter(const char *fmri) 2568*7c478bd9Sstevel@tonic-gate { 2569*7c478bd9Sstevel@tonic-gate char *cfmri; 2570*7c478bd9Sstevel@tonic-gate const char *pg_name; 2571*7c478bd9Sstevel@tonic-gate struct pfmri_list *rest; 2572*7c478bd9Sstevel@tonic-gate 2573*7c478bd9Sstevel@tonic-gate cfmri = safe_strdup(fmri); 2574*7c478bd9Sstevel@tonic-gate rest = safe_malloc(sizeof (*rest)); 2575*7c478bd9Sstevel@tonic-gate 2576*7c478bd9Sstevel@tonic-gate if (scf_parse_svc_fmri(cfmri, &rest->scope, &rest->service, 2577*7c478bd9Sstevel@tonic-gate &rest->instance, &pg_name, NULL) != SCF_SUCCESS) 2578*7c478bd9Sstevel@tonic-gate uu_die(gettext("Restarter FMRI \"%s\" is invalid.\n"), fmri); 2579*7c478bd9Sstevel@tonic-gate 2580*7c478bd9Sstevel@tonic-gate if (rest->instance == NULL || pg_name != NULL) 2581*7c478bd9Sstevel@tonic-gate uu_die(gettext("Restarter FMRI \"%s\" does not designate an " 2582*7c478bd9Sstevel@tonic-gate "instance.\n"), fmri); 2583*7c478bd9Sstevel@tonic-gate 2584*7c478bd9Sstevel@tonic-gate rest->next = restarters; 2585*7c478bd9Sstevel@tonic-gate restarters = rest; 2586*7c478bd9Sstevel@tonic-gate return; 2587*7c478bd9Sstevel@tonic-gate 2588*7c478bd9Sstevel@tonic-gate err: 2589*7c478bd9Sstevel@tonic-gate free(cfmri); 2590*7c478bd9Sstevel@tonic-gate free(rest); 2591*7c478bd9Sstevel@tonic-gate } 2592*7c478bd9Sstevel@tonic-gate 2593*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2594*7c478bd9Sstevel@tonic-gate static int 2595*7c478bd9Sstevel@tonic-gate line_cmp(const void *l_arg, const void *r_arg, void *private) 2596*7c478bd9Sstevel@tonic-gate { 2597*7c478bd9Sstevel@tonic-gate const struct avl_string *l = l_arg; 2598*7c478bd9Sstevel@tonic-gate const struct avl_string *r = r_arg; 2599*7c478bd9Sstevel@tonic-gate 2600*7c478bd9Sstevel@tonic-gate return (memcmp(l->key, r->key, sortkey_sz)); 2601*7c478bd9Sstevel@tonic-gate } 2602*7c478bd9Sstevel@tonic-gate 2603*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2604*7c478bd9Sstevel@tonic-gate static int 2605*7c478bd9Sstevel@tonic-gate print_line(void *e, void *private) 2606*7c478bd9Sstevel@tonic-gate { 2607*7c478bd9Sstevel@tonic-gate struct avl_string *lp = e; 2608*7c478bd9Sstevel@tonic-gate 2609*7c478bd9Sstevel@tonic-gate (void) puts(lp->str); 2610*7c478bd9Sstevel@tonic-gate 2611*7c478bd9Sstevel@tonic-gate return (UU_WALK_NEXT); 2612*7c478bd9Sstevel@tonic-gate } 2613*7c478bd9Sstevel@tonic-gate 2614*7c478bd9Sstevel@tonic-gate int 2615*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 2616*7c478bd9Sstevel@tonic-gate { 2617*7c478bd9Sstevel@tonic-gate char opt, opt_mode; 2618*7c478bd9Sstevel@tonic-gate int i, n; 2619*7c478bd9Sstevel@tonic-gate char *columns_str = NULL; 2620*7c478bd9Sstevel@tonic-gate char *cp; 2621*7c478bd9Sstevel@tonic-gate const char *progname; 2622*7c478bd9Sstevel@tonic-gate int err; 2623*7c478bd9Sstevel@tonic-gate 2624*7c478bd9Sstevel@tonic-gate int show_all = 0; 2625*7c478bd9Sstevel@tonic-gate int show_header = 1; 2626*7c478bd9Sstevel@tonic-gate 2627*7c478bd9Sstevel@tonic-gate const char * const options = "aHpvo:R:s:S:dDl?x"; 2628*7c478bd9Sstevel@tonic-gate 2629*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2630*7c478bd9Sstevel@tonic-gate 2631*7c478bd9Sstevel@tonic-gate locale = setlocale(LC_MESSAGES, ""); 2632*7c478bd9Sstevel@tonic-gate if (locale) { 2633*7c478bd9Sstevel@tonic-gate locale = safe_strdup(locale); 2634*7c478bd9Sstevel@tonic-gate sanitize_locale(locale); 2635*7c478bd9Sstevel@tonic-gate } 2636*7c478bd9Sstevel@tonic-gate 2637*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2638*7c478bd9Sstevel@tonic-gate progname = uu_setpname(argv[0]); 2639*7c478bd9Sstevel@tonic-gate 2640*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_OK; 2641*7c478bd9Sstevel@tonic-gate 2642*7c478bd9Sstevel@tonic-gate max_scf_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH); 2643*7c478bd9Sstevel@tonic-gate max_scf_value_length = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 2644*7c478bd9Sstevel@tonic-gate max_scf_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 2645*7c478bd9Sstevel@tonic-gate 2646*7c478bd9Sstevel@tonic-gate if (max_scf_name_length == -1 || max_scf_value_length == -1 || 2647*7c478bd9Sstevel@tonic-gate max_scf_fmri_length == -1) 2648*7c478bd9Sstevel@tonic-gate scfdie(); 2649*7c478bd9Sstevel@tonic-gate 2650*7c478bd9Sstevel@tonic-gate now = time(NULL); 2651*7c478bd9Sstevel@tonic-gate assert(now != -1); 2652*7c478bd9Sstevel@tonic-gate 2653*7c478bd9Sstevel@tonic-gate /* 2654*7c478bd9Sstevel@tonic-gate * opt_mode is the mode of operation. 0 for plain, 'd' for 2655*7c478bd9Sstevel@tonic-gate * dependencies, 'D' for dependents, and 'l' for detailed (long). We 2656*7c478bd9Sstevel@tonic-gate * need to know now so we know which options are valid. 2657*7c478bd9Sstevel@tonic-gate */ 2658*7c478bd9Sstevel@tonic-gate opt_mode = 0; 2659*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, options)) != -1) { 2660*7c478bd9Sstevel@tonic-gate switch (opt) { 2661*7c478bd9Sstevel@tonic-gate case '?': 2662*7c478bd9Sstevel@tonic-gate if (optopt == '?') { 2663*7c478bd9Sstevel@tonic-gate print_help(progname); 2664*7c478bd9Sstevel@tonic-gate return (UU_EXIT_OK); 2665*7c478bd9Sstevel@tonic-gate } else { 2666*7c478bd9Sstevel@tonic-gate argserr(progname); 2667*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2668*7c478bd9Sstevel@tonic-gate } 2669*7c478bd9Sstevel@tonic-gate 2670*7c478bd9Sstevel@tonic-gate case 'd': 2671*7c478bd9Sstevel@tonic-gate case 'D': 2672*7c478bd9Sstevel@tonic-gate case 'l': 2673*7c478bd9Sstevel@tonic-gate if (opt_mode != 0) 2674*7c478bd9Sstevel@tonic-gate argserr(progname); 2675*7c478bd9Sstevel@tonic-gate 2676*7c478bd9Sstevel@tonic-gate opt_mode = opt; 2677*7c478bd9Sstevel@tonic-gate break; 2678*7c478bd9Sstevel@tonic-gate 2679*7c478bd9Sstevel@tonic-gate case 'x': 2680*7c478bd9Sstevel@tonic-gate if (opt_mode != 0) 2681*7c478bd9Sstevel@tonic-gate argserr(progname); 2682*7c478bd9Sstevel@tonic-gate 2683*7c478bd9Sstevel@tonic-gate opt_mode = opt; 2684*7c478bd9Sstevel@tonic-gate break; 2685*7c478bd9Sstevel@tonic-gate 2686*7c478bd9Sstevel@tonic-gate default: 2687*7c478bd9Sstevel@tonic-gate break; 2688*7c478bd9Sstevel@tonic-gate } 2689*7c478bd9Sstevel@tonic-gate } 2690*7c478bd9Sstevel@tonic-gate 2691*7c478bd9Sstevel@tonic-gate sortkey_sz = 0; 2692*7c478bd9Sstevel@tonic-gate 2693*7c478bd9Sstevel@tonic-gate optind = 1; /* Reset getopt() */ 2694*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, options)) != -1) { 2695*7c478bd9Sstevel@tonic-gate switch (opt) { 2696*7c478bd9Sstevel@tonic-gate case 'a': 2697*7c478bd9Sstevel@tonic-gate if (opt_mode != 0) 2698*7c478bd9Sstevel@tonic-gate argserr(progname); 2699*7c478bd9Sstevel@tonic-gate show_all = 1; 2700*7c478bd9Sstevel@tonic-gate break; 2701*7c478bd9Sstevel@tonic-gate 2702*7c478bd9Sstevel@tonic-gate case 'H': 2703*7c478bd9Sstevel@tonic-gate if (opt_mode == 'l' || opt_mode == 'x') 2704*7c478bd9Sstevel@tonic-gate argserr(progname); 2705*7c478bd9Sstevel@tonic-gate show_header = 0; 2706*7c478bd9Sstevel@tonic-gate break; 2707*7c478bd9Sstevel@tonic-gate 2708*7c478bd9Sstevel@tonic-gate case 'p': 2709*7c478bd9Sstevel@tonic-gate if (opt_mode == 'x') 2710*7c478bd9Sstevel@tonic-gate argserr(progname); 2711*7c478bd9Sstevel@tonic-gate opt_processes = 1; 2712*7c478bd9Sstevel@tonic-gate break; 2713*7c478bd9Sstevel@tonic-gate 2714*7c478bd9Sstevel@tonic-gate case 'v': 2715*7c478bd9Sstevel@tonic-gate if (opt_mode == 'l') 2716*7c478bd9Sstevel@tonic-gate argserr(progname); 2717*7c478bd9Sstevel@tonic-gate opt_verbose = 1; 2718*7c478bd9Sstevel@tonic-gate break; 2719*7c478bd9Sstevel@tonic-gate 2720*7c478bd9Sstevel@tonic-gate case 'o': 2721*7c478bd9Sstevel@tonic-gate if (opt_mode == 'l' || opt_mode == 'x') 2722*7c478bd9Sstevel@tonic-gate argserr(progname); 2723*7c478bd9Sstevel@tonic-gate columns_str = optarg; 2724*7c478bd9Sstevel@tonic-gate break; 2725*7c478bd9Sstevel@tonic-gate 2726*7c478bd9Sstevel@tonic-gate case 'R': 2727*7c478bd9Sstevel@tonic-gate if (opt_mode != 0 || opt_mode == 'x') 2728*7c478bd9Sstevel@tonic-gate argserr(progname); 2729*7c478bd9Sstevel@tonic-gate 2730*7c478bd9Sstevel@tonic-gate add_restarter(optarg); 2731*7c478bd9Sstevel@tonic-gate break; 2732*7c478bd9Sstevel@tonic-gate 2733*7c478bd9Sstevel@tonic-gate case 's': 2734*7c478bd9Sstevel@tonic-gate case 'S': 2735*7c478bd9Sstevel@tonic-gate if (opt_mode != 0) 2736*7c478bd9Sstevel@tonic-gate argserr(progname); 2737*7c478bd9Sstevel@tonic-gate 2738*7c478bd9Sstevel@tonic-gate add_sort_column(optarg, optopt == 'S'); 2739*7c478bd9Sstevel@tonic-gate break; 2740*7c478bd9Sstevel@tonic-gate 2741*7c478bd9Sstevel@tonic-gate case 'd': 2742*7c478bd9Sstevel@tonic-gate case 'D': 2743*7c478bd9Sstevel@tonic-gate case 'l': 2744*7c478bd9Sstevel@tonic-gate case 'x': 2745*7c478bd9Sstevel@tonic-gate assert(opt_mode == optopt); 2746*7c478bd9Sstevel@tonic-gate break; 2747*7c478bd9Sstevel@tonic-gate 2748*7c478bd9Sstevel@tonic-gate case '?': 2749*7c478bd9Sstevel@tonic-gate argserr(progname); 2750*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2751*7c478bd9Sstevel@tonic-gate 2752*7c478bd9Sstevel@tonic-gate default: 2753*7c478bd9Sstevel@tonic-gate assert(0); 2754*7c478bd9Sstevel@tonic-gate abort(); 2755*7c478bd9Sstevel@tonic-gate } 2756*7c478bd9Sstevel@tonic-gate } 2757*7c478bd9Sstevel@tonic-gate 2758*7c478bd9Sstevel@tonic-gate /* 2759*7c478bd9Sstevel@tonic-gate * -a is only meaningful when given no arguments 2760*7c478bd9Sstevel@tonic-gate */ 2761*7c478bd9Sstevel@tonic-gate if (show_all && optind != argc) 2762*7c478bd9Sstevel@tonic-gate uu_warn(gettext("-a ignored when used with arguments.\n")); 2763*7c478bd9Sstevel@tonic-gate 2764*7c478bd9Sstevel@tonic-gate h = scf_handle_create(SCF_VERSION); 2765*7c478bd9Sstevel@tonic-gate if (h == NULL) 2766*7c478bd9Sstevel@tonic-gate scfdie(); 2767*7c478bd9Sstevel@tonic-gate 2768*7c478bd9Sstevel@tonic-gate if (scf_handle_bind(h) == -1) 2769*7c478bd9Sstevel@tonic-gate uu_die(gettext("Could not bind to repository server: %s. " 2770*7c478bd9Sstevel@tonic-gate "Exiting.\n"), scf_strerror(scf_error())); 2771*7c478bd9Sstevel@tonic-gate 2772*7c478bd9Sstevel@tonic-gate if ((g_pg = scf_pg_create(h)) == NULL || 2773*7c478bd9Sstevel@tonic-gate (g_prop = scf_property_create(h)) == NULL || 2774*7c478bd9Sstevel@tonic-gate (g_val = scf_value_create(h)) == NULL) 2775*7c478bd9Sstevel@tonic-gate scfdie(); 2776*7c478bd9Sstevel@tonic-gate 2777*7c478bd9Sstevel@tonic-gate argc -= optind; 2778*7c478bd9Sstevel@tonic-gate argv += optind; 2779*7c478bd9Sstevel@tonic-gate 2780*7c478bd9Sstevel@tonic-gate /* 2781*7c478bd9Sstevel@tonic-gate * If we're in long mode, take care of it now before we deal with the 2782*7c478bd9Sstevel@tonic-gate * sorting and the columns, since we won't use them anyway. 2783*7c478bd9Sstevel@tonic-gate */ 2784*7c478bd9Sstevel@tonic-gate if (opt_mode == 'l') { 2785*7c478bd9Sstevel@tonic-gate if (argc == 0) 2786*7c478bd9Sstevel@tonic-gate argserr(progname); 2787*7c478bd9Sstevel@tonic-gate 2788*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc, argv, SCF_WALK_MULTIPLE, 2789*7c478bd9Sstevel@tonic-gate print_detailed, NULL, &exit_status, uu_warn)) != 0) { 2790*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2791*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2792*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2793*7c478bd9Sstevel@tonic-gate } 2794*7c478bd9Sstevel@tonic-gate 2795*7c478bd9Sstevel@tonic-gate return (exit_status); 2796*7c478bd9Sstevel@tonic-gate } 2797*7c478bd9Sstevel@tonic-gate 2798*7c478bd9Sstevel@tonic-gate if (opt_mode == 'x') { 2799*7c478bd9Sstevel@tonic-gate explain(opt_verbose, argc, argv); 2800*7c478bd9Sstevel@tonic-gate 2801*7c478bd9Sstevel@tonic-gate return (exit_status); 2802*7c478bd9Sstevel@tonic-gate } 2803*7c478bd9Sstevel@tonic-gate 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate if (opt_snum == 0) { 2806*7c478bd9Sstevel@tonic-gate /* Default sort. */ 2807*7c478bd9Sstevel@tonic-gate add_sort_column("state", 0); 2808*7c478bd9Sstevel@tonic-gate add_sort_column("stime", 0); 2809*7c478bd9Sstevel@tonic-gate add_sort_column("fmri", 0); 2810*7c478bd9Sstevel@tonic-gate } 2811*7c478bd9Sstevel@tonic-gate 2812*7c478bd9Sstevel@tonic-gate if (columns_str == NULL) { 2813*7c478bd9Sstevel@tonic-gate if (!opt_verbose) 2814*7c478bd9Sstevel@tonic-gate columns_str = safe_strdup("state,stime,fmri"); 2815*7c478bd9Sstevel@tonic-gate else 2816*7c478bd9Sstevel@tonic-gate columns_str = 2817*7c478bd9Sstevel@tonic-gate safe_strdup("state,nstate,stime,ctid,fmri"); 2818*7c478bd9Sstevel@tonic-gate } 2819*7c478bd9Sstevel@tonic-gate 2820*7c478bd9Sstevel@tonic-gate /* Decode columns_str into opt_columns. */ 2821*7c478bd9Sstevel@tonic-gate line_sz = 0; 2822*7c478bd9Sstevel@tonic-gate 2823*7c478bd9Sstevel@tonic-gate opt_cnum = 1; 2824*7c478bd9Sstevel@tonic-gate for (cp = columns_str; *cp != '\0'; ++cp) 2825*7c478bd9Sstevel@tonic-gate if (*cp == ',') 2826*7c478bd9Sstevel@tonic-gate ++opt_cnum; 2827*7c478bd9Sstevel@tonic-gate 2828*7c478bd9Sstevel@tonic-gate opt_columns = malloc(opt_cnum * sizeof (*opt_columns)); 2829*7c478bd9Sstevel@tonic-gate if (opt_columns == NULL) 2830*7c478bd9Sstevel@tonic-gate uu_die(gettext("Too many columns.\n")); 2831*7c478bd9Sstevel@tonic-gate 2832*7c478bd9Sstevel@tonic-gate for (n = 0; *columns_str != '\0'; ++n) { 2833*7c478bd9Sstevel@tonic-gate i = getcolumnopt(&columns_str); 2834*7c478bd9Sstevel@tonic-gate if (i == -1) 2835*7c478bd9Sstevel@tonic-gate uu_die(gettext("Unknown column \"%s\".\n"), 2836*7c478bd9Sstevel@tonic-gate columns_str); 2837*7c478bd9Sstevel@tonic-gate 2838*7c478bd9Sstevel@tonic-gate if (strcmp(columns[i].name, "N") == 0 || 2839*7c478bd9Sstevel@tonic-gate strcmp(columns[i].name, "SN") == 0 || 2840*7c478bd9Sstevel@tonic-gate strcmp(columns[i].name, "NSTA") == 0 || 2841*7c478bd9Sstevel@tonic-gate strcmp(columns[i].name, "NSTATE") == 0) 2842*7c478bd9Sstevel@tonic-gate opt_nstate_shown = 1; 2843*7c478bd9Sstevel@tonic-gate 2844*7c478bd9Sstevel@tonic-gate opt_columns[n] = i; 2845*7c478bd9Sstevel@tonic-gate line_sz += columns[i].width + 1; 2846*7c478bd9Sstevel@tonic-gate } 2847*7c478bd9Sstevel@tonic-gate 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate if ((lines_pool = uu_avl_pool_create("lines_pool", 2850*7c478bd9Sstevel@tonic-gate sizeof (struct avl_string), offsetof(struct avl_string, node), 2851*7c478bd9Sstevel@tonic-gate line_cmp, UU_AVL_DEBUG)) == NULL || 2852*7c478bd9Sstevel@tonic-gate (lines = uu_avl_create(lines_pool, NULL, 0)) == NULL) 2853*7c478bd9Sstevel@tonic-gate uu_die(gettext("Unexpected libuutil error: %s. Exiting.\n"), 2854*7c478bd9Sstevel@tonic-gate uu_strerror(uu_error())); 2855*7c478bd9Sstevel@tonic-gate 2856*7c478bd9Sstevel@tonic-gate switch (opt_mode) { 2857*7c478bd9Sstevel@tonic-gate case 0: 2858*7c478bd9Sstevel@tonic-gate ht_init(); 2859*7c478bd9Sstevel@tonic-gate 2860*7c478bd9Sstevel@tonic-gate /* Always show all FMRIs when given arguments or restarters */ 2861*7c478bd9Sstevel@tonic-gate if (argc != 0 || restarters != NULL) 2862*7c478bd9Sstevel@tonic-gate show_all = 1; 2863*7c478bd9Sstevel@tonic-gate 2864*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc, argv, 2865*7c478bd9Sstevel@tonic-gate SCF_WALK_MULTIPLE | SCF_WALK_LEGACY, 2866*7c478bd9Sstevel@tonic-gate show_all ? list_instance : list_if_enabled, NULL, 2867*7c478bd9Sstevel@tonic-gate &exit_status, uu_warn)) != 0) { 2868*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2869*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2870*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2871*7c478bd9Sstevel@tonic-gate } 2872*7c478bd9Sstevel@tonic-gate break; 2873*7c478bd9Sstevel@tonic-gate 2874*7c478bd9Sstevel@tonic-gate case 'd': 2875*7c478bd9Sstevel@tonic-gate if (argc == 0) 2876*7c478bd9Sstevel@tonic-gate argserr(progname); 2877*7c478bd9Sstevel@tonic-gate 2878*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc, argv, 2879*7c478bd9Sstevel@tonic-gate SCF_WALK_MULTIPLE, list_dependencies, NULL, 2880*7c478bd9Sstevel@tonic-gate &exit_status, uu_warn)) != 0) { 2881*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2882*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2883*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2884*7c478bd9Sstevel@tonic-gate } 2885*7c478bd9Sstevel@tonic-gate break; 2886*7c478bd9Sstevel@tonic-gate 2887*7c478bd9Sstevel@tonic-gate case 'D': 2888*7c478bd9Sstevel@tonic-gate if (argc == 0) 2889*7c478bd9Sstevel@tonic-gate argserr(progname); 2890*7c478bd9Sstevel@tonic-gate 2891*7c478bd9Sstevel@tonic-gate provider_scope = safe_malloc(max_scf_fmri_length); 2892*7c478bd9Sstevel@tonic-gate provider_svc = safe_malloc(max_scf_fmri_length); 2893*7c478bd9Sstevel@tonic-gate provider_inst = safe_malloc(max_scf_fmri_length); 2894*7c478bd9Sstevel@tonic-gate 2895*7c478bd9Sstevel@tonic-gate if ((err = scf_walk_fmri(h, argc, argv, 2896*7c478bd9Sstevel@tonic-gate SCF_WALK_MULTIPLE | SCF_WALK_SERVICE, 2897*7c478bd9Sstevel@tonic-gate list_dependents, NULL, &exit_status, uu_warn)) != 0) { 2898*7c478bd9Sstevel@tonic-gate uu_warn(gettext("failed to iterate over " 2899*7c478bd9Sstevel@tonic-gate "instances: %s\n"), scf_strerror(err)); 2900*7c478bd9Sstevel@tonic-gate exit_status = UU_EXIT_FATAL; 2901*7c478bd9Sstevel@tonic-gate } 2902*7c478bd9Sstevel@tonic-gate 2903*7c478bd9Sstevel@tonic-gate free(provider_scope); 2904*7c478bd9Sstevel@tonic-gate free(provider_svc); 2905*7c478bd9Sstevel@tonic-gate free(provider_inst); 2906*7c478bd9Sstevel@tonic-gate break; 2907*7c478bd9Sstevel@tonic-gate 2908*7c478bd9Sstevel@tonic-gate default: 2909*7c478bd9Sstevel@tonic-gate assert(0); 2910*7c478bd9Sstevel@tonic-gate abort(); 2911*7c478bd9Sstevel@tonic-gate } 2912*7c478bd9Sstevel@tonic-gate 2913*7c478bd9Sstevel@tonic-gate if (show_header) 2914*7c478bd9Sstevel@tonic-gate print_header(); 2915*7c478bd9Sstevel@tonic-gate 2916*7c478bd9Sstevel@tonic-gate (void) uu_avl_walk(lines, print_line, NULL, 0); 2917*7c478bd9Sstevel@tonic-gate 2918*7c478bd9Sstevel@tonic-gate return (exit_status); 2919*7c478bd9Sstevel@tonic-gate } 2920