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, ¶m))
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