xref: /onnv-gate/usr/src/cmd/ctstat/ctstat.c (revision 12357:7f18af55ec5e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56073Sacruz  * Common Development and Distribution License (the "License").
66073Sacruz  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12357SStephen.Hanson@Sun.COM  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <sys/types.h>
260Sstevel@tonic-gate #include <sys/ctfs.h>
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <unistd.h>
300Sstevel@tonic-gate #include <fcntl.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <libuutil.h>
340Sstevel@tonic-gate #include <sys/contract/process.h>
35*12357SStephen.Hanson@Sun.COM #include <sys/contract/device.h>
360Sstevel@tonic-gate #include <limits.h>
370Sstevel@tonic-gate #include <libcontract.h>
380Sstevel@tonic-gate #include <libcontract_priv.h>
390Sstevel@tonic-gate #include <dirent.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include <locale.h>
420Sstevel@tonic-gate #include <langinfo.h>
430Sstevel@tonic-gate 
4410265SKrishnendu.Sadhukhan@Sun.COM #include "statcommon.h"
4510265SKrishnendu.Sadhukhan@Sun.COM 
4610265SKrishnendu.Sadhukhan@Sun.COM static uint_t timestamp_fmt = NODATE;
4710265SKrishnendu.Sadhukhan@Sun.COM 
480Sstevel@tonic-gate static int opt_verbose = 0;
490Sstevel@tonic-gate static int opt_showall = 0;
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  * usage
530Sstevel@tonic-gate  *
540Sstevel@tonic-gate  * Educate the user.
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate static void
usage(void)570Sstevel@tonic-gate usage(void)
580Sstevel@tonic-gate {
590Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Usage: %s [-a] [-i ctidlist] "
6010265SKrishnendu.Sadhukhan@Sun.COM 	    "[-t typelist] [-T d|u] [-v] [interval [count]]\n"), uu_getpname());
610Sstevel@tonic-gate 	exit(UU_EXIT_USAGE);
620Sstevel@tonic-gate }
630Sstevel@tonic-gate 
640Sstevel@tonic-gate /*
650Sstevel@tonic-gate  * mystrtoul
660Sstevel@tonic-gate  *
670Sstevel@tonic-gate  * Convert a string into an int in [0, INT_MAX].  Exit if the argument
680Sstevel@tonic-gate  * doen't fit this description.
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate static int
mystrtoul(const char * arg)710Sstevel@tonic-gate mystrtoul(const char *arg)
720Sstevel@tonic-gate {
730Sstevel@tonic-gate 	unsigned int result;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	if (uu_strtoint(arg, &result, sizeof (result), 10, 0, INT_MAX) == -1) {
760Sstevel@tonic-gate 		uu_warn(gettext("invalid numerical argument \"%s\"\n"), arg);
770Sstevel@tonic-gate 		usage();
780Sstevel@tonic-gate 	}
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	return (result);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate  * int_compar
850Sstevel@tonic-gate  *
860Sstevel@tonic-gate  * A simple integer comparator.  Also used for id_ts, since they're the
870Sstevel@tonic-gate  * same thing.
880Sstevel@tonic-gate  */
890Sstevel@tonic-gate static int
int_compar(const void * a1,const void * a2)900Sstevel@tonic-gate int_compar(const void *a1, const void *a2)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	int id1 = *(int *)a1;
930Sstevel@tonic-gate 	int id2 = *(int *)a2;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	if (id1 > id2)
960Sstevel@tonic-gate 		return (1);
970Sstevel@tonic-gate 	if (id2 > id1)
980Sstevel@tonic-gate 		return (-1);
990Sstevel@tonic-gate 	return (0);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate typedef struct optvect {
1030Sstevel@tonic-gate 	const char	*option;
1040Sstevel@tonic-gate 	uint_t		bit;
1050Sstevel@tonic-gate } optvect_t;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate static optvect_t option_params[] = {
1080Sstevel@tonic-gate 	{ "inherit", CT_PR_INHERIT },
1090Sstevel@tonic-gate 	{ "noorphan", CT_PR_NOORPHAN },
1100Sstevel@tonic-gate 	{ "pgrponly", CT_PR_PGRPONLY },
1110Sstevel@tonic-gate 	{ "regent", CT_PR_REGENT },
1120Sstevel@tonic-gate 	{ NULL }
1130Sstevel@tonic-gate };
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate static optvect_t option_events[] = {
1160Sstevel@tonic-gate 	{ "core", CT_PR_EV_CORE },
1170Sstevel@tonic-gate 	{ "signal", CT_PR_EV_SIGNAL },
1180Sstevel@tonic-gate 	{ "hwerr", CT_PR_EV_HWERR },
1190Sstevel@tonic-gate 	{ "empty", CT_PR_EV_EMPTY },
1200Sstevel@tonic-gate 	{ "fork", CT_PR_EV_FORK },
1210Sstevel@tonic-gate 	{ "exit", CT_PR_EV_EXIT },
1220Sstevel@tonic-gate 	{ NULL }
1230Sstevel@tonic-gate };
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate  * print_bits
1270Sstevel@tonic-gate  *
1280Sstevel@tonic-gate  * Display a set whose membership is identified by a bitfield.
1290Sstevel@tonic-gate  */
1300Sstevel@tonic-gate static void
print_bits(uint_t bits,optvect_t * desc)1310Sstevel@tonic-gate print_bits(uint_t bits, optvect_t *desc)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate 	int i, printed = 0;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	for (i = 0; desc[i].option; i++)
1360Sstevel@tonic-gate 		if (desc[i].bit & bits) {
1370Sstevel@tonic-gate 			if (printed)
1380Sstevel@tonic-gate 				(void) putchar(' ');
1390Sstevel@tonic-gate 			printed = 1;
1400Sstevel@tonic-gate 			(void) fputs(desc[i].option, stdout);
1410Sstevel@tonic-gate 		}
1420Sstevel@tonic-gate 	if (printed)
1430Sstevel@tonic-gate 		(void) putchar('\n');
1440Sstevel@tonic-gate 	else
1450Sstevel@tonic-gate 		(void) puts("none");
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate  * print_ids
1500Sstevel@tonic-gate  *
1510Sstevel@tonic-gate  * Display a list of ids, sorted.
1520Sstevel@tonic-gate  */
1530Sstevel@tonic-gate static void
print_ids(id_t * ids,uint_t nids)1540Sstevel@tonic-gate print_ids(id_t *ids, uint_t nids)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	int i;
1570Sstevel@tonic-gate 	int first = 1;
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	qsort(ids, nids, sizeof (int), int_compar);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	for (i = 0; i < nids; i++) {
1620Sstevel@tonic-gate 		/*LINTED*/
1630Sstevel@tonic-gate 		(void) printf(" %d" + first, ids[i]);
1640Sstevel@tonic-gate 		first = 0;
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 	if (first)
1670Sstevel@tonic-gate 		(void) puts("none");
1680Sstevel@tonic-gate 	else
1690Sstevel@tonic-gate 		(void) putchar('\n');
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate typedef void printfunc_t(ct_stathdl_t);
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate  * A structure defining a displayed field.  Includes a label to be
1760Sstevel@tonic-gate  * printed along side the field value, and a function which extracts
1770Sstevel@tonic-gate  * the data from a status structure, formats it, and displays it on
1780Sstevel@tonic-gate  * stdout.
1790Sstevel@tonic-gate  */
1800Sstevel@tonic-gate typedef struct verbout {
1810Sstevel@tonic-gate 	const char	*label;	/* field label */
1820Sstevel@tonic-gate 	printfunc_t	*func;	/* field display function */
1830Sstevel@tonic-gate } verbout_t;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate /*
1860Sstevel@tonic-gate  * verb_cookie
1870Sstevel@tonic-gate  *
1880Sstevel@tonic-gate  * Used to display an error encountered when reading a contract status
1890Sstevel@tonic-gate  * field.
1900Sstevel@tonic-gate  */
1910Sstevel@tonic-gate static void
verb_error(int err)1920Sstevel@tonic-gate verb_error(int err)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	(void) printf("(error: %s)\n", strerror(err));
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate  * verb_cookie
1990Sstevel@tonic-gate  *
2000Sstevel@tonic-gate  * Display the contract's cookie.
2010Sstevel@tonic-gate  */
2020Sstevel@tonic-gate static void
verb_cookie(ct_stathdl_t hdl)2030Sstevel@tonic-gate verb_cookie(ct_stathdl_t hdl)
2040Sstevel@tonic-gate {
2050Sstevel@tonic-gate 	(void) printf("%#llx\n", ct_status_get_cookie(hdl));
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate  * verb_info
2100Sstevel@tonic-gate  *
2110Sstevel@tonic-gate  * Display the parameters in the parameter set.
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate static void
verb_param(ct_stathdl_t hdl)2140Sstevel@tonic-gate verb_param(ct_stathdl_t hdl)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	uint_t param;
2170Sstevel@tonic-gate 	int err;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	if (err = ct_pr_status_get_param(hdl, &param))
2200Sstevel@tonic-gate 		verb_error(err);
2210Sstevel@tonic-gate 	else
2220Sstevel@tonic-gate 		print_bits(param, option_params);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate  * verb_info
2270Sstevel@tonic-gate  *
2280Sstevel@tonic-gate  * Display the events in the informative event set.
2290Sstevel@tonic-gate  */
2300Sstevel@tonic-gate static void
verb_info(ct_stathdl_t hdl)2310Sstevel@tonic-gate verb_info(ct_stathdl_t hdl)
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate 	print_bits(ct_status_get_informative(hdl), option_events);
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate  * verb_crit
2380Sstevel@tonic-gate  *
2390Sstevel@tonic-gate  * Display the events in the critical event set.
2400Sstevel@tonic-gate  */
2410Sstevel@tonic-gate static void
verb_crit(ct_stathdl_t hdl)2420Sstevel@tonic-gate verb_crit(ct_stathdl_t hdl)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	print_bits(ct_status_get_critical(hdl), option_events);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate /*
248*12357SStephen.Hanson@Sun.COM  * verb_minor
249*12357SStephen.Hanson@Sun.COM  *
250*12357SStephen.Hanson@Sun.COM  * Display the minor device
251*12357SStephen.Hanson@Sun.COM  */
252*12357SStephen.Hanson@Sun.COM static void
verb_minor(ct_stathdl_t hdl)253*12357SStephen.Hanson@Sun.COM verb_minor(ct_stathdl_t hdl)
254*12357SStephen.Hanson@Sun.COM {
255*12357SStephen.Hanson@Sun.COM 	int err;
256*12357SStephen.Hanson@Sun.COM 	char *buf;
257*12357SStephen.Hanson@Sun.COM 
258*12357SStephen.Hanson@Sun.COM 	if (err = ct_dev_status_get_minor(hdl, &buf))
259*12357SStephen.Hanson@Sun.COM 		verb_error(err);
260*12357SStephen.Hanson@Sun.COM 	else
261*12357SStephen.Hanson@Sun.COM 		(void) printf("%s\n", buf);
262*12357SStephen.Hanson@Sun.COM }
263*12357SStephen.Hanson@Sun.COM 
264*12357SStephen.Hanson@Sun.COM /*
265*12357SStephen.Hanson@Sun.COM  * verb_state
266*12357SStephen.Hanson@Sun.COM  *
267*12357SStephen.Hanson@Sun.COM  * Display the state of the device
268*12357SStephen.Hanson@Sun.COM  */
269*12357SStephen.Hanson@Sun.COM static void
verb_dev_state(ct_stathdl_t hdl)270*12357SStephen.Hanson@Sun.COM verb_dev_state(ct_stathdl_t hdl)
271*12357SStephen.Hanson@Sun.COM {
272*12357SStephen.Hanson@Sun.COM 	int err;
273*12357SStephen.Hanson@Sun.COM 	uint_t state;
274*12357SStephen.Hanson@Sun.COM 
275*12357SStephen.Hanson@Sun.COM 	if (err = ct_dev_status_get_dev_state(hdl, &state))
276*12357SStephen.Hanson@Sun.COM 		verb_error(err);
277*12357SStephen.Hanson@Sun.COM 	else
278*12357SStephen.Hanson@Sun.COM 		(void) printf("%s\n", state == CT_DEV_EV_ONLINE ? "online" :
279*12357SStephen.Hanson@Sun.COM 		    state == CT_DEV_EV_DEGRADED ? "degraded" : "offline");
280*12357SStephen.Hanson@Sun.COM }
281*12357SStephen.Hanson@Sun.COM 
282*12357SStephen.Hanson@Sun.COM /*
2830Sstevel@tonic-gate  * verb_fatal
2840Sstevel@tonic-gate  *
2850Sstevel@tonic-gate  * Display the events in the fatal event set.
2860Sstevel@tonic-gate  */
2870Sstevel@tonic-gate static void
verb_fatal(ct_stathdl_t hdl)2880Sstevel@tonic-gate verb_fatal(ct_stathdl_t hdl)
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate 	uint_t event;
2910Sstevel@tonic-gate 	int err;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	if (err = ct_pr_status_get_fatal(hdl, &event))
2940Sstevel@tonic-gate 		verb_error(err);
2950Sstevel@tonic-gate 	else
2960Sstevel@tonic-gate 		print_bits(event, option_events);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate  * verb_members
3010Sstevel@tonic-gate  *
3020Sstevel@tonic-gate  * Display the list of member contracts.
3030Sstevel@tonic-gate  */
3040Sstevel@tonic-gate static void
verb_members(ct_stathdl_t hdl)3050Sstevel@tonic-gate verb_members(ct_stathdl_t hdl)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate 	pid_t *pids;
3080Sstevel@tonic-gate 	uint_t npids;
3090Sstevel@tonic-gate 	int err;
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	if (err = ct_pr_status_get_members(hdl, &pids, &npids)) {
3120Sstevel@tonic-gate 		verb_error(err);
3130Sstevel@tonic-gate 		return;
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	print_ids(pids, npids);
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate /*
3200Sstevel@tonic-gate  * verb_inherit
3210Sstevel@tonic-gate  *
3220Sstevel@tonic-gate  * Display the list of inherited contracts.
3230Sstevel@tonic-gate  */
3240Sstevel@tonic-gate static void
verb_inherit(ct_stathdl_t hdl)3250Sstevel@tonic-gate verb_inherit(ct_stathdl_t hdl)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate 	ctid_t *ctids;
3280Sstevel@tonic-gate 	uint_t nctids;
3290Sstevel@tonic-gate 	int err;
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	if (err = ct_pr_status_get_contracts(hdl, &ctids, &nctids))
3320Sstevel@tonic-gate 		verb_error(err);
3330Sstevel@tonic-gate 	else
3340Sstevel@tonic-gate 		print_ids(ctids, nctids);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate /*
3386073Sacruz  * verb_svc_fmri
3396073Sacruz  *
3406073Sacruz  * Display the process contract service fmri
3416073Sacruz  */
3426073Sacruz static void
verb_svc_fmri(ct_stathdl_t hdl)3436073Sacruz verb_svc_fmri(ct_stathdl_t hdl)
3446073Sacruz {
3456073Sacruz 	char *svc_fmri;
3466073Sacruz 	int err;
3476073Sacruz 	if (err = ct_pr_status_get_svc_fmri(hdl, &svc_fmri))
3486073Sacruz 		verb_error(err);
3496073Sacruz 	else
3506073Sacruz 		(void) printf("%s\n", svc_fmri);
3516073Sacruz }
3526073Sacruz 
3536073Sacruz /*
3546073Sacruz  * verb_svc_aux
3556073Sacruz  *
3566073Sacruz  * Display the process contract service fmri auxiliar
3576073Sacruz  */
3586073Sacruz static void
verb_svc_aux(ct_stathdl_t hdl)3596073Sacruz verb_svc_aux(ct_stathdl_t hdl)
3606073Sacruz {
3616073Sacruz 	char *svc_aux;
3626073Sacruz 	int err;
3636073Sacruz 	if (err = ct_pr_status_get_svc_aux(hdl, &svc_aux))
3646073Sacruz 		verb_error(err);
3656073Sacruz 	else
3666073Sacruz 		(void) printf("%s\n", svc_aux);
3676073Sacruz }
3686073Sacruz 
3696073Sacruz /*
3706073Sacruz  * verb_svc_ctid
3716073Sacruz  *
3726073Sacruz  * Display the process contract service fmri ctid
3736073Sacruz  */
3746073Sacruz static void
verb_svc_ctid(ct_stathdl_t hdl)3756073Sacruz verb_svc_ctid(ct_stathdl_t hdl)
3766073Sacruz {
3776073Sacruz 	ctid_t svc_ctid;
3786073Sacruz 	int err;
3796073Sacruz 	if (err = ct_pr_status_get_svc_ctid(hdl, &svc_ctid))
3806073Sacruz 		verb_error(err);
3816073Sacruz 	else
3826073Sacruz 		(void) printf("%ld\n", svc_ctid);
3836073Sacruz }
3846073Sacruz 
3856073Sacruz /*
3866073Sacruz  * verb_svc_creator
3876073Sacruz  *
3886073Sacruz  * Display the process contract creator's execname
3896073Sacruz  */
3906073Sacruz static void
verb_svc_creator(ct_stathdl_t hdl)3916073Sacruz verb_svc_creator(ct_stathdl_t hdl)
3926073Sacruz {
3936073Sacruz 	char *svc_creator;
3946073Sacruz 	int err;
3956073Sacruz 	if (err = ct_pr_status_get_svc_creator(hdl, &svc_creator))
3966073Sacruz 		verb_error(err);
3976073Sacruz 	else
3986073Sacruz 		(void) printf("%s\n", svc_creator);
3996073Sacruz }
4006073Sacruz 
4016073Sacruz /*
4020Sstevel@tonic-gate  * Common contract status fields.
4030Sstevel@tonic-gate  */
4040Sstevel@tonic-gate static verbout_t vcommon[] = {
4050Sstevel@tonic-gate 	"cookie", verb_cookie,
4060Sstevel@tonic-gate 	NULL,
4070Sstevel@tonic-gate };
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate  * Process contract-specific status fields.
4110Sstevel@tonic-gate  * The critical and informative event sets are here because the event
4120Sstevel@tonic-gate  * names are contract-specific.  They are listed first, however, so
4130Sstevel@tonic-gate  * they are displayed adjacent to the "normal" common output.
4140Sstevel@tonic-gate  */
4150Sstevel@tonic-gate static verbout_t vprocess[] = {
4160Sstevel@tonic-gate 	"informative event set", verb_info,
4170Sstevel@tonic-gate 	"critical event set", verb_crit,
4180Sstevel@tonic-gate 	"fatal event set", verb_fatal,
4190Sstevel@tonic-gate 	"parameter set", verb_param,
4200Sstevel@tonic-gate 	"member processes", verb_members,
4210Sstevel@tonic-gate 	"inherited contracts", verb_inherit,
4226073Sacruz 	"service fmri", verb_svc_fmri,
4236073Sacruz 	"service fmri ctid", verb_svc_ctid,
4246073Sacruz 	"creator", verb_svc_creator,
4256073Sacruz 	"aux", verb_svc_aux,
4260Sstevel@tonic-gate 	NULL
4270Sstevel@tonic-gate };
4280Sstevel@tonic-gate 
429*12357SStephen.Hanson@Sun.COM static verbout_t vdevice[] = {
430*12357SStephen.Hanson@Sun.COM 	"device", verb_minor,
431*12357SStephen.Hanson@Sun.COM 	"dev_state", verb_dev_state,
432*12357SStephen.Hanson@Sun.COM 	NULL
433*12357SStephen.Hanson@Sun.COM };
434*12357SStephen.Hanson@Sun.COM 
4350Sstevel@tonic-gate /*
4360Sstevel@tonic-gate  * print_verbose
4370Sstevel@tonic-gate  *
4380Sstevel@tonic-gate  * Displays a contract's verbose status, common fields first.
4390Sstevel@tonic-gate  */
4400Sstevel@tonic-gate static void
print_verbose(ct_stathdl_t hdl,verbout_t * spec,verbout_t * common)4410Sstevel@tonic-gate print_verbose(ct_stathdl_t hdl, verbout_t *spec, verbout_t *common)
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate 	int i;
4440Sstevel@tonic-gate 	int tmp, maxwidth = 0;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	/*
4470Sstevel@tonic-gate 	 * Compute the width of all the fields.
4480Sstevel@tonic-gate 	 */
4490Sstevel@tonic-gate 	for (i = 0; common[i].label; i++)
4500Sstevel@tonic-gate 		if ((tmp = strlen(common[i].label)) > maxwidth)
4510Sstevel@tonic-gate 			maxwidth = tmp;
4520Sstevel@tonic-gate 	if (spec)
4530Sstevel@tonic-gate 		for (i = 0; spec[i].label; i++)
4540Sstevel@tonic-gate 			if ((tmp = strlen(spec[i].label)) > maxwidth)
4550Sstevel@tonic-gate 				maxwidth = tmp;
4560Sstevel@tonic-gate 	maxwidth += 2;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	/*
4590Sstevel@tonic-gate 	 * Display the data.
4600Sstevel@tonic-gate 	 */
4610Sstevel@tonic-gate 	for (i = 0; common[i].label; i++) {
4620Sstevel@tonic-gate 		tmp = printf("\t%s", common[i].label);
4630Sstevel@tonic-gate 		if (tmp < 0)
4640Sstevel@tonic-gate 			tmp = 0;
4650Sstevel@tonic-gate 		(void) printf("%-*s", maxwidth - tmp + 1, ":");
4660Sstevel@tonic-gate 		common[i].func(hdl);
4670Sstevel@tonic-gate 	}
4680Sstevel@tonic-gate 	if (spec)
4690Sstevel@tonic-gate 		for (i = 0; spec[i].label; i++) {
4700Sstevel@tonic-gate 			(void) printf("\t%s%n", spec[i].label, &tmp);
4710Sstevel@tonic-gate 			(void) printf("%-*s", maxwidth - tmp + 1, ":");
4720Sstevel@tonic-gate 			spec[i].func(hdl);
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate struct {
4770Sstevel@tonic-gate 	const char *name;
4780Sstevel@tonic-gate 	verbout_t *verbout;
4790Sstevel@tonic-gate } cttypes[] = {
4800Sstevel@tonic-gate 	{ "process", vprocess },
481*12357SStephen.Hanson@Sun.COM 	{ "device", vdevice },
4820Sstevel@tonic-gate 	{ NULL }
4830Sstevel@tonic-gate };
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate /*
4860Sstevel@tonic-gate  * get_type
4870Sstevel@tonic-gate  *
4880Sstevel@tonic-gate  * Given a type name, return an index into the above array of types.
4890Sstevel@tonic-gate  */
4900Sstevel@tonic-gate static int
get_type(const char * typestr)4910Sstevel@tonic-gate get_type(const char *typestr)
4920Sstevel@tonic-gate {
4930Sstevel@tonic-gate 	int i;
4940Sstevel@tonic-gate 	for (i = 0; cttypes[i].name; i++)
4950Sstevel@tonic-gate 		if (strcmp(cttypes[i].name, typestr) == 0)
4960Sstevel@tonic-gate 			return (i);
4970Sstevel@tonic-gate 	uu_die(gettext("invalid contract type: %s\n"), typestr);
4980Sstevel@tonic-gate 	/* NOTREACHED */
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate /*
5020Sstevel@tonic-gate  * print_header
5030Sstevel@tonic-gate  *
5040Sstevel@tonic-gate  * Display the status header.
5050Sstevel@tonic-gate  */
5060Sstevel@tonic-gate static void
print_header(void)5070Sstevel@tonic-gate print_header(void)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate 	(void) printf("%-8s%-8s%-8s%-8s%-8s%-8s%-8s%-8s\n", "CTID", "ZONEID",
5100Sstevel@tonic-gate 	    "TYPE", "STATE", "HOLDER", "EVENTS", "QTIME", "NTIME");
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate /*
5140Sstevel@tonic-gate  * print_contract
5150Sstevel@tonic-gate  *
5160Sstevel@tonic-gate  * Display status for contract ID 'id' from type directory 'dir'.  If
5170Sstevel@tonic-gate  * only contracts of a specific set of types should be displayed,
5180Sstevel@tonic-gate  * 'types' will be a sorted list of type indices of length 'ntypes'.
5190Sstevel@tonic-gate  */
5200Sstevel@tonic-gate static void
print_contract(const char * dir,ctid_t id,verbout_t * spec,int * types,int ntypes)5210Sstevel@tonic-gate print_contract(const char *dir, ctid_t id, verbout_t *spec,
5220Sstevel@tonic-gate     int *types, int ntypes)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate 	ct_stathdl_t status;
5250Sstevel@tonic-gate 	char hstr[100], qstr[20], nstr[20];
5260Sstevel@tonic-gate 	ctstate_t state;
5270Sstevel@tonic-gate 	int fd = 0;
5280Sstevel@tonic-gate 	int t;
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	/*
5310Sstevel@tonic-gate 	 * Open and obtain status.
5320Sstevel@tonic-gate 	 */
5330Sstevel@tonic-gate 	if ((fd = contract_open(id, dir, "status", O_RDONLY)) == -1) {
5340Sstevel@tonic-gate 		if (errno == ENOENT)
5350Sstevel@tonic-gate 			return;
5360Sstevel@tonic-gate 		uu_die(gettext("could not open contract status file"));
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	if (errno = ct_status_read(fd, opt_verbose ? CTD_ALL : CTD_COMMON,
5400Sstevel@tonic-gate 	    &status))
5410Sstevel@tonic-gate 		uu_die(gettext("failed to get contract status for %d"), id);
5420Sstevel@tonic-gate 	(void) close(fd);
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	/*
5450Sstevel@tonic-gate 	 * Unless otherwise directed, don't display dead contracts.
5460Sstevel@tonic-gate 	 */
5470Sstevel@tonic-gate 	state = ct_status_get_state(status);
5480Sstevel@tonic-gate 	if (!opt_showall && state == CTS_DEAD) {
5490Sstevel@tonic-gate 		ct_status_free(status);
5500Sstevel@tonic-gate 		return;
5510Sstevel@tonic-gate 	}
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	/*
5540Sstevel@tonic-gate 	 * If we are only allowed to display certain contract types,
5550Sstevel@tonic-gate 	 * perform that filtering here.  We stash a copy of spec so we
5560Sstevel@tonic-gate 	 * don't have to recompute it later.
5570Sstevel@tonic-gate 	 */
5580Sstevel@tonic-gate 	if (types) {
5590Sstevel@tonic-gate 		int key = get_type(ct_status_get_type(status));
5600Sstevel@tonic-gate 		spec = cttypes[key].verbout;
5610Sstevel@tonic-gate 		if (bsearch(&key, types, ntypes, sizeof (int), int_compar) ==
5620Sstevel@tonic-gate 		    NULL) {
5630Sstevel@tonic-gate 			ct_status_free(status);
5640Sstevel@tonic-gate 			return;
5650Sstevel@tonic-gate 		}
5660Sstevel@tonic-gate 	}
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	/*
5690Sstevel@tonic-gate 	 * Precompute those fields which have both textual and
5700Sstevel@tonic-gate 	 * numerical values.
5710Sstevel@tonic-gate 	 */
5720Sstevel@tonic-gate 	if ((state == CTS_OWNED) || (state == CTS_INHERITED))
5730Sstevel@tonic-gate 		(void) snprintf(hstr, sizeof (hstr), "%ld",
5740Sstevel@tonic-gate 		    ct_status_get_holder(status));
5750Sstevel@tonic-gate 	else
5760Sstevel@tonic-gate 		(void) snprintf(hstr, sizeof (hstr), "%s", "-");
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	if ((t = ct_status_get_qtime(status)) == -1) {
5790Sstevel@tonic-gate 		qstr[0] = nstr[0] = '-';
5800Sstevel@tonic-gate 		qstr[1] = nstr[1] = '\0';
5810Sstevel@tonic-gate 	} else {
5820Sstevel@tonic-gate 		(void) snprintf(qstr, sizeof (qstr), "%d", t);
5830Sstevel@tonic-gate 		(void) snprintf(nstr, sizeof (nstr), "%d",
5840Sstevel@tonic-gate 		    ct_status_get_ntime(status));
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	/*
5880Sstevel@tonic-gate 	 * Emit the contract's status.
5890Sstevel@tonic-gate 	 */
5900Sstevel@tonic-gate 	(void) printf("%-7ld %-7ld %-7s %-7s %-7s %-7d %-7s %-8s\n",
5910Sstevel@tonic-gate 	    ct_status_get_id(status),
5920Sstevel@tonic-gate 	    ct_status_get_zoneid(status),
5930Sstevel@tonic-gate 	    ct_status_get_type(status),
5940Sstevel@tonic-gate 	    (state == CTS_OWNED) ? "owned" :
5950Sstevel@tonic-gate 	    (state == CTS_INHERITED) ? "inherit" :
5960Sstevel@tonic-gate 	    (state == CTS_ORPHAN) ? "orphan" : "dead", hstr,
5970Sstevel@tonic-gate 	    ct_status_get_nevents(status), qstr, nstr);
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	/*
6000Sstevel@tonic-gate 	 * Emit verbose status information, if requested.  If we
6010Sstevel@tonic-gate 	 * weren't provided a verbose output spec or didn't compute it
6020Sstevel@tonic-gate 	 * earlier, do it now.
6030Sstevel@tonic-gate 	 */
6040Sstevel@tonic-gate 	if (opt_verbose) {
6050Sstevel@tonic-gate 		if (spec == NULL)
6060Sstevel@tonic-gate 			spec = cttypes[get_type(ct_status_get_type(status))].
6070Sstevel@tonic-gate 			    verbout;
6080Sstevel@tonic-gate 		print_verbose(status, spec, vcommon);
6090Sstevel@tonic-gate 	}
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	ct_status_free(status);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate /*
6150Sstevel@tonic-gate  * scan_type
6160Sstevel@tonic-gate  *
6170Sstevel@tonic-gate  * Display all contracts of the requested type.
6180Sstevel@tonic-gate  */
6190Sstevel@tonic-gate static void
scan_type(int typeno)6200Sstevel@tonic-gate scan_type(int typeno)
6210Sstevel@tonic-gate {
6220Sstevel@tonic-gate 	DIR *dir;
6230Sstevel@tonic-gate 	struct dirent64 *de;
6240Sstevel@tonic-gate 	char path[PATH_MAX];
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	verbout_t *vo = cttypes[typeno].verbout;
6270Sstevel@tonic-gate 	const char *type = cttypes[typeno].name;
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	if (snprintf(path, PATH_MAX, CTFS_ROOT "/%s", type) >= PATH_MAX ||
6300Sstevel@tonic-gate 	    (dir = opendir(path)) == NULL)
6310Sstevel@tonic-gate 		uu_die(gettext("bad contract type: %s\n"), type);
6320Sstevel@tonic-gate 	while ((de = readdir64(dir)) != NULL) {
6330Sstevel@tonic-gate 		/*
6340Sstevel@tonic-gate 		 * Eliminate special files (e.g. '.', '..').
6350Sstevel@tonic-gate 		 */
6360Sstevel@tonic-gate 		if (de->d_name[0] < '0' || de->d_name[0] > '9')
6370Sstevel@tonic-gate 			continue;
6380Sstevel@tonic-gate 		print_contract(type, mystrtoul(de->d_name), vo, NULL, 0);
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate 	(void) closedir(dir);
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate  * scan_ids
6450Sstevel@tonic-gate  *
6460Sstevel@tonic-gate  * Display all contracts with the requested IDs.
6470Sstevel@tonic-gate  */
6480Sstevel@tonic-gate static void
scan_ids(ctid_t * ids,int nids)6490Sstevel@tonic-gate scan_ids(ctid_t *ids, int nids)
6500Sstevel@tonic-gate {
6510Sstevel@tonic-gate 	int i;
6520Sstevel@tonic-gate 	for (i = 0; i < nids; i++)
6530Sstevel@tonic-gate 		print_contract("all", ids[i], NULL, NULL, 0);
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate /*
6570Sstevel@tonic-gate  * scan_all
6580Sstevel@tonic-gate  *
6590Sstevel@tonic-gate  * Display the union of the requested IDs and types.  So that the
6600Sstevel@tonic-gate  * output is sorted by contract ID, it takes the slow road by testing
6610Sstevel@tonic-gate  * each entry in /system/contract/all against its criteria.  Used when
6620Sstevel@tonic-gate  * the number of types is greater than 1, when we have a mixture of
6630Sstevel@tonic-gate  * types and ids, or no lists were provided at all.
6640Sstevel@tonic-gate  */
6650Sstevel@tonic-gate static void
scan_all(int * types,int ntypes,ctid_t * ids,int nids)6660Sstevel@tonic-gate scan_all(int *types, int ntypes, ctid_t *ids, int nids)
6670Sstevel@tonic-gate {
6680Sstevel@tonic-gate 	DIR *dir;
6690Sstevel@tonic-gate 	struct dirent64 *de;
6700Sstevel@tonic-gate 	const char *path = CTFS_ROOT "/all";
6710Sstevel@tonic-gate 	int key, test;
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 	if ((dir = opendir(path)) == NULL)
6740Sstevel@tonic-gate 		uu_die(gettext("could not open %s"), path);
6750Sstevel@tonic-gate 	while ((de = readdir64(dir)) != NULL) {
6760Sstevel@tonic-gate 		/*
6770Sstevel@tonic-gate 		 * Eliminate special files (e.g. '.', '..').
6780Sstevel@tonic-gate 		 */
6790Sstevel@tonic-gate 		if (de->d_name[0] < '0' || de->d_name[0] > '9')
6800Sstevel@tonic-gate 			continue;
6810Sstevel@tonic-gate 		key = mystrtoul(de->d_name);
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 		/*
6840Sstevel@tonic-gate 		 * If we are given IDs to look at and this contract
6850Sstevel@tonic-gate 		 * isn't in the ID list, or if we weren't given a list
6860Sstevel@tonic-gate 		 * if IDs but were given a list of types, provide the
6870Sstevel@tonic-gate 		 * list of acceptable types to print_contract.
6880Sstevel@tonic-gate 		 */
6890Sstevel@tonic-gate 		test = nids ? (bsearch(&key, ids, nids, sizeof (int),
6906073Sacruz 		    int_compar) == NULL) : (ntypes != 0);
6910Sstevel@tonic-gate 		print_contract("all", key, NULL, (test ? types : NULL), ntypes);
6920Sstevel@tonic-gate 	}
6930Sstevel@tonic-gate 	(void) closedir(dir);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate /*
6970Sstevel@tonic-gate  * walk_args
6980Sstevel@tonic-gate  *
6990Sstevel@tonic-gate  * Apply fp to each token in the comma- or space- separated argument
7000Sstevel@tonic-gate  * string str and store the results in the array starting at results.
7010Sstevel@tonic-gate  */
7020Sstevel@tonic-gate static int
walk_args(const char * str,int (* fp)(const char *),int * results)7030Sstevel@tonic-gate walk_args(const char *str, int (*fp)(const char *), int *results)
7040Sstevel@tonic-gate {
7050Sstevel@tonic-gate 	char *copy, *token;
7060Sstevel@tonic-gate 	int count = 0;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	if ((copy = strdup(str)) == NULL)
7090Sstevel@tonic-gate 		uu_die(gettext("strdup() failed"));
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 	token = strtok(copy, ", ");
7120Sstevel@tonic-gate 	if (token == NULL) {
7130Sstevel@tonic-gate 		free(copy);
7140Sstevel@tonic-gate 		return (0);
7150Sstevel@tonic-gate 	}
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	do {
7180Sstevel@tonic-gate 		if (fp)
7190Sstevel@tonic-gate 			*(results++) = fp(token);
7200Sstevel@tonic-gate 		count++;
7210Sstevel@tonic-gate 	} while (token = strtok(NULL, ", "));
7220Sstevel@tonic-gate 	free(copy);
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	return (count);
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate /*
7280Sstevel@tonic-gate  * parse
7290Sstevel@tonic-gate  *
7300Sstevel@tonic-gate  * Parse the comma- or space- separated string str, using fp to covert
7310Sstevel@tonic-gate  * the tokens to integers.  Append the list of integers to the array
7320Sstevel@tonic-gate  * pointed to by *idps, growing the array if necessary.
7330Sstevel@tonic-gate  */
7340Sstevel@tonic-gate static int
parse(const char * str,int ** idsp,int nids,int (* fp)(const char * fp))7350Sstevel@tonic-gate parse(const char *str, int **idsp, int nids, int (*fp)(const char *fp))
7360Sstevel@tonic-gate {
7370Sstevel@tonic-gate 	int count;
7380Sstevel@tonic-gate 	int *array;
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	count = walk_args(str, NULL, NULL);
7410Sstevel@tonic-gate 	if (count == 0)
7420Sstevel@tonic-gate 		return (0);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	if ((array = calloc(nids + count, sizeof (int))) == NULL)
7450Sstevel@tonic-gate 		uu_die(gettext("calloc() failed"));
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	if (*idsp) {
7480Sstevel@tonic-gate 		(void) memcpy(array, *idsp, nids * sizeof (int));
7490Sstevel@tonic-gate 		free(*idsp);
7500Sstevel@tonic-gate 	}
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	(void) walk_args(str, fp, array + nids);
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	*idsp = array;
7550Sstevel@tonic-gate 	return (count + nids);
7560Sstevel@tonic-gate }
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate /*
7590Sstevel@tonic-gate  * parse_ids
7600Sstevel@tonic-gate  *
7610Sstevel@tonic-gate  * Extract a list of ids from the comma- or space- separated string str
7620Sstevel@tonic-gate  * and append them to the array *idsp, growing it if necessary.
7630Sstevel@tonic-gate  */
7640Sstevel@tonic-gate static int
parse_ids(const char * arg,int ** idsp,int nids)7650Sstevel@tonic-gate parse_ids(const char *arg, int **idsp, int nids)
7660Sstevel@tonic-gate {
7670Sstevel@tonic-gate 	return (parse(arg, idsp, nids, mystrtoul));
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate /*
7710Sstevel@tonic-gate  * parse_types
7720Sstevel@tonic-gate  *
7730Sstevel@tonic-gate  * Extract a list of types from the comma- or space- separated string
7740Sstevel@tonic-gate  * str and append them to the array *idsp, growing it if necessary.
7750Sstevel@tonic-gate  */
7760Sstevel@tonic-gate static int
parse_types(const char * arg,int ** typesp,int ntypes)7770Sstevel@tonic-gate parse_types(const char *arg, int **typesp, int ntypes)
7780Sstevel@tonic-gate {
7790Sstevel@tonic-gate 	return (parse(arg, typesp, ntypes, get_type));
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate /*
7830Sstevel@tonic-gate  * compact
7840Sstevel@tonic-gate  *
7850Sstevel@tonic-gate  * Sorts and removes duplicates from array.  Initial size of array is
7860Sstevel@tonic-gate  * in *size; final size is stored in *size.
7870Sstevel@tonic-gate  */
7880Sstevel@tonic-gate static void
compact(int * array,int * size)7890Sstevel@tonic-gate compact(int *array, int *size)
7900Sstevel@tonic-gate {
7910Sstevel@tonic-gate 	int i, j, last = -1;
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	qsort(array, *size, sizeof (int), int_compar);
7940Sstevel@tonic-gate 	for (i = j = 0; i < *size; i++) {
7950Sstevel@tonic-gate 		if (array[i] != last) {
7960Sstevel@tonic-gate 			last = array[i];
7970Sstevel@tonic-gate 			array[j++] = array[i];
7980Sstevel@tonic-gate 		}
7990Sstevel@tonic-gate 	}
8000Sstevel@tonic-gate 	*size = j;
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate int
main(int argc,char ** argv)8040Sstevel@tonic-gate main(int argc, char **argv)
8050Sstevel@tonic-gate {
8060Sstevel@tonic-gate 	unsigned int interval = 0, count = 1;
8070Sstevel@tonic-gate 	ctid_t	*ids = NULL;
8080Sstevel@tonic-gate 	int	*types = NULL;
8090Sstevel@tonic-gate 	int	nids = 0, ntypes = 0;
8100Sstevel@tonic-gate 	int	i, s;
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
8130Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	(void) uu_setpname(argv[0]);
8160Sstevel@tonic-gate 
81710265SKrishnendu.Sadhukhan@Sun.COM 	while ((s = getopt(argc, argv, "ai:T:t:v")) != EOF) {
8180Sstevel@tonic-gate 		switch (s) {
8190Sstevel@tonic-gate 		case 'a':
8200Sstevel@tonic-gate 			opt_showall = 1;
8210Sstevel@tonic-gate 			break;
8220Sstevel@tonic-gate 		case 'i':
8230Sstevel@tonic-gate 			nids = parse_ids(optarg, (int **)&ids, nids);
8240Sstevel@tonic-gate 			break;
82510265SKrishnendu.Sadhukhan@Sun.COM 		case 'T':
82610265SKrishnendu.Sadhukhan@Sun.COM 			if (optarg) {
82710265SKrishnendu.Sadhukhan@Sun.COM 				if (*optarg == 'u')
82810265SKrishnendu.Sadhukhan@Sun.COM 					timestamp_fmt = UDATE;
82910265SKrishnendu.Sadhukhan@Sun.COM 				else if (*optarg == 'd')
83010265SKrishnendu.Sadhukhan@Sun.COM 					timestamp_fmt = DDATE;
83110265SKrishnendu.Sadhukhan@Sun.COM 				else
83210265SKrishnendu.Sadhukhan@Sun.COM 					usage();
83310265SKrishnendu.Sadhukhan@Sun.COM 			} else {
83410265SKrishnendu.Sadhukhan@Sun.COM 				usage();
83510265SKrishnendu.Sadhukhan@Sun.COM 			}
83610265SKrishnendu.Sadhukhan@Sun.COM 			break;
8370Sstevel@tonic-gate 		case 't':
8380Sstevel@tonic-gate 			ntypes = parse_types(optarg, &types, ntypes);
8390Sstevel@tonic-gate 			break;
8400Sstevel@tonic-gate 		case 'v':
8410Sstevel@tonic-gate 			opt_verbose = 1;
8420Sstevel@tonic-gate 			break;
8430Sstevel@tonic-gate 		default:
8440Sstevel@tonic-gate 			usage();
8450Sstevel@tonic-gate 		}
8460Sstevel@tonic-gate 	}
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate 	argc -= optind;
8490Sstevel@tonic-gate 	argv += optind;
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 	if (argc > 2 || argc < 0)
8520Sstevel@tonic-gate 		usage();
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	if (argc > 0) {
8550Sstevel@tonic-gate 		interval = mystrtoul(argv[0]);
8560Sstevel@tonic-gate 		count = 0;
8570Sstevel@tonic-gate 	}
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate 	if (argc > 1) {
8600Sstevel@tonic-gate 		count = mystrtoul(argv[1]);
8610Sstevel@tonic-gate 		if (count == 0)
8620Sstevel@tonic-gate 			return (0);
8630Sstevel@tonic-gate 	}
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 	if (nids)
8660Sstevel@tonic-gate 		compact((int *)ids, &nids);
8670Sstevel@tonic-gate 	if (ntypes)
8680Sstevel@tonic-gate 		compact(types, &ntypes);
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	for (i = 0; count == 0 || i < count; i++) {
8710Sstevel@tonic-gate 		if (i)
8720Sstevel@tonic-gate 			(void) sleep(interval);
87310265SKrishnendu.Sadhukhan@Sun.COM 		if (timestamp_fmt != NODATE)
87410265SKrishnendu.Sadhukhan@Sun.COM 			print_timestamp(timestamp_fmt);
8750Sstevel@tonic-gate 		print_header();
8760Sstevel@tonic-gate 		if (nids && ntypes)
8770Sstevel@tonic-gate 			scan_all(types, ntypes, ids, nids);
8780Sstevel@tonic-gate 		else if (ntypes == 1)
8790Sstevel@tonic-gate 			scan_type(*types);
8800Sstevel@tonic-gate 		else if (nids)
8810Sstevel@tonic-gate 			scan_ids(ids, nids);
8820Sstevel@tonic-gate 		else
8830Sstevel@tonic-gate 			scan_all(types, ntypes, ids, nids);
8840Sstevel@tonic-gate 	}
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 	return (0);
8870Sstevel@tonic-gate }
888