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, ¶m))
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
2477c478bd9Sstevel@tonic-gate /*
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
282*f76de749SStephen Hanson /*
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
3377c478bd9Sstevel@tonic-gate /*
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
4017b209c2cSacruz /*
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),
6907c478bd9Sstevel@tonic-gate 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