xref: /illumos-gate/usr/src/cmd/ctstat/ctstat.c (revision f76de749)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57b209c2cSacruz  * Common Development and Distribution License (the "License").
67b209c2cSacruz  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*f76de749SStephen Hanson  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <sys/types.h>
267c478bd9Sstevel@tonic-gate #include <sys/ctfs.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <unistd.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <errno.h>
337c478bd9Sstevel@tonic-gate #include <libuutil.h>
347c478bd9Sstevel@tonic-gate #include <sys/contract/process.h>
35*f76de749SStephen Hanson #include <sys/contract/device.h>
367c478bd9Sstevel@tonic-gate #include <limits.h>
377c478bd9Sstevel@tonic-gate #include <libcontract.h>
387c478bd9Sstevel@tonic-gate #include <libcontract_priv.h>
397c478bd9Sstevel@tonic-gate #include <dirent.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include <locale.h>
427c478bd9Sstevel@tonic-gate #include <langinfo.h>
437c478bd9Sstevel@tonic-gate 
4426fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h"
4526fd7700SKrishnendu Sadhukhan - Sun Microsystems 
4626fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE;
4726fd7700SKrishnendu Sadhukhan - Sun Microsystems 
487c478bd9Sstevel@tonic-gate static int opt_verbose = 0;
497c478bd9Sstevel@tonic-gate static int opt_showall = 0;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate  * usage
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * Educate the user.
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate static void
usage(void)577c478bd9Sstevel@tonic-gate usage(void)
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Usage: %s [-a] [-i ctidlist] "
6026fd7700SKrishnendu Sadhukhan - Sun Microsystems 	    "[-t typelist] [-T d|u] [-v] [interval [count]]\n"), uu_getpname());
617c478bd9Sstevel@tonic-gate 	exit(UU_EXIT_USAGE);
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * mystrtoul
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * Convert a string into an int in [0, INT_MAX].  Exit if the argument
687c478bd9Sstevel@tonic-gate  * doen't fit this description.
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate static int
mystrtoul(const char * arg)717c478bd9Sstevel@tonic-gate mystrtoul(const char *arg)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate 	unsigned int result;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	if (uu_strtoint(arg, &result, sizeof (result), 10, 0, INT_MAX) == -1) {
767c478bd9Sstevel@tonic-gate 		uu_warn(gettext("invalid numerical argument \"%s\"\n"), arg);
777c478bd9Sstevel@tonic-gate 		usage();
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	return (result);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * int_compar
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  * A simple integer comparator.  Also used for id_ts, since they're the
877c478bd9Sstevel@tonic-gate  * same thing.
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate static int
int_compar(const void * a1,const void * a2)907c478bd9Sstevel@tonic-gate int_compar(const void *a1, const void *a2)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	int id1 = *(int *)a1;
937c478bd9Sstevel@tonic-gate 	int id2 = *(int *)a2;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	if (id1 > id2)
967c478bd9Sstevel@tonic-gate 		return (1);
977c478bd9Sstevel@tonic-gate 	if (id2 > id1)
987c478bd9Sstevel@tonic-gate 		return (-1);
997c478bd9Sstevel@tonic-gate 	return (0);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate typedef struct optvect {
1037c478bd9Sstevel@tonic-gate 	const char	*option;
1047c478bd9Sstevel@tonic-gate 	uint_t		bit;
1057c478bd9Sstevel@tonic-gate } optvect_t;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate static optvect_t option_params[] = {
1087c478bd9Sstevel@tonic-gate 	{ "inherit", CT_PR_INHERIT },
1097c478bd9Sstevel@tonic-gate 	{ "noorphan", CT_PR_NOORPHAN },
1107c478bd9Sstevel@tonic-gate 	{ "pgrponly", CT_PR_PGRPONLY },
1117c478bd9Sstevel@tonic-gate 	{ "regent", CT_PR_REGENT },
1127c478bd9Sstevel@tonic-gate 	{ NULL }
1137c478bd9Sstevel@tonic-gate };
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static optvect_t option_events[] = {
1167c478bd9Sstevel@tonic-gate 	{ "core", CT_PR_EV_CORE },
1177c478bd9Sstevel@tonic-gate 	{ "signal", CT_PR_EV_SIGNAL },
1187c478bd9Sstevel@tonic-gate 	{ "hwerr", CT_PR_EV_HWERR },
1197c478bd9Sstevel@tonic-gate 	{ "empty", CT_PR_EV_EMPTY },
1207c478bd9Sstevel@tonic-gate 	{ "fork", CT_PR_EV_FORK },
1217c478bd9Sstevel@tonic-gate 	{ "exit", CT_PR_EV_EXIT },
1227c478bd9Sstevel@tonic-gate 	{ NULL }
1237c478bd9Sstevel@tonic-gate };
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * print_bits
1277c478bd9Sstevel@tonic-gate  *
1287c478bd9Sstevel@tonic-gate  * Display a set whose membership is identified by a bitfield.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate static void
print_bits(uint_t bits,optvect_t * desc)1317c478bd9Sstevel@tonic-gate print_bits(uint_t bits, optvect_t *desc)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	int i, printed = 0;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	for (i = 0; desc[i].option; i++)
1367c478bd9Sstevel@tonic-gate 		if (desc[i].bit & bits) {
1377c478bd9Sstevel@tonic-gate 			if (printed)
1387c478bd9Sstevel@tonic-gate 				(void) putchar(' ');
1397c478bd9Sstevel@tonic-gate 			printed = 1;
1407c478bd9Sstevel@tonic-gate 			(void) fputs(desc[i].option, stdout);
1417c478bd9Sstevel@tonic-gate 		}
1427c478bd9Sstevel@tonic-gate 	if (printed)
1437c478bd9Sstevel@tonic-gate 		(void) putchar('\n');
1447c478bd9Sstevel@tonic-gate 	else
1457c478bd9Sstevel@tonic-gate 		(void) puts("none");
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate  * print_ids
1507c478bd9Sstevel@tonic-gate  *
1517c478bd9Sstevel@tonic-gate  * Display a list of ids, sorted.
1527c478bd9Sstevel@tonic-gate  */
1537c478bd9Sstevel@tonic-gate static void
print_ids(id_t * ids,uint_t nids)1547c478bd9Sstevel@tonic-gate print_ids(id_t *ids, uint_t nids)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate 	int i;
1577c478bd9Sstevel@tonic-gate 	int first = 1;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	qsort(ids, nids, sizeof (int), int_compar);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	for (i = 0; i < nids; i++) {
1627c478bd9Sstevel@tonic-gate 		/*LINTED*/
1637c478bd9Sstevel@tonic-gate 		(void) printf(" %d" + first, ids[i]);
1647c478bd9Sstevel@tonic-gate 		first = 0;
1657c478bd9Sstevel@tonic-gate 	}
1667c478bd9Sstevel@tonic-gate 	if (first)
1677c478bd9Sstevel@tonic-gate 		(void) puts("none");
1687c478bd9Sstevel@tonic-gate 	else
1697c478bd9Sstevel@tonic-gate 		(void) putchar('\n');
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate typedef void printfunc_t(ct_stathdl_t);
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate  * A structure defining a displayed field.  Includes a label to be
1767c478bd9Sstevel@tonic-gate  * printed along side the field value, and a function which extracts
1777c478bd9Sstevel@tonic-gate  * the data from a status structure, formats it, and displays it on
1787c478bd9Sstevel@tonic-gate  * stdout.
1797c478bd9Sstevel@tonic-gate  */
1807c478bd9Sstevel@tonic-gate typedef struct verbout {
1817c478bd9Sstevel@tonic-gate 	const char	*label;	/* field label */
1827c478bd9Sstevel@tonic-gate 	printfunc_t	*func;	/* field display function */
1837c478bd9Sstevel@tonic-gate } verbout_t;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * verb_cookie
1877c478bd9Sstevel@tonic-gate  *
1887c478bd9Sstevel@tonic-gate  * Used to display an error encountered when reading a contract status
1897c478bd9Sstevel@tonic-gate  * field.
1907c478bd9Sstevel@tonic-gate  */
1917c478bd9Sstevel@tonic-gate static void
verb_error(int err)1927c478bd9Sstevel@tonic-gate verb_error(int err)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	(void) printf("(error: %s)\n", strerror(err));
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * verb_cookie
1997c478bd9Sstevel@tonic-gate  *
2007c478bd9Sstevel@tonic-gate  * Display the contract's cookie.
2017c478bd9Sstevel@tonic-gate  */
2027c478bd9Sstevel@tonic-gate static void
verb_cookie(ct_stathdl_t hdl)2037c478bd9Sstevel@tonic-gate verb_cookie(ct_stathdl_t hdl)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	(void) printf("%#llx\n", ct_status_get_cookie(hdl));
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate  * verb_info
2107c478bd9Sstevel@tonic-gate  *
2117c478bd9Sstevel@tonic-gate  * Display the parameters in the parameter set.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate static void
verb_param(ct_stathdl_t hdl)2147c478bd9Sstevel@tonic-gate verb_param(ct_stathdl_t hdl)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	uint_t param;
2177c478bd9Sstevel@tonic-gate 	int err;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if (err = ct_pr_status_get_param(hdl, &param))
2207c478bd9Sstevel@tonic-gate 		verb_error(err);
2217c478bd9Sstevel@tonic-gate 	else
2227c478bd9Sstevel@tonic-gate 		print_bits(param, option_params);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * verb_info
2277c478bd9Sstevel@tonic-gate  *
2287c478bd9Sstevel@tonic-gate  * Display the events in the informative event set.
2297c478bd9Sstevel@tonic-gate  */
2307c478bd9Sstevel@tonic-gate static void
verb_info(ct_stathdl_t hdl)2317c478bd9Sstevel@tonic-gate verb_info(ct_stathdl_t hdl)
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate 	print_bits(ct_status_get_informative(hdl), option_events);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate  * verb_crit
2387c478bd9Sstevel@tonic-gate  *
2397c478bd9Sstevel@tonic-gate  * Display the events in the critical event set.
2407c478bd9Sstevel@tonic-gate  */
2417c478bd9Sstevel@tonic-gate static void
verb_crit(ct_stathdl_t hdl)2427c478bd9Sstevel@tonic-gate verb_crit(ct_stathdl_t hdl)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate 	print_bits(ct_status_get_critical(hdl), option_events);
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate 
247*f76de749SStephen Hanson /*
248*f76de749SStephen Hanson  * verb_minor
249*f76de749SStephen Hanson  *
250*f76de749SStephen Hanson  * Display the minor device
251*f76de749SStephen Hanson  */
252*f76de749SStephen Hanson static void
verb_minor(ct_stathdl_t hdl)253*f76de749SStephen Hanson verb_minor(ct_stathdl_t hdl)
254*f76de749SStephen Hanson {
255*f76de749SStephen Hanson 	int err;
256*f76de749SStephen Hanson 	char *buf;
257*f76de749SStephen Hanson 
258*f76de749SStephen Hanson 	if (err = ct_dev_status_get_minor(hdl, &buf))
259*f76de749SStephen Hanson 		verb_error(err);
260*f76de749SStephen Hanson 	else
261*f76de749SStephen Hanson 		(void) printf("%s\n", buf);
262*f76de749SStephen Hanson }
263*f76de749SStephen Hanson 
264*f76de749SStephen Hanson /*
265*f76de749SStephen Hanson  * verb_state
266*f76de749SStephen Hanson  *
267*f76de749SStephen Hanson  * Display the state of the device
268*f76de749SStephen Hanson  */
269*f76de749SStephen Hanson static void
verb_dev_state(ct_stathdl_t hdl)270*f76de749SStephen Hanson verb_dev_state(ct_stathdl_t hdl)
271*f76de749SStephen Hanson {
272*f76de749SStephen Hanson 	int err;
273*f76de749SStephen Hanson 	uint_t state;
274*f76de749SStephen Hanson 
275*f76de749SStephen Hanson 	if (err = ct_dev_status_get_dev_state(hdl, &state))
276*f76de749SStephen Hanson 		verb_error(err);
277*f76de749SStephen Hanson 	else
278*f76de749SStephen Hanson 		(void) printf("%s\n", state == CT_DEV_EV_ONLINE ? "online" :
279*f76de749SStephen Hanson 		    state == CT_DEV_EV_DEGRADED ? "degraded" : "offline");
280*f76de749SStephen Hanson }
281*f76de749SStephen Hanson 
2827c478bd9Sstevel@tonic-gate /*
2837c478bd9Sstevel@tonic-gate  * verb_fatal
2847c478bd9Sstevel@tonic-gate  *
2857c478bd9Sstevel@tonic-gate  * Display the events in the fatal event set.
2867c478bd9Sstevel@tonic-gate  */
2877c478bd9Sstevel@tonic-gate static void
verb_fatal(ct_stathdl_t hdl)2887c478bd9Sstevel@tonic-gate verb_fatal(ct_stathdl_t hdl)
2897c478bd9Sstevel@tonic-gate {
2907c478bd9Sstevel@tonic-gate 	uint_t event;
2917c478bd9Sstevel@tonic-gate 	int err;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	if (err = ct_pr_status_get_fatal(hdl, &event))
2947c478bd9Sstevel@tonic-gate 		verb_error(err);
2957c478bd9Sstevel@tonic-gate 	else
2967c478bd9Sstevel@tonic-gate 		print_bits(event, option_events);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate  * verb_members
3017c478bd9Sstevel@tonic-gate  *
3027c478bd9Sstevel@tonic-gate  * Display the list of member contracts.
3037c478bd9Sstevel@tonic-gate  */
3047c478bd9Sstevel@tonic-gate static void
verb_members(ct_stathdl_t hdl)3057c478bd9Sstevel@tonic-gate verb_members(ct_stathdl_t hdl)
3067c478bd9Sstevel@tonic-gate {
3077c478bd9Sstevel@tonic-gate 	pid_t *pids;
3087c478bd9Sstevel@tonic-gate 	uint_t npids;
3097c478bd9Sstevel@tonic-gate 	int err;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	if (err = ct_pr_status_get_members(hdl, &pids, &npids)) {
3127c478bd9Sstevel@tonic-gate 		verb_error(err);
3137c478bd9Sstevel@tonic-gate 		return;
3147c478bd9Sstevel@tonic-gate 	}
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	print_ids(pids, npids);
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate  * verb_inherit
3217c478bd9Sstevel@tonic-gate  *
3227c478bd9Sstevel@tonic-gate  * Display the list of inherited contracts.
3237c478bd9Sstevel@tonic-gate  */
3247c478bd9Sstevel@tonic-gate static void
verb_inherit(ct_stathdl_t hdl)3257c478bd9Sstevel@tonic-gate verb_inherit(ct_stathdl_t hdl)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate 	ctid_t *ctids;
3287c478bd9Sstevel@tonic-gate 	uint_t nctids;
3297c478bd9Sstevel@tonic-gate 	int err;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	if (err = ct_pr_status_get_contracts(hdl, &ctids, &nctids))
3327c478bd9Sstevel@tonic-gate 		verb_error(err);
3337c478bd9Sstevel@tonic-gate 	else
3347c478bd9Sstevel@tonic-gate 		print_ids(ctids, nctids);
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377b209c2cSacruz /*
3387b209c2cSacruz  * verb_svc_fmri
3397b209c2cSacruz  *
3407b209c2cSacruz  * Display the process contract service fmri
3417b209c2cSacruz  */
3427b209c2cSacruz static void
verb_svc_fmri(ct_stathdl_t hdl)3437b209c2cSacruz verb_svc_fmri(ct_stathdl_t hdl)
3447b209c2cSacruz {
3457b209c2cSacruz 	char *svc_fmri;
3467b209c2cSacruz 	int err;
3477b209c2cSacruz 	if (err = ct_pr_status_get_svc_fmri(hdl, &svc_fmri))
3487b209c2cSacruz 		verb_error(err);
3497b209c2cSacruz 	else
3507b209c2cSacruz 		(void) printf("%s\n", svc_fmri);
3517b209c2cSacruz }
3527b209c2cSacruz 
3537b209c2cSacruz /*
3547b209c2cSacruz  * verb_svc_aux
3557b209c2cSacruz  *
3567b209c2cSacruz  * Display the process contract service fmri auxiliar
3577b209c2cSacruz  */
3587b209c2cSacruz static void
verb_svc_aux(ct_stathdl_t hdl)3597b209c2cSacruz verb_svc_aux(ct_stathdl_t hdl)
3607b209c2cSacruz {
3617b209c2cSacruz 	char *svc_aux;
3627b209c2cSacruz 	int err;
3637b209c2cSacruz 	if (err = ct_pr_status_get_svc_aux(hdl, &svc_aux))
3647b209c2cSacruz 		verb_error(err);
3657b209c2cSacruz 	else
3667b209c2cSacruz 		(void) printf("%s\n", svc_aux);
3677b209c2cSacruz }
3687b209c2cSacruz 
3697b209c2cSacruz /*
3707b209c2cSacruz  * verb_svc_ctid
3717b209c2cSacruz  *
3727b209c2cSacruz  * Display the process contract service fmri ctid
3737b209c2cSacruz  */
3747b209c2cSacruz static void
verb_svc_ctid(ct_stathdl_t hdl)3757b209c2cSacruz verb_svc_ctid(ct_stathdl_t hdl)
3767b209c2cSacruz {
3777b209c2cSacruz 	ctid_t svc_ctid;
3787b209c2cSacruz 	int err;
3797b209c2cSacruz 	if (err = ct_pr_status_get_svc_ctid(hdl, &svc_ctid))
3807b209c2cSacruz 		verb_error(err);
3817b209c2cSacruz 	else
3827b209c2cSacruz 		(void) printf("%ld\n", svc_ctid);
3837b209c2cSacruz }
3847b209c2cSacruz 
3857b209c2cSacruz /*
3867b209c2cSacruz  * verb_svc_creator
3877b209c2cSacruz  *
3887b209c2cSacruz  * Display the process contract creator's execname
3897b209c2cSacruz  */
3907b209c2cSacruz static void
verb_svc_creator(ct_stathdl_t hdl)3917b209c2cSacruz verb_svc_creator(ct_stathdl_t hdl)
3927b209c2cSacruz {
3937b209c2cSacruz 	char *svc_creator;
3947b209c2cSacruz 	int err;
3957b209c2cSacruz 	if (err = ct_pr_status_get_svc_creator(hdl, &svc_creator))
3967b209c2cSacruz 		verb_error(err);
3977b209c2cSacruz 	else
3987b209c2cSacruz 		(void) printf("%s\n", svc_creator);
3997b209c2cSacruz }
4007b209c2cSacruz 
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate  * Common contract status fields.
4037c478bd9Sstevel@tonic-gate  */
4047c478bd9Sstevel@tonic-gate static verbout_t vcommon[] = {
4057c478bd9Sstevel@tonic-gate 	"cookie", verb_cookie,
4067c478bd9Sstevel@tonic-gate 	NULL,
4077c478bd9Sstevel@tonic-gate };
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate  * Process contract-specific status fields.
4117c478bd9Sstevel@tonic-gate  * The critical and informative event sets are here because the event
4127c478bd9Sstevel@tonic-gate  * names are contract-specific.  They are listed first, however, so
4137c478bd9Sstevel@tonic-gate  * they are displayed adjacent to the "normal" common output.
4147c478bd9Sstevel@tonic-gate  */
4157c478bd9Sstevel@tonic-gate static verbout_t vprocess[] = {
4167c478bd9Sstevel@tonic-gate 	"informative event set", verb_info,
4177c478bd9Sstevel@tonic-gate 	"critical event set", verb_crit,
4187c478bd9Sstevel@tonic-gate 	"fatal event set", verb_fatal,
4197c478bd9Sstevel@tonic-gate 	"parameter set", verb_param,
4207c478bd9Sstevel@tonic-gate 	"member processes", verb_members,
4217c478bd9Sstevel@tonic-gate 	"inherited contracts", verb_inherit,
4227b209c2cSacruz 	"service fmri", verb_svc_fmri,
4237b209c2cSacruz 	"service fmri ctid", verb_svc_ctid,
4247b209c2cSacruz 	"creator", verb_svc_creator,
4257b209c2cSacruz 	"aux", verb_svc_aux,
4267c478bd9Sstevel@tonic-gate 	NULL
4277c478bd9Sstevel@tonic-gate };
4287c478bd9Sstevel@tonic-gate 
429*f76de749SStephen Hanson static verbout_t vdevice[] = {
430*f76de749SStephen Hanson 	"device", verb_minor,
431*f76de749SStephen Hanson 	"dev_state", verb_dev_state,
432*f76de749SStephen Hanson 	NULL
433*f76de749SStephen Hanson };
434*f76de749SStephen Hanson 
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate  * print_verbose
4377c478bd9Sstevel@tonic-gate  *
4387c478bd9Sstevel@tonic-gate  * Displays a contract's verbose status, common fields first.
4397c478bd9Sstevel@tonic-gate  */
4407c478bd9Sstevel@tonic-gate static void
print_verbose(ct_stathdl_t hdl,verbout_t * spec,verbout_t * common)4417c478bd9Sstevel@tonic-gate print_verbose(ct_stathdl_t hdl, verbout_t *spec, verbout_t *common)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	int i;
4447c478bd9Sstevel@tonic-gate 	int tmp, maxwidth = 0;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	/*
4477c478bd9Sstevel@tonic-gate 	 * Compute the width of all the fields.
4487c478bd9Sstevel@tonic-gate 	 */
4497c478bd9Sstevel@tonic-gate 	for (i = 0; common[i].label; i++)
4507c478bd9Sstevel@tonic-gate 		if ((tmp = strlen(common[i].label)) > maxwidth)
4517c478bd9Sstevel@tonic-gate 			maxwidth = tmp;
4527c478bd9Sstevel@tonic-gate 	if (spec)
4537c478bd9Sstevel@tonic-gate 		for (i = 0; spec[i].label; i++)
4547c478bd9Sstevel@tonic-gate 			if ((tmp = strlen(spec[i].label)) > maxwidth)
4557c478bd9Sstevel@tonic-gate 				maxwidth = tmp;
4567c478bd9Sstevel@tonic-gate 	maxwidth += 2;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/*
4597c478bd9Sstevel@tonic-gate 	 * Display the data.
4607c478bd9Sstevel@tonic-gate 	 */
4617c478bd9Sstevel@tonic-gate 	for (i = 0; common[i].label; i++) {
4627c478bd9Sstevel@tonic-gate 		tmp = printf("\t%s", common[i].label);
4637c478bd9Sstevel@tonic-gate 		if (tmp < 0)
4647c478bd9Sstevel@tonic-gate 			tmp = 0;
4657c478bd9Sstevel@tonic-gate 		(void) printf("%-*s", maxwidth - tmp + 1, ":");
4667c478bd9Sstevel@tonic-gate 		common[i].func(hdl);
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 	if (spec)
4697c478bd9Sstevel@tonic-gate 		for (i = 0; spec[i].label; i++) {
4707c478bd9Sstevel@tonic-gate 			(void) printf("\t%s%n", spec[i].label, &tmp);
4717c478bd9Sstevel@tonic-gate 			(void) printf("%-*s", maxwidth - tmp + 1, ":");
4727c478bd9Sstevel@tonic-gate 			spec[i].func(hdl);
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate struct {
4777c478bd9Sstevel@tonic-gate 	const char *name;
4787c478bd9Sstevel@tonic-gate 	verbout_t *verbout;
4797c478bd9Sstevel@tonic-gate } cttypes[] = {
4807c478bd9Sstevel@tonic-gate 	{ "process", vprocess },
481*f76de749SStephen Hanson 	{ "device", vdevice },
4827c478bd9Sstevel@tonic-gate 	{ NULL }
4837c478bd9Sstevel@tonic-gate };
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate /*
4867c478bd9Sstevel@tonic-gate  * get_type
4877c478bd9Sstevel@tonic-gate  *
4887c478bd9Sstevel@tonic-gate  * Given a type name, return an index into the above array of types.
4897c478bd9Sstevel@tonic-gate  */
4907c478bd9Sstevel@tonic-gate static int
get_type(const char * typestr)4917c478bd9Sstevel@tonic-gate get_type(const char *typestr)
4927c478bd9Sstevel@tonic-gate {
4937c478bd9Sstevel@tonic-gate 	int i;
4947c478bd9Sstevel@tonic-gate 	for (i = 0; cttypes[i].name; i++)
4957c478bd9Sstevel@tonic-gate 		if (strcmp(cttypes[i].name, typestr) == 0)
4967c478bd9Sstevel@tonic-gate 			return (i);
4977c478bd9Sstevel@tonic-gate 	uu_die(gettext("invalid contract type: %s\n"), typestr);
4987c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate /*
5027c478bd9Sstevel@tonic-gate  * print_header
5037c478bd9Sstevel@tonic-gate  *
5047c478bd9Sstevel@tonic-gate  * Display the status header.
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate static void
print_header(void)5077c478bd9Sstevel@tonic-gate print_header(void)
5087c478bd9Sstevel@tonic-gate {
5097c478bd9Sstevel@tonic-gate 	(void) printf("%-8s%-8s%-8s%-8s%-8s%-8s%-8s%-8s\n", "CTID", "ZONEID",
5107c478bd9Sstevel@tonic-gate 	    "TYPE", "STATE", "HOLDER", "EVENTS", "QTIME", "NTIME");
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate /*
5147c478bd9Sstevel@tonic-gate  * print_contract
5157c478bd9Sstevel@tonic-gate  *
5167c478bd9Sstevel@tonic-gate  * Display status for contract ID 'id' from type directory 'dir'.  If
5177c478bd9Sstevel@tonic-gate  * only contracts of a specific set of types should be displayed,
5187c478bd9Sstevel@tonic-gate  * 'types' will be a sorted list of type indices of length 'ntypes'.
5197c478bd9Sstevel@tonic-gate  */
5207c478bd9Sstevel@tonic-gate static void
print_contract(const char * dir,ctid_t id,verbout_t * spec,int * types,int ntypes)5217c478bd9Sstevel@tonic-gate print_contract(const char *dir, ctid_t id, verbout_t *spec,
5227c478bd9Sstevel@tonic-gate     int *types, int ntypes)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate 	ct_stathdl_t status;
5257c478bd9Sstevel@tonic-gate 	char hstr[100], qstr[20], nstr[20];
5267c478bd9Sstevel@tonic-gate 	ctstate_t state;
5277c478bd9Sstevel@tonic-gate 	int fd = 0;
5287c478bd9Sstevel@tonic-gate 	int t;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	/*
5317c478bd9Sstevel@tonic-gate 	 * Open and obtain status.
5327c478bd9Sstevel@tonic-gate 	 */
5337c478bd9Sstevel@tonic-gate 	if ((fd = contract_open(id, dir, "status", O_RDONLY)) == -1) {
5347c478bd9Sstevel@tonic-gate 		if (errno == ENOENT)
5357c478bd9Sstevel@tonic-gate 			return;
5367c478bd9Sstevel@tonic-gate 		uu_die(gettext("could not open contract status file"));
5377c478bd9Sstevel@tonic-gate 	}
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	if (errno = ct_status_read(fd, opt_verbose ? CTD_ALL : CTD_COMMON,
5407c478bd9Sstevel@tonic-gate 	    &status))
5417c478bd9Sstevel@tonic-gate 		uu_die(gettext("failed to get contract status for %d"), id);
5427c478bd9Sstevel@tonic-gate 	(void) close(fd);
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	/*
5457c478bd9Sstevel@tonic-gate 	 * Unless otherwise directed, don't display dead contracts.
5467c478bd9Sstevel@tonic-gate 	 */
5477c478bd9Sstevel@tonic-gate 	state = ct_status_get_state(status);
5487c478bd9Sstevel@tonic-gate 	if (!opt_showall && state == CTS_DEAD) {
5497c478bd9Sstevel@tonic-gate 		ct_status_free(status);
5507c478bd9Sstevel@tonic-gate 		return;
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/*
5547c478bd9Sstevel@tonic-gate 	 * If we are only allowed to display certain contract types,
5557c478bd9Sstevel@tonic-gate 	 * perform that filtering here.  We stash a copy of spec so we
5567c478bd9Sstevel@tonic-gate 	 * don't have to recompute it later.
5577c478bd9Sstevel@tonic-gate 	 */
5587c478bd9Sstevel@tonic-gate 	if (types) {
5597c478bd9Sstevel@tonic-gate 		int key = get_type(ct_status_get_type(status));
5607c478bd9Sstevel@tonic-gate 		spec = cttypes[key].verbout;
5617c478bd9Sstevel@tonic-gate 		if (bsearch(&key, types, ntypes, sizeof (int), int_compar) ==
5627c478bd9Sstevel@tonic-gate 		    NULL) {
5637c478bd9Sstevel@tonic-gate 			ct_status_free(status);
5647c478bd9Sstevel@tonic-gate 			return;
5657c478bd9Sstevel@tonic-gate 		}
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	/*
5697c478bd9Sstevel@tonic-gate 	 * Precompute those fields which have both textual and
5707c478bd9Sstevel@tonic-gate 	 * numerical values.
5717c478bd9Sstevel@tonic-gate 	 */
5727c478bd9Sstevel@tonic-gate 	if ((state == CTS_OWNED) || (state == CTS_INHERITED))
5737c478bd9Sstevel@tonic-gate 		(void) snprintf(hstr, sizeof (hstr), "%ld",
5747c478bd9Sstevel@tonic-gate 		    ct_status_get_holder(status));
5757c478bd9Sstevel@tonic-gate 	else
5767c478bd9Sstevel@tonic-gate 		(void) snprintf(hstr, sizeof (hstr), "%s", "-");
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	if ((t = ct_status_get_qtime(status)) == -1) {
5797c478bd9Sstevel@tonic-gate 		qstr[0] = nstr[0] = '-';
5807c478bd9Sstevel@tonic-gate 		qstr[1] = nstr[1] = '\0';
5817c478bd9Sstevel@tonic-gate 	} else {
5827c478bd9Sstevel@tonic-gate 		(void) snprintf(qstr, sizeof (qstr), "%d", t);
5837c478bd9Sstevel@tonic-gate 		(void) snprintf(nstr, sizeof (nstr), "%d",
5847c478bd9Sstevel@tonic-gate 		    ct_status_get_ntime(status));
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	/*
5887c478bd9Sstevel@tonic-gate 	 * Emit the contract's status.
5897c478bd9Sstevel@tonic-gate 	 */
5907c478bd9Sstevel@tonic-gate 	(void) printf("%-7ld %-7ld %-7s %-7s %-7s %-7d %-7s %-8s\n",
5917c478bd9Sstevel@tonic-gate 	    ct_status_get_id(status),
5927c478bd9Sstevel@tonic-gate 	    ct_status_get_zoneid(status),
5937c478bd9Sstevel@tonic-gate 	    ct_status_get_type(status),
5947c478bd9Sstevel@tonic-gate 	    (state == CTS_OWNED) ? "owned" :
5957c478bd9Sstevel@tonic-gate 	    (state == CTS_INHERITED) ? "inherit" :
5967c478bd9Sstevel@tonic-gate 	    (state == CTS_ORPHAN) ? "orphan" : "dead", hstr,
5977c478bd9Sstevel@tonic-gate 	    ct_status_get_nevents(status), qstr, nstr);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	/*
6007c478bd9Sstevel@tonic-gate 	 * Emit verbose status information, if requested.  If we
6017c478bd9Sstevel@tonic-gate 	 * weren't provided a verbose output spec or didn't compute it
6027c478bd9Sstevel@tonic-gate 	 * earlier, do it now.
6037c478bd9Sstevel@tonic-gate 	 */
6047c478bd9Sstevel@tonic-gate 	if (opt_verbose) {
6057c478bd9Sstevel@tonic-gate 		if (spec == NULL)
6067c478bd9Sstevel@tonic-gate 			spec = cttypes[get_type(ct_status_get_type(status))].
6077c478bd9Sstevel@tonic-gate 			    verbout;
6087c478bd9Sstevel@tonic-gate 		print_verbose(status, spec, vcommon);
6097c478bd9Sstevel@tonic-gate 	}
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	ct_status_free(status);
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate  * scan_type
6167c478bd9Sstevel@tonic-gate  *
6177c478bd9Sstevel@tonic-gate  * Display all contracts of the requested type.
6187c478bd9Sstevel@tonic-gate  */
6197c478bd9Sstevel@tonic-gate static void
scan_type(int typeno)6207c478bd9Sstevel@tonic-gate scan_type(int typeno)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate 	DIR *dir;
6237c478bd9Sstevel@tonic-gate 	struct dirent64 *de;
6247c478bd9Sstevel@tonic-gate 	char path[PATH_MAX];
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	verbout_t *vo = cttypes[typeno].verbout;
6277c478bd9Sstevel@tonic-gate 	const char *type = cttypes[typeno].name;
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	if (snprintf(path, PATH_MAX, CTFS_ROOT "/%s", type) >= PATH_MAX ||
6307c478bd9Sstevel@tonic-gate 	    (dir = opendir(path)) == NULL)
6317c478bd9Sstevel@tonic-gate 		uu_die(gettext("bad contract type: %s\n"), type);
6327c478bd9Sstevel@tonic-gate 	while ((de = readdir64(dir)) != NULL) {
6337c478bd9Sstevel@tonic-gate 		/*
6347c478bd9Sstevel@tonic-gate 		 * Eliminate special files (e.g. '.', '..').
6357c478bd9Sstevel@tonic-gate 		 */
6367c478bd9Sstevel@tonic-gate 		if (de->d_name[0] < '0' || de->d_name[0] > '9')
6377c478bd9Sstevel@tonic-gate 			continue;
6387c478bd9Sstevel@tonic-gate 		print_contract(type, mystrtoul(de->d_name), vo, NULL, 0);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 	(void) closedir(dir);
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate  * scan_ids
6457c478bd9Sstevel@tonic-gate  *
6467c478bd9Sstevel@tonic-gate  * Display all contracts with the requested IDs.
6477c478bd9Sstevel@tonic-gate  */
6487c478bd9Sstevel@tonic-gate static void
scan_ids(ctid_t * ids,int nids)6497c478bd9Sstevel@tonic-gate scan_ids(ctid_t *ids, int nids)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate 	int i;
6527c478bd9Sstevel@tonic-gate 	for (i = 0; i < nids; i++)
6537c478bd9Sstevel@tonic-gate 		print_contract("all", ids[i], NULL, NULL, 0);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate  * scan_all
6587c478bd9Sstevel@tonic-gate  *
6597c478bd9Sstevel@tonic-gate  * Display the union of the requested IDs and types.  So that the
6607c478bd9Sstevel@tonic-gate  * output is sorted by contract ID, it takes the slow road by testing
6617c478bd9Sstevel@tonic-gate  * each entry in /system/contract/all against its criteria.  Used when
6627c478bd9Sstevel@tonic-gate  * the number of types is greater than 1, when we have a mixture of
6637c478bd9Sstevel@tonic-gate  * types and ids, or no lists were provided at all.
6647c478bd9Sstevel@tonic-gate  */
6657c478bd9Sstevel@tonic-gate static void
scan_all(int * types,int ntypes,ctid_t * ids,int nids)6667c478bd9Sstevel@tonic-gate scan_all(int *types, int ntypes, ctid_t *ids, int nids)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	DIR *dir;
6697c478bd9Sstevel@tonic-gate 	struct dirent64 *de;
6707c478bd9Sstevel@tonic-gate 	const char *path = CTFS_ROOT "/all";
6717c478bd9Sstevel@tonic-gate 	int key, test;
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	if ((dir = opendir(path)) == NULL)
6747c478bd9Sstevel@tonic-gate 		uu_die(gettext("could not open %s"), path);
6757c478bd9Sstevel@tonic-gate 	while ((de = readdir64(dir)) != NULL) {
6767c478bd9Sstevel@tonic-gate 		/*
6777c478bd9Sstevel@tonic-gate 		 * Eliminate special files (e.g. '.', '..').
6787c478bd9Sstevel@tonic-gate 		 */
6797c478bd9Sstevel@tonic-gate 		if (de->d_name[0] < '0' || de->d_name[0] > '9')
6807c478bd9Sstevel@tonic-gate 			continue;
6817c478bd9Sstevel@tonic-gate 		key = mystrtoul(de->d_name);
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 		/*
6847c478bd9Sstevel@tonic-gate 		 * If we are given IDs to look at and this contract
6857c478bd9Sstevel@tonic-gate 		 * isn't in the ID list, or if we weren't given a list
6867c478bd9Sstevel@tonic-gate 		 * if IDs but were given a list of types, provide the
6877c478bd9Sstevel@tonic-gate 		 * list of acceptable types to print_contract.
6887c478bd9Sstevel@tonic-gate 		 */
6897c478bd9Sstevel@tonic-gate 		test = nids ? (bsearch(&key, ids, nids, sizeof (int),
6907b209c2cSacruz 		    int_compar) == NULL) : (ntypes != 0);
6917c478bd9Sstevel@tonic-gate 		print_contract("all", key, NULL, (test ? types : NULL), ntypes);
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 	(void) closedir(dir);
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate /*
6977c478bd9Sstevel@tonic-gate  * walk_args
6987c478bd9Sstevel@tonic-gate  *
6997c478bd9Sstevel@tonic-gate  * Apply fp to each token in the comma- or space- separated argument
7007c478bd9Sstevel@tonic-gate  * string str and store the results in the array starting at results.
7017c478bd9Sstevel@tonic-gate  */
7027c478bd9Sstevel@tonic-gate static int
walk_args(const char * str,int (* fp)(const char *),int * results)7037c478bd9Sstevel@tonic-gate walk_args(const char *str, int (*fp)(const char *), int *results)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate 	char *copy, *token;
7067c478bd9Sstevel@tonic-gate 	int count = 0;
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	if ((copy = strdup(str)) == NULL)
7097c478bd9Sstevel@tonic-gate 		uu_die(gettext("strdup() failed"));
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	token = strtok(copy, ", ");
7127c478bd9Sstevel@tonic-gate 	if (token == NULL) {
7137c478bd9Sstevel@tonic-gate 		free(copy);
7147c478bd9Sstevel@tonic-gate 		return (0);
7157c478bd9Sstevel@tonic-gate 	}
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	do {
7187c478bd9Sstevel@tonic-gate 		if (fp)
7197c478bd9Sstevel@tonic-gate 			*(results++) = fp(token);
7207c478bd9Sstevel@tonic-gate 		count++;
7217c478bd9Sstevel@tonic-gate 	} while (token = strtok(NULL, ", "));
7227c478bd9Sstevel@tonic-gate 	free(copy);
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	return (count);
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate /*
7287c478bd9Sstevel@tonic-gate  * parse
7297c478bd9Sstevel@tonic-gate  *
7307c478bd9Sstevel@tonic-gate  * Parse the comma- or space- separated string str, using fp to covert
7317c478bd9Sstevel@tonic-gate  * the tokens to integers.  Append the list of integers to the array
7327c478bd9Sstevel@tonic-gate  * pointed to by *idps, growing the array if necessary.
7337c478bd9Sstevel@tonic-gate  */
7347c478bd9Sstevel@tonic-gate static int
parse(const char * str,int ** idsp,int nids,int (* fp)(const char * fp))7357c478bd9Sstevel@tonic-gate parse(const char *str, int **idsp, int nids, int (*fp)(const char *fp))
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate 	int count;
7387c478bd9Sstevel@tonic-gate 	int *array;
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	count = walk_args(str, NULL, NULL);
7417c478bd9Sstevel@tonic-gate 	if (count == 0)
7427c478bd9Sstevel@tonic-gate 		return (0);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	if ((array = calloc(nids + count, sizeof (int))) == NULL)
7457c478bd9Sstevel@tonic-gate 		uu_die(gettext("calloc() failed"));
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	if (*idsp) {
7487c478bd9Sstevel@tonic-gate 		(void) memcpy(array, *idsp, nids * sizeof (int));
7497c478bd9Sstevel@tonic-gate 		free(*idsp);
7507c478bd9Sstevel@tonic-gate 	}
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	(void) walk_args(str, fp, array + nids);
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	*idsp = array;
7557c478bd9Sstevel@tonic-gate 	return (count + nids);
7567c478bd9Sstevel@tonic-gate }
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate /*
7597c478bd9Sstevel@tonic-gate  * parse_ids
7607c478bd9Sstevel@tonic-gate  *
7617c478bd9Sstevel@tonic-gate  * Extract a list of ids from the comma- or space- separated string str
7627c478bd9Sstevel@tonic-gate  * and append them to the array *idsp, growing it if necessary.
7637c478bd9Sstevel@tonic-gate  */
7647c478bd9Sstevel@tonic-gate static int
parse_ids(const char * arg,int ** idsp,int nids)7657c478bd9Sstevel@tonic-gate parse_ids(const char *arg, int **idsp, int nids)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate 	return (parse(arg, idsp, nids, mystrtoul));
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate /*
7717c478bd9Sstevel@tonic-gate  * parse_types
7727c478bd9Sstevel@tonic-gate  *
7737c478bd9Sstevel@tonic-gate  * Extract a list of types from the comma- or space- separated string
7747c478bd9Sstevel@tonic-gate  * str and append them to the array *idsp, growing it if necessary.
7757c478bd9Sstevel@tonic-gate  */
7767c478bd9Sstevel@tonic-gate static int
parse_types(const char * arg,int ** typesp,int ntypes)7777c478bd9Sstevel@tonic-gate parse_types(const char *arg, int **typesp, int ntypes)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate 	return (parse(arg, typesp, ntypes, get_type));
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * compact
7847c478bd9Sstevel@tonic-gate  *
7857c478bd9Sstevel@tonic-gate  * Sorts and removes duplicates from array.  Initial size of array is
7867c478bd9Sstevel@tonic-gate  * in *size; final size is stored in *size.
7877c478bd9Sstevel@tonic-gate  */
7887c478bd9Sstevel@tonic-gate static void
compact(int * array,int * size)7897c478bd9Sstevel@tonic-gate compact(int *array, int *size)
7907c478bd9Sstevel@tonic-gate {
7917c478bd9Sstevel@tonic-gate 	int i, j, last = -1;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	qsort(array, *size, sizeof (int), int_compar);
7947c478bd9Sstevel@tonic-gate 	for (i = j = 0; i < *size; i++) {
7957c478bd9Sstevel@tonic-gate 		if (array[i] != last) {
7967c478bd9Sstevel@tonic-gate 			last = array[i];
7977c478bd9Sstevel@tonic-gate 			array[j++] = array[i];
7987c478bd9Sstevel@tonic-gate 		}
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate 	*size = j;
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)8047c478bd9Sstevel@tonic-gate main(int argc, char **argv)
8057c478bd9Sstevel@tonic-gate {
8067c478bd9Sstevel@tonic-gate 	unsigned int interval = 0, count = 1;
8077c478bd9Sstevel@tonic-gate 	ctid_t	*ids = NULL;
8087c478bd9Sstevel@tonic-gate 	int	*types = NULL;
8097c478bd9Sstevel@tonic-gate 	int	nids = 0, ntypes = 0;
8107c478bd9Sstevel@tonic-gate 	int	i, s;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
8137c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	(void) uu_setpname(argv[0]);
8167c478bd9Sstevel@tonic-gate 
81726fd7700SKrishnendu Sadhukhan - Sun Microsystems 	while ((s = getopt(argc, argv, "ai:T:t:v")) != EOF) {
8187c478bd9Sstevel@tonic-gate 		switch (s) {
8197c478bd9Sstevel@tonic-gate 		case 'a':
8207c478bd9Sstevel@tonic-gate 			opt_showall = 1;
8217c478bd9Sstevel@tonic-gate 			break;
8227c478bd9Sstevel@tonic-gate 		case 'i':
8237c478bd9Sstevel@tonic-gate 			nids = parse_ids(optarg, (int **)&ids, nids);
8247c478bd9Sstevel@tonic-gate 			break;
82526fd7700SKrishnendu Sadhukhan - Sun Microsystems 		case 'T':
82626fd7700SKrishnendu Sadhukhan - Sun Microsystems 			if (optarg) {
82726fd7700SKrishnendu Sadhukhan - Sun Microsystems 				if (*optarg == 'u')
82826fd7700SKrishnendu Sadhukhan - Sun Microsystems 					timestamp_fmt = UDATE;
82926fd7700SKrishnendu Sadhukhan - Sun Microsystems 				else if (*optarg == 'd')
83026fd7700SKrishnendu Sadhukhan - Sun Microsystems 					timestamp_fmt = DDATE;
83126fd7700SKrishnendu Sadhukhan - Sun Microsystems 				else
83226fd7700SKrishnendu Sadhukhan - Sun Microsystems 					usage();
83326fd7700SKrishnendu Sadhukhan - Sun Microsystems 			} else {
83426fd7700SKrishnendu Sadhukhan - Sun Microsystems 				usage();
83526fd7700SKrishnendu Sadhukhan - Sun Microsystems 			}
83626fd7700SKrishnendu Sadhukhan - Sun Microsystems 			break;
8377c478bd9Sstevel@tonic-gate 		case 't':
8387c478bd9Sstevel@tonic-gate 			ntypes = parse_types(optarg, &types, ntypes);
8397c478bd9Sstevel@tonic-gate 			break;
8407c478bd9Sstevel@tonic-gate 		case 'v':
8417c478bd9Sstevel@tonic-gate 			opt_verbose = 1;
8427c478bd9Sstevel@tonic-gate 			break;
8437c478bd9Sstevel@tonic-gate 		default:
8447c478bd9Sstevel@tonic-gate 			usage();
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	argc -= optind;
8497c478bd9Sstevel@tonic-gate 	argv += optind;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	if (argc > 2 || argc < 0)
8527c478bd9Sstevel@tonic-gate 		usage();
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	if (argc > 0) {
8557c478bd9Sstevel@tonic-gate 		interval = mystrtoul(argv[0]);
8567c478bd9Sstevel@tonic-gate 		count = 0;
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	if (argc > 1) {
8607c478bd9Sstevel@tonic-gate 		count = mystrtoul(argv[1]);
8617c478bd9Sstevel@tonic-gate 		if (count == 0)
8627c478bd9Sstevel@tonic-gate 			return (0);
8637c478bd9Sstevel@tonic-gate 	}
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	if (nids)
8667c478bd9Sstevel@tonic-gate 		compact((int *)ids, &nids);
8677c478bd9Sstevel@tonic-gate 	if (ntypes)
8687c478bd9Sstevel@tonic-gate 		compact(types, &ntypes);
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	for (i = 0; count == 0 || i < count; i++) {
8717c478bd9Sstevel@tonic-gate 		if (i)
8727c478bd9Sstevel@tonic-gate 			(void) sleep(interval);
87326fd7700SKrishnendu Sadhukhan - Sun Microsystems 		if (timestamp_fmt != NODATE)
87426fd7700SKrishnendu Sadhukhan - Sun Microsystems 			print_timestamp(timestamp_fmt);
8757c478bd9Sstevel@tonic-gate 		print_header();
8767c478bd9Sstevel@tonic-gate 		if (nids && ntypes)
8777c478bd9Sstevel@tonic-gate 			scan_all(types, ntypes, ids, nids);
8787c478bd9Sstevel@tonic-gate 		else if (ntypes == 1)
8797c478bd9Sstevel@tonic-gate 			scan_type(*types);
8807c478bd9Sstevel@tonic-gate 		else if (nids)
8817c478bd9Sstevel@tonic-gate 			scan_ids(ids, nids);
8827c478bd9Sstevel@tonic-gate 		else
8837c478bd9Sstevel@tonic-gate 			scan_all(types, ntypes, ids, nids);
8847c478bd9Sstevel@tonic-gate 	}
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	return (0);
8877c478bd9Sstevel@tonic-gate }
888