Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144992430
D10916.id33986.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
33 KB
Referenced Files
None
Subscribers
None
D10916.id33986.diff
View Options
Index: usr.bin/procstat/procstat.h
===================================================================
--- usr.bin/procstat/procstat.h
+++ usr.bin/procstat/procstat.h
@@ -35,7 +35,19 @@
#define PROCSTAT_XO_VERSION "1"
-extern int hflag, nflag, Cflag, Hflag;
+enum {
+ PS_OPT_CAPABILITIES = 0x01,
+ PS_OPT_NOHEADER = 0x02,
+ PS_OPT_PERTHREAD = 0x04,
+ PS_OPT_SIGNUM = 0x08,
+ PS_OPT_VERBOSE = 0x10
+};
+
+#define PS_SUBCOMMAND_OPTS \
+ (PS_OPT_CAPABILITIES | PS_OPT_SIGNUM | \
+ PS_OPT_PERTHREAD | PS_OPT_VERBOSE)
+
+extern int procstat_opts;
struct kinfo_proc;
void kinfo_proc_sort(struct kinfo_proc *kipp, int count);
@@ -43,15 +55,14 @@
void procstat_args(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_auxv(struct procstat *prstat, struct kinfo_proc *kipp);
-void procstat_basic(struct kinfo_proc *kipp);
+void procstat_basic(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_cred(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_cs(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_env(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp);
-void procstat_kstack(struct procstat *prstat, struct kinfo_proc *kipp,
- int kflag);
-void procstat_ptlwpinfo(struct procstat *prstat);
+void procstat_kstack(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_rusage(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
Index: usr.bin/procstat/procstat.1
===================================================================
--- usr.bin/procstat/procstat.1
+++ usr.bin/procstat/procstat.1
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 3, 2017
+.Dd October 14, 2017
.Dt PROCSTAT 1
.Os
.Sh NAME
@@ -34,14 +34,75 @@
.Sh SYNOPSIS
.Nm
.Op Fl -libxo
-.Op Fl CHhn
+.Op Fl h
.Op Fl M Ar core
.Op Fl N Ar system
.Op Fl w Ar interval
-.Op Fl b | c | e | f | i | j | k | l | L | r | s | S | t | v | x
-.Op Fl a | Ar pid | Ar core ...
+.Ar command
+.Op Ar pid ... | Ar core ...
+.Nm
+.Op Fl -libxo
+.Fl a
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Ar command
+.Nm
+.Op Fl -libxo
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Oo
+.Fl b |
+.Fl c |
+.Fl e |
+.Fl f Oo Fl C Oc |
+.Fl i Oo Fl n Oc |
+.Fl j Oo Fl n Oc |
+.Fl k Oo Fl k Oc |
+.Fl l |
+.Fl r Oo Fl H Oc |
+.Fl s |
+.Fl S |
+.Fl t |
+.Fl v |
+.Fl x
+.Oc
+.Op Ar pid ... | Ar core ...
+.Nm
+.Op Fl -libxo
+.Fl a
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Oo
+.Fl b |
+.Fl c |
+.Fl e |
+.Fl f Oo Fl C Oc |
+.Fl i Oo Fl n Oc |
+.Fl j Oo Fl n Oc |
+.Fl k Oo Fl k Oc |
+.Fl l |
+.Fl r Oo Fl H Oc |
+.Fl s |
+.Fl S |
+.Fl t |
+.Fl v |
+.Fl x
+.Oc
+.Nm
+.Op Fl -libxo
+.Fl L
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Ar core ...
.Sh DESCRIPTION
-The
.Nm
utility displays detailed information about the processes identified by the
.Ar pid
@@ -51,49 +112,89 @@
It can also display information extracted from a process core file, if
the core file is specified as the argument.
.Pp
-By default, basic process statistics are printed; one of the following
-options may be specified in order to select more detailed process information
-for printing:
-.Bl -tag -width indent
-.It Fl -libxo
-Generate output via
+If the
+.Fl -libxo
+flag is specified the output is generated via
.Xr libxo 3
in a selection of different human and machine readable formats.
See
.Xr xo_parse_args 3
for details on command line arguments.
-.It Fl b
+.Pp
+The following commands are available:
+.Bl -tag -width indent
+.It Ar basic
+Print basic process statistics (this is the default).
+.It Ar binary | Fl b
Display binary information for the process.
-.It Fl c
+.Pp
+Substring commands are accepted.
+.It Ar argument(s) | Fl c
Display command line arguments for the process.
-.It Fl e
+.Pp
+Substring commands are accepted.
+.It Ar environment | Fl e
Display environment variables for the process.
-.It Fl f
+.Pp
+Substring commands are accepted.
+.It Ar file(s) | Ar fd(s) | Fl f
Display file descriptor information for the process.
-.It Fl i
+.Pp
+If the
+.Fl C
+subcommand flag is used then additional capability information is printed.
+.It Ar signal(s) | Fl i
Display signal pending and disposition information for the process.
-.It Fl j
+.Pp
+If the
+.Fl n
+subcommand option is used, the signal numbers are shown instead of signal
+names.
+.Pp
+Substring commands are accepted.
+.It Ar tsignal(s) | Fl j
Display signal pending and blocked information for the process's threads.
-.It Fl k
+.Pp
+If the
+.Fl n
+subcommand option is used, the signal numbers are shown instead of signal
+names.
+.Pp
+Substring commands are accepted.
+.It Ar kstack | Fl k
Display the stacks of kernel threads in the process, excluding stacks of
threads currently running on a CPU and threads with stacks swapped to disk.
-If the flag is repeated, function offsets as well as function names are
-printed.
-.It Fl l
+.Pp
+If the
+.Fl v
+subcommand option is used (or the command flag is repeated), function
+offsets as well as function names are printed.
+.It Ar rlimit | Fl l
Display resource limits for the process.
-.It Fl L
+.It Ar ptlwpinfo | Fl L
Display LWP info for the process pertaining to its signal driven exit.
-.It Fl r
+.It Ar rusage | Fl r
Display resource usage information for the process.
-.It Fl s
+.Pp
+If the
+.Fl v
+.Pq or Fl H
+subcommand flag
+is used then per-thread statistics are printed, rather than per-process
+statistics.
+The second field in the table will list the thread ID to which the row of
+information corresponds.
+.It Ar credential(s) | Fl s
Display security credential information for the process.
-.It Fl S
+.Pp
+Substring commands are accepted.
+.It Ar cpuset | Ar cs | Fl S
Display the cpuset information for the thread.
-.It Fl t
+.It Ar thread(s) | Fl t
Display thread information for the process.
-.It Fl v
+.It Ar vm | Fl v
Display virtual memory mappings for the process.
-.It Fl x
+.It Ar auxv | Fl x
Display ELF auxiliary vector for the process.
.El
.Pp
@@ -111,23 +212,6 @@
.Fl w
flag is not specified, the output will not repeat.
.Pp
-The
-.Fl C
-flag requests the printing of additional capability information in the file
-descriptor view.
-.Pp
-The
-.Fl H
-flag may be used to request per-thread statistics rather than per-process
-statistics for some options.
-For those options, the second field in the table will list the thread ID
-to which the row of information corresponds.
-The
-.Fl H
-flag is implied for the
-.Fl S
-mode.
-.Pp
Information for VM, file descriptor, and cpuset options is available
only to the owner of a process or the superuser.
A cpuset value displayed as -1 means that the information is either invalid
Index: usr.bin/procstat/procstat.c
===================================================================
--- usr.bin/procstat/procstat.c
+++ usr.bin/procstat/procstat.c
@@ -42,37 +42,111 @@
#include "procstat.h"
-static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag;
-static int lflag, Lflag, rflag, sflag, tflag, vflag, xflag, Sflag;
-int hflag, nflag, Cflag, Hflag;
+enum {
+ PS_CMP_NORMAL = 0x00,
+ PS_CMP_PLURAL = 0x01,
+ PS_CMP_SUBSTR = 0x02
+};
+
+struct procstat_cmd {
+ const char *command;
+ const char *xocontainer;
+ const char *usage;
+ void (*cmd)(struct procstat *, struct kinfo_proc *);
+ void (*opt)(int, char * const *);
+ int cmp;
+};
+
+int procstat_opts = 0;
+
+static void cmdopt_none(int argc, char * const argv[]);
+static void cmdopt_verbose(int argc, char * const argv[]);
+static void cmdopt_signals(int argc, char * const argv[]);
+static void cmdopt_rusage(int argc, char * const argv[]);
+static void cmdopt_files(int argc, char * const argv[]);
+static void cmdopt_cpuset(int argc, char * const argv[]);
+
+static const struct procstat_cmd cmd_table[] = {
+ { "argument", "arguments", NULL, &procstat_args, &cmdopt_none,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "auxv", "auxv", NULL, &procstat_auxv, &cmdopt_none, PS_CMP_NORMAL },
+ { "basic", "basic", NULL, &procstat_basic, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "binary", "binary", NULL, &procstat_bin, &cmdopt_none,
+ PS_CMP_SUBSTR },
+ { "cpuset", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL },
+ { "cs", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL },
+ { "credential", "credentials", NULL, &procstat_cred, &cmdopt_none,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "environment", "environment", NULL, &procstat_env, &cmdopt_none,
+ PS_CMP_SUBSTR },
+ { "fd", "files", "[-C]", &procstat_files, &cmdopt_files,
+ PS_CMP_PLURAL },
+ { "file", "files", "[-C]", &procstat_files, &cmdopt_files,
+ PS_CMP_PLURAL },
+ { "kstack", "kstack", "[-v]", &procstat_kstack, &cmdopt_verbose,
+ PS_CMP_NORMAL },
+ { "ptlwpinfo", "ptlwpinfo", NULL, &procstat_ptlwpinfo, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "rlimit", "rlimit", NULL, &procstat_rlimit, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "rusage", "rusage", "[-Ht]", &procstat_rusage, &cmdopt_rusage,
+ PS_CMP_NORMAL },
+ { "signal", "signals", "[-n]", &procstat_sigs, &cmdopt_signals,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "thread", "threads", NULL, &procstat_threads, &cmdopt_none,
+ PS_CMP_PLURAL },
+ { "tsignal", "thread_signals", "[-n]", &procstat_threads_sigs,
+ &cmdopt_signals, PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "vm", "vm", NULL, &procstat_vm, &cmdopt_none, PS_CMP_NORMAL }
+};
static void
usage(void)
{
-
- xo_error(
- "usage: procstat [--libxo] [-Hhn] [-M core] "
- "[-N system] [-w interval]\n"
- " [-S | -b | -c | -e | -i | -j | -k | -kk | "
- "-l | -r | -s | \n"
- " -t | -v | -x]\n"
- " [-a | pid ... | core ...]\n"
- " procstat [--libxo] -Cf [-hn] [-M core] "
- "[-N system] [-a | pid ... | core ...]\n"
- " [-S | -b | -c | -e | -i | -j | -k | -kk | "
- "-l | -r | -s | \n"
- " procstat [--libxo] -L [-hn] [-M core] "
- "[-N system] [-w interval]\n"
- " [-S | -b | -c | -e | -i | -j | -k | -kk | "
- "-l | -r | -s | \n"
- " -t | -v | -x]\n"
- " [core ...]\n");
+ size_t i, l;
+ int multi;
+
+ xo_error("usage: procstat [--libxo] [-h] [-M core] [-N system]"
+ " [-w interval] command\n"
+ " [pid ... | core ...]\n"
+ " procstat [--libxo] -a [-h] [-M core] [-N system] "
+ " [-w interval] command\n"
+ " procstat [--libxo] [-h] [-M core] [-N system]"
+ " [-w interval]\n"
+ " [-S | -b | -c | -e | -f [-C] | -i [-n] | "
+ "-j [-n] | -k [-k] |\n"
+ " -l | -r [-H] | -s | -t | -v | -x] "
+ "[pid ... | core ...]\n"
+ " procstat [--libxo] -a [-h] [-M core] [-N system]"
+ " [-w interval]\n"
+ " [-S | -b | -c | -e | -f [-C] | -i [-n] | "
+ "-j [-n] | -k [-k] |\n"
+ " -l | -r [-H] | -s | -t | -v | -x]\n"
+ " procstat [--libxo] -L [-h] [-M core] [-N system] core ...\n"
+ "Available commands:\n");
+ for (i = 0, l = nitems(cmd_table); i < l; i++) {
+ multi = i + 1 < l && cmd_table[i].cmd == cmd_table[i + 1].cmd;
+ xo_error(" %s%s%s", multi ? "[" : "",
+ cmd_table[i].command, (cmd_table[i].cmp & PS_CMP_PLURAL) ?
+ "(s)" : "");
+ for (; i + 1 < l && cmd_table[i].cmd == cmd_table[i + 1].cmd;
+ i++)
+ xo_error(" | %s%s", cmd_table[i + 1].command,
+ (cmd_table[i].cmp & PS_CMP_PLURAL) ? "(s)" : "");
+ if (multi)
+ xo_error("]");
+ if (cmd_table[i].usage != NULL)
+ xo_error(" %s", cmd_table[i].usage);
+ xo_error("\n");
+ }
xo_finish();
exit(EX_USAGE);
}
static void
-procstat(struct procstat *prstat, struct kinfo_proc *kipp)
+procstat(const struct procstat_cmd *cmd, struct procstat *prstat,
+ struct kinfo_proc *kipp)
{
char *pidstr = NULL;
@@ -80,40 +154,7 @@
if (pidstr == NULL)
xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()");
xo_open_container(pidstr);
-
- if (bflag)
- procstat_bin(prstat, kipp);
- else if (cflag)
- procstat_args(prstat, kipp);
- else if (eflag)
- procstat_env(prstat, kipp);
- else if (fflag)
- procstat_files(prstat, kipp);
- else if (iflag)
- procstat_sigs(prstat, kipp);
- else if (jflag)
- procstat_threads_sigs(prstat, kipp);
- else if (kflag)
- procstat_kstack(prstat, kipp, kflag);
- else if (lflag)
- procstat_rlimit(prstat, kipp);
- else if (Lflag)
- procstat_ptlwpinfo(prstat);
- else if (rflag)
- procstat_rusage(prstat, kipp);
- else if (sflag)
- procstat_cred(prstat, kipp);
- else if (tflag)
- procstat_threads(prstat, kipp);
- else if (vflag)
- procstat_vm(prstat, kipp);
- else if (xflag)
- procstat_auxv(prstat, kipp);
- else if (Sflag)
- procstat_cs(prstat, kipp);
- else
- procstat_basic(kipp);
-
+ cmd->cmd(prstat, kipp);
xo_close_container(pidstr);
free(pidstr);
}
@@ -157,122 +198,158 @@
return (name);
}
+static const struct procstat_cmd *
+getcmd(const char *str)
+{
+ const struct procstat_cmd *cmd;
+ size_t i, l;
+ int cmp, s;
+
+ if (str == NULL)
+ return (NULL);
+ cmd = NULL;
+ if ((l = strlen(str)) == 0)
+ return (getcmd("basic"));
+ s = l > 1 && strcasecmp(str + l - 1, "s") == 0;
+ for (i = 0; i < nitems(cmd_table); i++) {
+ /*
+ * After the first match substring matches are disabled,
+ * allowing subsequent full matches to take precedence.
+ */
+ if (cmd == NULL && (cmd_table[i].cmp & PS_CMP_SUBSTR))
+ cmp = strncasecmp(str, cmd_table[i].command, l -
+ ((cmd_table[i].cmp & PS_CMP_PLURAL) && s ? 1 : 0));
+ else if ((cmd_table[i].cmp & PS_CMP_PLURAL) && s &&
+ l == strlen(cmd_table[i].command) + 1)
+ cmp = strncasecmp(str, cmd_table[i].command, l - 1);
+ else
+ cmp = strcasecmp(str, cmd_table[i].command);
+ if (cmp == 0)
+ cmd = &cmd_table[i];
+ }
+ return (cmd);
+}
+
int
main(int argc, char *argv[])
{
- int ch, interval, tmp;
+ int ch, interval;
int i;
struct kinfo_proc *p;
+ const struct procstat_cmd *cmd;
struct procstat *prstat, *cprstat;
long l;
pid_t pid;
char *dummy;
char *nlistf, *memf;
- const char *xocontainer;
+ int aflag;
int cnt;
interval = 0;
+ cmd = NULL;
memf = nlistf = NULL;
+ aflag = 0;
argc = xo_parse_args(argc, argv);
- xocontainer = "basic";
while ((ch = getopt(argc, argv, "abCcefHhijkLlM:N:nrSstvw:x")) != -1) {
switch (ch) {
- case 'C':
- Cflag++;
- break;
-
- case 'H':
- Hflag++;
- break;
-
- case 'M':
- memf = optarg;
- break;
- case 'N':
- nlistf = optarg;
- break;
- case 'S':
- Sflag++;
- xocontainer = "cs";
- break;
case 'a':
aflag++;
break;
-
case 'b':
- bflag++;
- xocontainer = "binary";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("binary");
+ break;
+ case 'C':
+ procstat_opts |= PS_OPT_CAPABILITIES;
break;
-
case 'c':
- cflag++;
- xocontainer = "arguments";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("arguments");
break;
-
case 'e':
- eflag++;
- xocontainer = "environment";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("environment");
break;
-
case 'f':
- fflag++;
- xocontainer = "files";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("files");
+ break;
+ case 'H':
+ procstat_opts |= PS_OPT_PERTHREAD;
+ break;
+ case 'h':
+ procstat_opts |= PS_OPT_NOHEADER;
break;
-
case 'i':
- iflag++;
- xocontainer = "signals";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("signals");
break;
-
case 'j':
- jflag++;
- xocontainer = "thread_signals";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("tsignals");
break;
-
case 'k':
- kflag++;
- xocontainer = "kstack";
+ if (cmd->cmd == procstat_kstack) {
+ if ((procstat_opts & PS_OPT_VERBOSE) != 0)
+ usage();
+ procstat_opts |= PS_OPT_VERBOSE;
+ } else {
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("kstack");
+ }
+ break;
+ case 'L':
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("ptlwpinfo");
break;
-
case 'l':
- lflag++;
- xocontainer = "rlimit";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("rlimit");
break;
-
- case 'L':
- Lflag++;
- xocontainer = "ptlwpinfo";
+ case 'M':
+ memf = optarg;
break;
-
- case 'n':
- nflag++;
+ case 'N':
+ nlistf = optarg;
break;
-
- case 'h':
- hflag++;
+ case 'n':
+ procstat_opts |= PS_OPT_SIGNUM;
break;
-
case 'r':
- rflag++;
- xocontainer = "rusage";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("rusage");
+ break;
+ case 'S':
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("cpuset");
break;
-
case 's':
- sflag++;
- xocontainer = "credentials";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("credentials");
break;
-
case 't':
- tflag++;
- xocontainer = "threads";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("threads");
break;
-
case 'v':
- vflag++;
- xocontainer = "vm";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("vm");
break;
-
case 'w':
l = strtol(optarg, &dummy, 10);
if (*dummy != '\0')
@@ -281,12 +358,11 @@
usage();
interval = l;
break;
-
case 'x':
- xflag++;
- xocontainer = "auxv";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("auxv");
break;
-
case '?':
default:
usage();
@@ -296,24 +372,31 @@
argc -= optind;
argv += optind;
- /* We require that either 0 or 1 mode flags be set. */
- tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) +
- lflag + rflag + sflag + tflag + vflag + xflag + Sflag;
- if (!(tmp == 0 || tmp == 1))
- usage();
-
- /* We allow -k to be specified up to twice, but not more. */
- if (kflag > 2)
- usage();
+ if (cmd == NULL && argv[0] != NULL && (cmd = getcmd(argv[0])) != NULL) {
+ if ((procstat_opts & PS_SUBCOMMAND_OPTS) != 0)
+ usage();
+ if (cmd->opt != NULL) {
+ optreset = 1;
+ optind = 1;
+ cmd->opt(argc, argv);
+ argc -= optind;
+ argv += optind;
+ } else {
+ argc -= 1;
+ argv += 1;
+ }
+ } else {
+ if (cmd == NULL)
+ cmd = getcmd("basic");
+ if (cmd->cmd != procstat_files &&
+ (procstat_opts & PS_OPT_CAPABILITIES) != 0)
+ usage();
+ }
/* Must specify either the -a flag or a list of pids. */
if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
usage();
- /* Only allow -C with -f. */
- if (Cflag && !fflag)
- usage();
-
if (memf != NULL)
prstat = procstat_open_kvm(nlistf, memf);
else
@@ -323,7 +406,7 @@
do {
xo_set_version(PROCSTAT_XO_VERSION);
xo_open_container("procstat");
- xo_open_container(xocontainer);
+ xo_open_container(cmd->xocontainer);
if (aflag) {
p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
@@ -331,10 +414,10 @@
xo_errx(1, "procstat_getprocs()");
kinfo_proc_sort(p, cnt);
for (i = 0; i < cnt; i++) {
- procstat(prstat, &p[i]);
+ procstat(cmd, prstat, &p[i]);
/* Suppress header after first process. */
- hflag = 1;
+ procstat_opts |= PS_OPT_NOHEADER;
xo_flush();
}
procstat_freeprocs(prstat, p);
@@ -351,7 +434,7 @@
if (p == NULL)
xo_errx(1, "procstat_getprocs()");
if (cnt != 0)
- procstat(prstat, p);
+ procstat(cmd, prstat, p);
procstat_freeprocs(prstat, p);
} else {
cprstat = procstat_open_core(argv[i]);
@@ -364,15 +447,15 @@
if (p == NULL)
xo_errx(1, "procstat_getprocs()");
if (cnt != 0)
- procstat(cprstat, p);
+ procstat(cmd, cprstat, p);
procstat_freeprocs(cprstat, p);
procstat_close(cprstat);
}
/* Suppress header after first process. */
- hflag = 1;
+ procstat_opts |= PS_OPT_NOHEADER;
}
- xo_close_container(xocontainer);
+ xo_close_container(cmd->xocontainer);
xo_close_container("procstat");
xo_finish();
if (interval)
@@ -383,3 +466,95 @@
exit(0);
}
+
+void
+cmdopt_none(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ case '?':
+ default:
+ usage();
+ }
+ }
+}
+
+void
+cmdopt_verbose(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ procstat_opts |= PS_OPT_VERBOSE;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+}
+
+void
+cmdopt_signals(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "n")) != -1) {
+ switch (ch) {
+ case 'n':
+ procstat_opts |= PS_OPT_SIGNUM;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+}
+
+void
+cmdopt_rusage(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "Ht")) != -1) {
+ switch (ch) {
+ case 'H':
+ /* FALLTHROUGH */
+ case 't':
+ procstat_opts |= PS_OPT_PERTHREAD;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+}
+
+void
+cmdopt_files(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "C")) != -1) {
+ switch (ch) {
+ case 'C':
+ procstat_opts |= PS_OPT_CAPABILITIES;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+}
+
+void
+cmdopt_cpuset(int argc, char * const argv[])
+{
+
+ procstat_opts |= PS_OPT_PERTHREAD;
+ cmdopt_none(argc, argv);
+}
Index: usr.bin/procstat/procstat_args.c
===================================================================
--- usr.bin/procstat/procstat_args.c
+++ usr.bin/procstat/procstat_args.c
@@ -47,7 +47,7 @@
int i;
char **args;
- if (!hflag) {
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ARGS");
}
@@ -74,7 +74,7 @@
int i;
char **envs;
- if (!hflag) {
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
}
Index: usr.bin/procstat/procstat_auxv.c
===================================================================
--- usr.bin/procstat/procstat_auxv.c
+++ usr.bin/procstat/procstat_auxv.c
@@ -51,7 +51,7 @@
u_int count, i;
static char prefix[256];
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %-16s %-16s %-16s}\n", "PID", "COMM", "AUXV",
"VALUE");
Index: usr.bin/procstat/procstat_basic.c
===================================================================
--- usr.bin/procstat/procstat_basic.c
+++ usr.bin/procstat/procstat_basic.c
@@ -39,10 +39,10 @@
#include "procstat.h"
void
-procstat_basic(struct kinfo_proc *kipp)
+procstat_basic(struct procstat *procstat __unused, struct kinfo_proc *kipp)
{
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s}\n",
"PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN",
"WCHAN", "EMUL", "COMM");
Index: usr.bin/procstat/procstat_bin.c
===================================================================
--- usr.bin/procstat/procstat_bin.c
+++ usr.bin/procstat/procstat_bin.c
@@ -46,7 +46,7 @@
int osrel;
static char pathname[PATH_MAX];
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %-16s %8s %s}\n", "PID", "COMM", "OSREL",
"PATH");
Index: usr.bin/procstat/procstat_cred.c
===================================================================
--- usr.bin/procstat/procstat_cred.c
+++ usr.bin/procstat/procstat_cred.c
@@ -48,7 +48,7 @@
unsigned int i, ngroups;
gid_t *groups;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s}\n",
"PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID",
"SVGID", "UMASK", "FLAGS", "GROUPS");
Index: usr.bin/procstat/procstat_cs.c
===================================================================
--- usr.bin/procstat/procstat_cs.c
+++ usr.bin/procstat/procstat_cs.c
@@ -52,7 +52,7 @@
unsigned int count, i;
int once, twice, lastcpu, cpu;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s}\n", "PID",
"TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK");
Index: usr.bin/procstat/procstat_files.c
===================================================================
--- usr.bin/procstat/procstat_files.c
+++ usr.bin/procstat/procstat_files.c
@@ -303,7 +303,8 @@
*/
capwidth = 0;
head = procstat_getfiles(procstat, kipp, 0);
- if (head != NULL && Cflag) {
+ if (head != NULL &&
+ (procstat_opts & PS_OPT_CAPABILITIES) != 0) {
STAILQ_FOREACH(fst, head, next) {
width = width_capability(&fst->fs_cap_rights);
if (width > capwidth)
@@ -313,8 +314,8 @@
capwidth = strlen("CAPABILITIES");
}
- if (!hflag) {
- if (Cflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ if ((procstat_opts & PS_OPT_CAPABILITIES) != 0)
xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s "
"%-3s %-12s}\n", "PID", "COMM", "FD", "T",
"FLAGS", capwidth, "CAPABILITIES", "PRO",
@@ -417,7 +418,7 @@
break;
}
xo_emit("{d:fd_type/%1s/%s} ", str);
- if (!Cflag) {
+ if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) {
str = "-";
if (fst->fs_type == PS_FST_TYPE_VNODE) {
error = procstat_get_vnode_info(procstat, fst,
@@ -514,7 +515,7 @@
xo_emit("{elq:fd_flags/lock_held}");
xo_close_list("fd_flags");
- if (!Cflag) {
+ if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) {
if (fst->fs_ref_count > -1)
xo_emit("{:ref_count/%3d/%d} ",
fst->fs_ref_count);
@@ -526,7 +527,7 @@
else
xo_emit("{q:offset/%7c/%c} ", '-');
}
- if (Cflag) {
+ if ((procstat_opts & PS_OPT_CAPABILITIES) != 0) {
print_capability(&fst->fs_cap_rights, capwidth);
xo_emit(" ");
}
Index: usr.bin/procstat/procstat_kstack.c
===================================================================
--- usr.bin/procstat/procstat_kstack.c
+++ usr.bin/procstat/procstat_kstack.c
@@ -162,7 +162,7 @@
void
-procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp, int kflag)
+procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp)
{
struct kinfo_kstack *kkstp, *kkstp_free;
struct kinfo_proc *kip, *kip_free;
@@ -170,7 +170,7 @@
unsigned int i, j;
unsigned int kip_count, kstk_count;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %6s %-19s %-19s %-29s}\n", "PID", "TID", "COMM",
"TDNAME", "KSTACK");
@@ -234,9 +234,11 @@
* entries, but for a more compact view, we convert carriage
* returns to spaces.
*/
- kstack_cleanup(kkstp->kkst_trace, trace, kflag);
+ kstack_cleanup(kkstp->kkst_trace, trace,
+ (procstat_opts & PS_OPT_VERBOSE) != 0 ? 2 : 1);
xo_open_list("trace");
- kstack_cleanup_encoded(kkstp->kkst_trace, encoded_trace, kflag);
+ kstack_cleanup_encoded(kkstp->kkst_trace, encoded_trace,
+ (procstat_opts & PS_OPT_VERBOSE) != 0 ? 2 : 1);
xo_close_list("trace");
xo_emit("{d:trace/%-29s}\n", trace);
}
Index: usr.bin/procstat/procstat_ptlwpinfo.c
===================================================================
--- usr.bin/procstat/procstat_ptlwpinfo.c
+++ usr.bin/procstat/procstat_ptlwpinfo.c
@@ -36,7 +36,7 @@
#include "procstat.h"
void
-procstat_ptlwpinfo(struct procstat *prstat)
+procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp __unused)
{
struct ptrace_lwpinfo *pl;
unsigned int count, i;
@@ -45,7 +45,7 @@
if (pl == NULL)
return;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit(
"{T:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{T:/%s}{]:} {T:/%s}\n",
"LWPID", "EVENT", "SIGNO", "CODE", "ERRNO", "PID", "UID",
Index: usr.bin/procstat/procstat_rlimit.c
===================================================================
--- usr.bin/procstat/procstat_rlimit.c
+++ usr.bin/procstat/procstat_rlimit.c
@@ -94,7 +94,7 @@
struct rlimit rlimit;
int i;
- if (!hflag) {
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-16s %16s %16s}\n",
"PID", "COMM", "RLIMIT", "SOFT ", "HARD ");
}
Index: usr.bin/procstat/procstat_rusage.c
===================================================================
--- usr.bin/procstat/procstat_rusage.c
+++ usr.bin/procstat/procstat_rusage.c
@@ -106,7 +106,7 @@
{
xo_emit("{d:process_id/%5d/%d} ", kipp->ki_pid);
- if (Hflag)
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0)
xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
}
@@ -125,7 +125,7 @@
xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "system time",
format_time(&kipp->ki_rusage.ru_stime));
- if (Hflag) {
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0) {
asprintf(&threadid, "%d", kipp->ki_tid);
if (threadid == NULL)
xo_errc(1, ENOMEM,
@@ -154,7 +154,7 @@
rusage_info[i].ri_scale));
lp++;
}
- if (Hflag) {
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0) {
xo_close_container(threadid);
free(threadid);
}
@@ -166,15 +166,15 @@
struct kinfo_proc *kip;
unsigned int count, i;
- if (!hflag) {
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{d:ta/%5s} ", "PID");
- if (Hflag)
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0)
xo_emit("{d:tb/%6s} ", "TID");
xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE",
"VALUE ");
}
- if (!Hflag) {
+ if ((procstat_opts & PS_OPT_PERTHREAD) == 0) {
print_rusage(kipp);
return;
}
Index: usr.bin/procstat/procstat_sigs.c
===================================================================
--- usr.bin/procstat/procstat_sigs.c
+++ usr.bin/procstat/procstat_sigs.c
@@ -48,7 +48,7 @@
char name[12];
int i;
- if (!nflag && sig < sys_nsig) {
+ if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
strlcpy(name, sys_signame[sig], sizeof(name));
for (i = 0; name[i] != 0; i++)
name[i] = toupper(name[i]);
@@ -67,7 +67,7 @@
char name[12];
int i;
- if (!nflag && sig < sys_nsig) {
+ if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
strlcpy(name, sys_signame[sig], sizeof(name));
for (i = 0; name[i] != 0; i++)
name[i] = toupper(name[i]);
@@ -110,7 +110,7 @@
{
int j;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
"FLAGS");
@@ -139,7 +139,7 @@
unsigned int count, i;
char *threadid;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
"SIG", "FLAGS");
Index: usr.bin/procstat/procstat_threads.c
===================================================================
--- usr.bin/procstat/procstat_threads.c
+++ usr.bin/procstat/procstat_threads.c
@@ -48,7 +48,7 @@
const char *str;
char *threadid;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s %-9s}\n", "PID",
"TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN");
Index: usr.bin/procstat/procstat_vm.c
===================================================================
--- usr.bin/procstat/procstat_vm.c
+++ usr.bin/procstat/procstat_vm.c
@@ -50,7 +50,7 @@
const char *str, *lstr;
ptrwidth = 2*sizeof(void *) + 2;
- if (!hflag)
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %*s %*s %3s %4s %4s %3s %3s %-4s %-2s %-s}\n",
"PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
"PRES", "REF", "SHD", "FLAG", "TP", "PATH");
Index: usr.bin/procstat/tests/procstat_test.sh
===================================================================
--- usr.bin/procstat/tests/procstat_test.sh
+++ usr.bin/procstat/tests/procstat_test.sh
@@ -63,8 +63,11 @@
header_re=$(printf "$line_format" "PID" "COMM" "OSREL" "PATH")
line_re=$(printf "$line_format" $PROG_PID $PROG_COMM "[[:digit:]]+" "$PROG_PATH")
- atf_check -o save:procstat.out procstat -b $PROG_PID
+ atf_check -o save:procstat.out procstat binary $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+ atf_check -o save:procstat.out procstat -b $PROG_PID
atf_check -o match:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" tail -n 1 procstat.out
}
@@ -84,6 +87,10 @@
header_re=$(printf "$line_format" "PID" "COMM" "ARGS")
line_re=$(printf "$line_format" $PROG_PID "$PROG_COMM" "$PROG_PATH $arguments")
+ atf_check -o save:procstat.out procstat arguments $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+
atf_check -o save:procstat.out procstat -c $PROG_PID
atf_check -o match:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" tail -n 1 procstat.out
@@ -105,8 +112,11 @@
header_re=$(printf "$line_format" "PID" "COMM" "ENVIRONMENT")
line_re=$(printf "$line_format" $PROG_PID $PROG_COMM ".*$var.*")
- atf_check -o save:procstat.out procstat -e $PROG_PID
+ atf_check -o save:procstat.out procstat environment $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+ atf_check -o save:procstat.out procstat -e $PROG_PID
atf_check -o match:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" tail -n 1 procstat.out
}
@@ -125,8 +135,11 @@
# XXX: write a more sensible feature test
line_re=$(printf "$line_format" $PROG_PID $PROG_COMM ".+" ".+" ".+" ".+" ".+" ".+" ".+" ".+")
- atf_check -o save:procstat.out procstat -f $PROG_PID
+ atf_check -o save:procstat.out procstat files $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" awk 'NR > 1' procstat.out
+ atf_check -o save:procstat.out procstat -f $PROG_PID
atf_check -o match:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" awk 'NR > 1' procstat.out
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 8:11 PM (10 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28754446
Default Alt Text
D10916.id33986.diff (33 KB)
Attached To
Mode
D10916: usr.bin/procstat: Switch procstat from subcommand flags to verbs
Attached
Detach File
Event Timeline
Log In to Comment