aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/procstat
diff options
context:
space:
mode:
authorBrooks Davis <brooks@FreeBSD.org>2017-10-14 18:38:36 +0000
committerBrooks Davis <brooks@FreeBSD.org>2017-10-14 18:38:36 +0000
commit2a243b9539a45b392a515569cab2091844cf2bdf (patch)
treefa6c815477eaedfb7bc8c1882a778285119b5223 /usr.bin/procstat
parent8c8e10b763684442d614bc0eb978fd90789cd2a6 (diff)
downloadsrc-2a243b9539a45b392a515569cab2091844cf2bdf.tar.gz
src-2a243b9539a45b392a515569cab2091844cf2bdf.zip
Switch procstat from subcommand flags to verbs
- Use an enumerated value instead of separate flags for commands - Look for a verb if no command flag is set - Lookup the "xocontainer" value based on the command - Document the new command verbs in the man-page Submitted by: kdrakehp@zoho.com Differential Revision: https://reviews.freebsd.org/D10916
Notes
Notes: svn path=/head/; revision=324619
Diffstat (limited to 'usr.bin/procstat')
-rw-r--r--usr.bin/procstat/procstat.1174
-rw-r--r--usr.bin/procstat/procstat.c471
-rw-r--r--usr.bin/procstat/procstat.h21
-rw-r--r--usr.bin/procstat/procstat_args.c4
-rw-r--r--usr.bin/procstat/procstat_auxv.c2
-rw-r--r--usr.bin/procstat/procstat_basic.c4
-rw-r--r--usr.bin/procstat/procstat_bin.c2
-rw-r--r--usr.bin/procstat/procstat_cred.c2
-rw-r--r--usr.bin/procstat/procstat_cs.c2
-rw-r--r--usr.bin/procstat/procstat_files.c13
-rw-r--r--usr.bin/procstat/procstat_kstack.c10
-rw-r--r--usr.bin/procstat/procstat_ptlwpinfo.c4
-rw-r--r--usr.bin/procstat/procstat_rlimit.c2
-rw-r--r--usr.bin/procstat/procstat_rusage.c12
-rw-r--r--usr.bin/procstat/procstat_sigs.c8
-rw-r--r--usr.bin/procstat/procstat_threads.c2
-rw-r--r--usr.bin/procstat/procstat_vm.c2
-rwxr-xr-xusr.bin/procstat/tests/procstat_test.sh19
18 files changed, 520 insertions, 234 deletions
diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1
index cbd8061d1188..14b0e1eba17b 100644
--- a/usr.bin/procstat/procstat.1
+++ b/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 @@ flag is used, all processes.
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 @@ If the
.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
diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c
index 375664119821..7ab9ba458aea 100644
--- a/usr.bin/procstat/procstat.c
+++ b/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 @@ procstat(struct procstat *prstat, struct kinfo_proc *kipp)
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 @@ kinfo_proc_thread_name(const struct kinfo_proc *kipp)
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 @@ main(int argc, char *argv[])
usage();
interval = l;
break;
-
case 'x':
- xflag++;
- xocontainer = "auxv";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("auxv");
break;
-
case '?':
default:
usage();
@@ -296,24 +372,31 @@ main(int argc, char *argv[])
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 @@ main(int argc, char *argv[])
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 @@ main(int argc, char *argv[])
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 @@ main(int argc, char *argv[])
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 @@ main(int argc, char *argv[])
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 @@ main(int argc, char *argv[])
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);
+}
diff --git a/usr.bin/procstat/procstat.h b/usr.bin/procstat/procstat.h
index dd35c9c796c7..c75018fc0908 100644
--- a/usr.bin/procstat/procstat.h
+++ b/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 @@ const char * kinfo_proc_thread_name(const struct kinfo_proc *kipp);
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);
diff --git a/usr.bin/procstat/procstat_args.c b/usr.bin/procstat/procstat_args.c
index fd5f3d3b0738..b64364bd8d81 100644
--- a/usr.bin/procstat/procstat_args.c
+++ b/usr.bin/procstat/procstat_args.c
@@ -47,7 +47,7 @@ procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
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 @@ procstat_env(struct procstat *procstat, struct kinfo_proc *kipp)
int i;
char **envs;
- if (!hflag) {
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
}
diff --git a/usr.bin/procstat/procstat_auxv.c b/usr.bin/procstat/procstat_auxv.c
index f4a2265d762a..0c930cae9140 100644
--- a/usr.bin/procstat/procstat_auxv.c
+++ b/usr.bin/procstat/procstat_auxv.c
@@ -51,7 +51,7 @@ procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/procstat_basic.c b/usr.bin/procstat/procstat_basic.c
index 75bb7a8d9ef1..b5675248f88e 100644
--- a/usr.bin/procstat/procstat_basic.c
+++ b/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");
diff --git a/usr.bin/procstat/procstat_bin.c b/usr.bin/procstat/procstat_bin.c
index 8b2b8a14be8b..800775f3efe7 100644
--- a/usr.bin/procstat/procstat_bin.c
+++ b/usr.bin/procstat/procstat_bin.c
@@ -46,7 +46,7 @@ procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/procstat_cred.c b/usr.bin/procstat/procstat_cred.c
index 940c952a8324..dbc0831233d3 100644
--- a/usr.bin/procstat/procstat_cred.c
+++ b/usr.bin/procstat/procstat_cred.c
@@ -48,7 +48,7 @@ procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/procstat_cs.c b/usr.bin/procstat/procstat_cs.c
index 8af912edb749..7b8a61645be4 100644
--- a/usr.bin/procstat/procstat_cs.c
+++ b/usr.bin/procstat/procstat_cs.c
@@ -52,7 +52,7 @@ procstat_cs(struct procstat *procstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
index dcfa6619ea7d..25ae8ae26d58 100644
--- a/usr.bin/procstat/procstat_files.c
+++ b/usr.bin/procstat/procstat_files.c
@@ -303,7 +303,8 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
*/
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 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
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 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
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 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
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 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
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(" ");
}
diff --git a/usr.bin/procstat/procstat_kstack.c b/usr.bin/procstat/procstat_kstack.c
index 374f9d085692..225d939b22c4 100644
--- a/usr.bin/procstat/procstat_kstack.c
+++ b/usr.bin/procstat/procstat_kstack.c
@@ -162,7 +162,7 @@ kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count)
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 @@ procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp, int kflag)
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 @@ procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp, int kflag)
* 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);
}
diff --git a/usr.bin/procstat/procstat_ptlwpinfo.c b/usr.bin/procstat/procstat_ptlwpinfo.c
index 20ab95889e6c..f95bdab28b2d 100644
--- a/usr.bin/procstat/procstat_ptlwpinfo.c
+++ b/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 @@ procstat_ptlwpinfo(struct procstat *prstat)
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",
diff --git a/usr.bin/procstat/procstat_rlimit.c b/usr.bin/procstat/procstat_rlimit.c
index 5088c59767e9..dc0d486dbb2e 100644
--- a/usr.bin/procstat/procstat_rlimit.c
+++ b/usr.bin/procstat/procstat_rlimit.c
@@ -94,7 +94,7 @@ procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp)
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 ");
}
diff --git a/usr.bin/procstat/procstat_rusage.c b/usr.bin/procstat/procstat_rusage.c
index e14ae2470fef..3d8c76370c0c 100644
--- a/usr.bin/procstat/procstat_rusage.c
+++ b/usr.bin/procstat/procstat_rusage.c
@@ -106,7 +106,7 @@ print_prefix(struct kinfo_proc *kipp)
{
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 @@ print_rusage(struct kinfo_proc *kipp)
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 @@ print_rusage(struct kinfo_proc *kipp)
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 @@ procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp)
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;
}
diff --git a/usr.bin/procstat/procstat_sigs.c b/usr.bin/procstat/procstat_sigs.c
index 7bc73ec43471..59759b2b7899 100644
--- a/usr.bin/procstat/procstat_sigs.c
+++ b/usr.bin/procstat/procstat_sigs.c
@@ -48,7 +48,7 @@ procstat_print_signame(int sig)
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 @@ procstat_close_signame(int sig)
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 @@ procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
{
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 @@ procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/procstat_threads.c b/usr.bin/procstat/procstat_threads.c
index 40e1b4b15bae..a09f7e83584b 100644
--- a/usr.bin/procstat/procstat_threads.c
+++ b/usr.bin/procstat/procstat_threads.c
@@ -48,7 +48,7 @@ procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/procstat_vm.c b/usr.bin/procstat/procstat_vm.c
index 8c641e55aad5..9f38c6432651 100644
--- a/usr.bin/procstat/procstat_vm.c
+++ b/usr.bin/procstat/procstat_vm.c
@@ -50,7 +50,7 @@ procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
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");
diff --git a/usr.bin/procstat/tests/procstat_test.sh b/usr.bin/procstat/tests/procstat_test.sh
index a939f4f26cd7..06fa1f995522 100755
--- a/usr.bin/procstat/tests/procstat_test.sh
+++ b/usr.bin/procstat/tests/procstat_test.sh
@@ -63,8 +63,11 @@ binary_info_body()
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 @@ command_line_arguments_body()
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 @@ environment_body()
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 @@ file_descriptor_body()
# 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
}