1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-18 02:19:39 +00:00

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
This commit is contained in:
Brooks Davis 2017-10-14 18:38:36 +00:00
parent 8c8e10b763
commit 2a243b9539
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324619
18 changed files with 529 additions and 243 deletions

View File

@ -25,7 +25,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd October 3, 2017 .Dd October 14, 2017
.Dt PROCSTAT 1 .Dt PROCSTAT 1
.Os .Os
.Sh NAME .Sh NAME
@ -34,14 +34,75 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl -libxo .Op Fl -libxo
.Op Fl CHhn .Op Fl h
.Op Fl M Ar core .Op Fl M Ar core
.Op Fl N Ar system .Op Fl N Ar system
.Op Fl w Ar interval .Op Fl w Ar interval
.Op Fl b | c | e | f | i | j | k | l | L | r | s | S | t | v | x .Ar command
.Op Fl a | Ar pid | Ar core ... .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 .Sh DESCRIPTION
The
.Nm .Nm
utility displays detailed information about the processes identified by the utility displays detailed information about the processes identified by the
.Ar pid .Ar pid
@ -51,49 +112,89 @@ flag is used, all processes.
It can also display information extracted from a process core file, if It can also display information extracted from a process core file, if
the core file is specified as the argument. the core file is specified as the argument.
.Pp .Pp
By default, basic process statistics are printed; one of the following If the
options may be specified in order to select more detailed process information .Fl -libxo
for printing: flag is specified the output is generated via
.Bl -tag -width indent
.It Fl -libxo
Generate output via
.Xr libxo 3 .Xr libxo 3
in a selection of different human and machine readable formats. in a selection of different human and machine readable formats.
See See
.Xr xo_parse_args 3 .Xr xo_parse_args 3
for details on command line arguments. 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. 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. 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. 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. 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. 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. 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 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. 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 .Pp
printed. If the
.It Fl l .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. 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. 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. 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. 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. Display the cpuset information for the thread.
.It Fl t .It Ar thread(s) | Fl t
Display thread information for the process. Display thread information for the process.
.It Fl v .It Ar vm | Fl v
Display virtual memory mappings for the process. Display virtual memory mappings for the process.
.It Fl x .It Ar auxv | Fl x
Display ELF auxiliary vector for the process. Display ELF auxiliary vector for the process.
.El .El
.Pp .Pp
@ -111,23 +212,6 @@ If the
.Fl w .Fl w
flag is not specified, the output will not repeat. flag is not specified, the output will not repeat.
.Pp .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 Information for VM, file descriptor, and cpuset options is available
only to the owner of a process or the superuser. only to the owner of a process or the superuser.
A cpuset value displayed as -1 means that the information is either invalid A cpuset value displayed as -1 means that the information is either invalid

View File

@ -42,37 +42,111 @@
#include "procstat.h" #include "procstat.h"
static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag; enum {
static int lflag, Lflag, rflag, sflag, tflag, vflag, xflag, Sflag; PS_CMP_NORMAL = 0x00,
int hflag, nflag, Cflag, Hflag; 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 static void
usage(void) usage(void)
{ {
size_t i, l;
int multi;
xo_error( xo_error("usage: procstat [--libxo] [-h] [-M core] [-N system]"
"usage: procstat [--libxo] [-Hhn] [-M core] " " [-w interval] command\n"
"[-N system] [-w interval]\n" " [pid ... | core ...]\n"
" [-S | -b | -c | -e | -i | -j | -k | -kk | " " procstat [--libxo] -a [-h] [-M core] [-N system] "
"-l | -r | -s | \n" " [-w interval] command\n"
" -t | -v | -x]\n" " procstat [--libxo] [-h] [-M core] [-N system]"
" [-a | pid ... | core ...]\n" " [-w interval]\n"
" procstat [--libxo] -Cf [-hn] [-M core] " " [-S | -b | -c | -e | -f [-C] | -i [-n] | "
"[-N system] [-a | pid ... | core ...]\n" "-j [-n] | -k [-k] |\n"
" [-S | -b | -c | -e | -i | -j | -k | -kk | " " -l | -r [-H] | -s | -t | -v | -x] "
"-l | -r | -s | \n" "[pid ... | core ...]\n"
" procstat [--libxo] -L [-hn] [-M core] " " procstat [--libxo] -a [-h] [-M core] [-N system]"
"[-N system] [-w interval]\n" " [-w interval]\n"
" [-S | -b | -c | -e | -i | -j | -k | -kk | " " [-S | -b | -c | -e | -f [-C] | -i [-n] | "
"-l | -r | -s | \n" "-j [-n] | -k [-k] |\n"
" -t | -v | -x]\n" " -l | -r [-H] | -s | -t | -v | -x]\n"
" [core ...]\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(); xo_finish();
exit(EX_USAGE); exit(EX_USAGE);
} }
static void 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; char *pidstr = NULL;
@ -80,40 +154,7 @@ procstat(struct procstat *prstat, struct kinfo_proc *kipp)
if (pidstr == NULL) if (pidstr == NULL)
xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()"); xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()");
xo_open_container(pidstr); xo_open_container(pidstr);
cmd->cmd(prstat, kipp);
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);
xo_close_container(pidstr); xo_close_container(pidstr);
free(pidstr); free(pidstr);
} }
@ -157,122 +198,158 @@ kinfo_proc_thread_name(const struct kinfo_proc *kipp)
return (name); 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 int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int ch, interval, tmp; int ch, interval;
int i; int i;
struct kinfo_proc *p; struct kinfo_proc *p;
const struct procstat_cmd *cmd;
struct procstat *prstat, *cprstat; struct procstat *prstat, *cprstat;
long l; long l;
pid_t pid; pid_t pid;
char *dummy; char *dummy;
char *nlistf, *memf; char *nlistf, *memf;
const char *xocontainer; int aflag;
int cnt; int cnt;
interval = 0; interval = 0;
cmd = NULL;
memf = nlistf = NULL; memf = nlistf = NULL;
aflag = 0;
argc = xo_parse_args(argc, argv); argc = xo_parse_args(argc, argv);
xocontainer = "basic";
while ((ch = getopt(argc, argv, "abCcefHhijkLlM:N:nrSstvw:x")) != -1) { while ((ch = getopt(argc, argv, "abCcefHhijkLlM:N:nrSstvw:x")) != -1) {
switch (ch) { switch (ch) {
case 'a':
aflag++;
break;
case 'b':
if (cmd != NULL)
usage();
cmd = getcmd("binary");
break;
case 'C': case 'C':
Cflag++; procstat_opts |= PS_OPT_CAPABILITIES;
break;
case 'c':
if (cmd != NULL)
usage();
cmd = getcmd("arguments");
break;
case 'e':
if (cmd != NULL)
usage();
cmd = getcmd("environment");
break;
case 'f':
if (cmd != NULL)
usage();
cmd = getcmd("files");
break; break;
case 'H': case 'H':
Hflag++; procstat_opts |= PS_OPT_PERTHREAD;
break;
case 'h':
procstat_opts |= PS_OPT_NOHEADER;
break;
case 'i':
if (cmd != NULL)
usage();
cmd = getcmd("signals");
break;
case 'j':
if (cmd != NULL)
usage();
cmd = getcmd("tsignals");
break;
case 'k':
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':
if (cmd != NULL)
usage();
cmd = getcmd("rlimit");
break; break;
case 'M': case 'M':
memf = optarg; memf = optarg;
break; break;
case 'N': case 'N':
nlistf = optarg; nlistf = optarg;
break; break;
case 'S':
Sflag++;
xocontainer = "cs";
break;
case 'a':
aflag++;
break;
case 'b':
bflag++;
xocontainer = "binary";
break;
case 'c':
cflag++;
xocontainer = "arguments";
break;
case 'e':
eflag++;
xocontainer = "environment";
break;
case 'f':
fflag++;
xocontainer = "files";
break;
case 'i':
iflag++;
xocontainer = "signals";
break;
case 'j':
jflag++;
xocontainer = "thread_signals";
break;
case 'k':
kflag++;
xocontainer = "kstack";
break;
case 'l':
lflag++;
xocontainer = "rlimit";
break;
case 'L':
Lflag++;
xocontainer = "ptlwpinfo";
break;
case 'n': case 'n':
nflag++; procstat_opts |= PS_OPT_SIGNUM;
break; break;
case 'h':
hflag++;
break;
case 'r': case 'r':
rflag++; if (cmd != NULL)
xocontainer = "rusage"; usage();
cmd = getcmd("rusage");
break;
case 'S':
if (cmd != NULL)
usage();
cmd = getcmd("cpuset");
break; break;
case 's': case 's':
sflag++; if (cmd != NULL)
xocontainer = "credentials"; usage();
cmd = getcmd("credentials");
break; break;
case 't': case 't':
tflag++; if (cmd != NULL)
xocontainer = "threads"; usage();
cmd = getcmd("threads");
break; break;
case 'v': case 'v':
vflag++; if (cmd != NULL)
xocontainer = "vm"; usage();
cmd = getcmd("vm");
break; break;
case 'w': case 'w':
l = strtol(optarg, &dummy, 10); l = strtol(optarg, &dummy, 10);
if (*dummy != '\0') if (*dummy != '\0')
@ -281,12 +358,11 @@ main(int argc, char *argv[])
usage(); usage();
interval = l; interval = l;
break; break;
case 'x': case 'x':
xflag++; if (cmd != NULL)
xocontainer = "auxv"; usage();
cmd = getcmd("auxv");
break; break;
case '?': case '?':
default: default:
usage(); usage();
@ -296,24 +372,31 @@ main(int argc, char *argv[])
argc -= optind; argc -= optind;
argv += optind; argv += optind;
/* We require that either 0 or 1 mode flags be set. */ if (cmd == NULL && argv[0] != NULL && (cmd = getcmd(argv[0])) != NULL) {
tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + if ((procstat_opts & PS_SUBCOMMAND_OPTS) != 0)
lflag + rflag + sflag + tflag + vflag + xflag + Sflag; usage();
if (!(tmp == 0 || tmp == 1)) if (cmd->opt != NULL) {
usage(); optreset = 1;
optind = 1;
/* We allow -k to be specified up to twice, but not more. */ cmd->opt(argc, argv);
if (kflag > 2) argc -= optind;
usage(); 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. */ /* Must specify either the -a flag or a list of pids. */
if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
usage(); usage();
/* Only allow -C with -f. */
if (Cflag && !fflag)
usage();
if (memf != NULL) if (memf != NULL)
prstat = procstat_open_kvm(nlistf, memf); prstat = procstat_open_kvm(nlistf, memf);
else else
@ -323,7 +406,7 @@ main(int argc, char *argv[])
do { do {
xo_set_version(PROCSTAT_XO_VERSION); xo_set_version(PROCSTAT_XO_VERSION);
xo_open_container("procstat"); xo_open_container("procstat");
xo_open_container(xocontainer); xo_open_container(cmd->xocontainer);
if (aflag) { if (aflag) {
p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
@ -331,10 +414,10 @@ main(int argc, char *argv[])
xo_errx(1, "procstat_getprocs()"); xo_errx(1, "procstat_getprocs()");
kinfo_proc_sort(p, cnt); kinfo_proc_sort(p, cnt);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
procstat(prstat, &p[i]); procstat(cmd, prstat, &p[i]);
/* Suppress header after first process. */ /* Suppress header after first process. */
hflag = 1; procstat_opts |= PS_OPT_NOHEADER;
xo_flush(); xo_flush();
} }
procstat_freeprocs(prstat, p); procstat_freeprocs(prstat, p);
@ -351,7 +434,7 @@ main(int argc, char *argv[])
if (p == NULL) if (p == NULL)
xo_errx(1, "procstat_getprocs()"); xo_errx(1, "procstat_getprocs()");
if (cnt != 0) if (cnt != 0)
procstat(prstat, p); procstat(cmd, prstat, p);
procstat_freeprocs(prstat, p); procstat_freeprocs(prstat, p);
} else { } else {
cprstat = procstat_open_core(argv[i]); cprstat = procstat_open_core(argv[i]);
@ -364,15 +447,15 @@ main(int argc, char *argv[])
if (p == NULL) if (p == NULL)
xo_errx(1, "procstat_getprocs()"); xo_errx(1, "procstat_getprocs()");
if (cnt != 0) if (cnt != 0)
procstat(cprstat, p); procstat(cmd, cprstat, p);
procstat_freeprocs(cprstat, p); procstat_freeprocs(cprstat, p);
procstat_close(cprstat); procstat_close(cprstat);
} }
/* Suppress header after first process. */ /* 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_close_container("procstat");
xo_finish(); xo_finish();
if (interval) if (interval)
@ -383,3 +466,95 @@ main(int argc, char *argv[])
exit(0); 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);
}

View File

@ -35,7 +35,19 @@
#define PROCSTAT_XO_VERSION "1" #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; struct kinfo_proc;
void kinfo_proc_sort(struct kinfo_proc *kipp, int count); 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_args(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_auxv(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_bin(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_cred(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_cs(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_env(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_files(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_kstack(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, struct kinfo_proc *kipp);
void procstat_ptlwpinfo(struct procstat *prstat);
void procstat_rlimit(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_rusage(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp);

View File

@ -47,7 +47,7 @@ procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
int i; int i;
char **args; char **args;
if (!hflag) { if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ARGS"); 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; int i;
char **envs; char **envs;
if (!hflag) { if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT"); xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
} }

View File

@ -51,7 +51,7 @@ procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
u_int count, i; u_int count, i;
static char prefix[256]; static char prefix[256];
if (!hflag) if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %-16s %-16s %-16s}\n", "PID", "COMM", "AUXV", xo_emit("{T:/%5s %-16s %-16s %-16s}\n", "PID", "COMM", "AUXV",
"VALUE"); "VALUE");

View File

@ -39,10 +39,10 @@
#include "procstat.h" #include "procstat.h"
void 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", xo_emit("{T:/%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s}\n",
"PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN", "PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN",
"WCHAN", "EMUL", "COMM"); "WCHAN", "EMUL", "COMM");

View File

@ -46,7 +46,7 @@ procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp)
int osrel; int osrel;
static char pathname[PATH_MAX]; 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", xo_emit("{T:/%5s %-16s %8s %s}\n", "PID", "COMM", "OSREL",
"PATH"); "PATH");

View File

@ -48,7 +48,7 @@ procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp)
unsigned int i, ngroups; unsigned int i, ngroups;
gid_t *groups; 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", xo_emit("{T:/%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s}\n",
"PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID", "PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID",
"SVGID", "UMASK", "FLAGS", "GROUPS"); "SVGID", "UMASK", "FLAGS", "GROUPS");

View File

@ -52,7 +52,7 @@ procstat_cs(struct procstat *procstat, struct kinfo_proc *kipp)
unsigned int count, i; unsigned int count, i;
int once, twice, lastcpu, cpu; 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", xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s}\n", "PID",
"TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK"); "TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK");

View File

@ -303,7 +303,8 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
*/ */
capwidth = 0; capwidth = 0;
head = procstat_getfiles(procstat, kipp, 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) { STAILQ_FOREACH(fst, head, next) {
width = width_capability(&fst->fs_cap_rights); width = width_capability(&fst->fs_cap_rights);
if (width > capwidth) if (width > capwidth)
@ -313,8 +314,8 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
capwidth = strlen("CAPABILITIES"); capwidth = strlen("CAPABILITIES");
} }
if (!hflag) { if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
if (Cflag) if ((procstat_opts & PS_OPT_CAPABILITIES) != 0)
xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s " xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s "
"%-3s %-12s}\n", "PID", "COMM", "FD", "T", "%-3s %-12s}\n", "PID", "COMM", "FD", "T",
"FLAGS", capwidth, "CAPABILITIES", "PRO", "FLAGS", capwidth, "CAPABILITIES", "PRO",
@ -417,7 +418,7 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
break; break;
} }
xo_emit("{d:fd_type/%1s/%s} ", str); xo_emit("{d:fd_type/%1s/%s} ", str);
if (!Cflag) { if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) {
str = "-"; str = "-";
if (fst->fs_type == PS_FST_TYPE_VNODE) { if (fst->fs_type == PS_FST_TYPE_VNODE) {
error = procstat_get_vnode_info(procstat, fst, 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_emit("{elq:fd_flags/lock_held}");
xo_close_list("fd_flags"); xo_close_list("fd_flags");
if (!Cflag) { if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) {
if (fst->fs_ref_count > -1) if (fst->fs_ref_count > -1)
xo_emit("{:ref_count/%3d/%d} ", xo_emit("{:ref_count/%3d/%d} ",
fst->fs_ref_count); fst->fs_ref_count);
@ -526,7 +527,7 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
else else
xo_emit("{q:offset/%7c/%c} ", '-'); xo_emit("{q:offset/%7c/%c} ", '-');
} }
if (Cflag) { if ((procstat_opts & PS_OPT_CAPABILITIES) != 0) {
print_capability(&fst->fs_cap_rights, capwidth); print_capability(&fst->fs_cap_rights, capwidth);
xo_emit(" "); xo_emit(" ");
} }

View File

@ -162,7 +162,7 @@ kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count)
void 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_kstack *kkstp, *kkstp_free;
struct kinfo_proc *kip, *kip_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 i, j;
unsigned int kip_count, kstk_count; 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", xo_emit("{T:/%5s %6s %-19s %-19s %-29s}\n", "PID", "TID", "COMM",
"TDNAME", "KSTACK"); "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 * entries, but for a more compact view, we convert carriage
* returns to spaces. * 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"); 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_close_list("trace");
xo_emit("{d:trace/%-29s}\n", trace); xo_emit("{d:trace/%-29s}\n", trace);
} }

View File

@ -36,7 +36,7 @@
#include "procstat.h" #include "procstat.h"
void void
procstat_ptlwpinfo(struct procstat *prstat) procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp __unused)
{ {
struct ptrace_lwpinfo *pl; struct ptrace_lwpinfo *pl;
unsigned int count, i; unsigned int count, i;
@ -45,7 +45,7 @@ procstat_ptlwpinfo(struct procstat *prstat)
if (pl == NULL) if (pl == NULL)
return; return;
if (!hflag) if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit( xo_emit(
"{T:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{T:/%s}{]:} {T:/%s}\n", "{T:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{T:/%s}{]:} {T:/%s}\n",
"LWPID", "EVENT", "SIGNO", "CODE", "ERRNO", "PID", "UID", "LWPID", "EVENT", "SIGNO", "CODE", "ERRNO", "PID", "UID",

View File

@ -94,7 +94,7 @@ procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp)
struct rlimit rlimit; struct rlimit rlimit;
int i; int i;
if (!hflag) { if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{T:/%5s %-16s %-16s %16s %16s}\n", xo_emit("{T:/%5s %-16s %-16s %16s %16s}\n",
"PID", "COMM", "RLIMIT", "SOFT ", "HARD "); "PID", "COMM", "RLIMIT", "SOFT ", "HARD ");
} }

View File

@ -106,7 +106,7 @@ print_prefix(struct kinfo_proc *kipp)
{ {
xo_emit("{d:process_id/%5d/%d} ", kipp->ki_pid); 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:thread_id/%6d/%d} ", kipp->ki_tid);
xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm); 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", xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "system time",
format_time(&kipp->ki_rusage.ru_stime)); format_time(&kipp->ki_rusage.ru_stime));
if (Hflag) { if ((procstat_opts & PS_OPT_PERTHREAD) != 0) {
asprintf(&threadid, "%d", kipp->ki_tid); asprintf(&threadid, "%d", kipp->ki_tid);
if (threadid == NULL) if (threadid == NULL)
xo_errc(1, ENOMEM, xo_errc(1, ENOMEM,
@ -154,7 +154,7 @@ print_rusage(struct kinfo_proc *kipp)
rusage_info[i].ri_scale)); rusage_info[i].ri_scale));
lp++; lp++;
} }
if (Hflag) { if ((procstat_opts & PS_OPT_PERTHREAD) != 0) {
xo_close_container(threadid); xo_close_container(threadid);
free(threadid); free(threadid);
} }
@ -166,15 +166,15 @@ procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp)
struct kinfo_proc *kip; struct kinfo_proc *kip;
unsigned int count, i; unsigned int count, i;
if (!hflag) { if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
xo_emit("{d:ta/%5s} ", "PID"); xo_emit("{d:ta/%5s} ", "PID");
if (Hflag) if ((procstat_opts & PS_OPT_PERTHREAD) != 0)
xo_emit("{d:tb/%6s} ", "TID"); xo_emit("{d:tb/%6s} ", "TID");
xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE", xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE",
"VALUE "); "VALUE ");
} }
if (!Hflag) { if ((procstat_opts & PS_OPT_PERTHREAD) == 0) {
print_rusage(kipp); print_rusage(kipp);
return; return;
} }

View File

@ -48,7 +48,7 @@ procstat_print_signame(int sig)
char name[12]; char name[12];
int i; int i;
if (!nflag && sig < sys_nsig) { if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
strlcpy(name, sys_signame[sig], sizeof(name)); strlcpy(name, sys_signame[sig], sizeof(name));
for (i = 0; name[i] != 0; i++) for (i = 0; name[i] != 0; i++)
name[i] = toupper(name[i]); name[i] = toupper(name[i]);
@ -67,7 +67,7 @@ procstat_close_signame(int sig)
char name[12]; char name[12];
int i; int i;
if (!nflag && sig < sys_nsig) { if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
strlcpy(name, sys_signame[sig], sizeof(name)); strlcpy(name, sys_signame[sig], sizeof(name));
for (i = 0; name[i] != 0; i++) for (i = 0; name[i] != 0; i++)
name[i] = toupper(name[i]); name[i] = toupper(name[i]);
@ -110,7 +110,7 @@ procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
{ {
int j; int j;
if (!hflag) if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG", xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
"FLAGS"); "FLAGS");
@ -139,7 +139,7 @@ procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
unsigned int count, i; unsigned int count, i;
char *threadid; char *threadid;
if (!hflag) if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM", xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
"SIG", "FLAGS"); "SIG", "FLAGS");

View File

@ -48,7 +48,7 @@ procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp)
const char *str; const char *str;
char *threadid; char *threadid;
if (!hflag) if ((procstat_opts & PS_OPT_NOHEADER) == 0)
xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s %-9s}\n", "PID", xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s %-9s}\n", "PID",
"TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN"); "TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN");

View File

@ -50,7 +50,7 @@ procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
const char *str, *lstr; const char *str, *lstr;
ptrwidth = 2*sizeof(void *) + 2; 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", xo_emit("{T:/%5s %*s %*s %3s %4s %4s %3s %3s %-4s %-2s %-s}\n",
"PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES", "PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
"PRES", "REF", "SHD", "FLAG", "TP", "PATH"); "PRES", "REF", "SHD", "FLAG", "TP", "PATH");

View File

@ -63,8 +63,11 @@ binary_info_body()
header_re=$(printf "$line_format" "PID" "COMM" "OSREL" "PATH") header_re=$(printf "$line_format" "PID" "COMM" "OSREL" "PATH")
line_re=$(printf "$line_format" $PROG_PID $PROG_COMM "[[:digit:]]+" "$PROG_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:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" tail -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") header_re=$(printf "$line_format" "PID" "COMM" "ARGS")
line_re=$(printf "$line_format" $PROG_PID "$PROG_COMM" "$PROG_PATH $arguments") 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 save:procstat.out procstat -c $PROG_PID
atf_check -o match:"$header_re" head -n 1 procstat.out 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 match:"$line_re" tail -n 1 procstat.out
@ -105,8 +112,11 @@ environment_body()
header_re=$(printf "$line_format" "PID" "COMM" "ENVIRONMENT") header_re=$(printf "$line_format" "PID" "COMM" "ENVIRONMENT")
line_re=$(printf "$line_format" $PROG_PID $PROG_COMM ".*$var.*") 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:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" tail -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 # XXX: write a more sensible feature test
line_re=$(printf "$line_format" $PROG_PID $PROG_COMM ".+" ".+" ".+" ".+" ".+" ".+" ".+" ".+") 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:"$header_re" head -n 1 procstat.out
atf_check -o match:"$line_re" awk 'NR > 1' procstat.out atf_check -o match:"$line_re" awk 'NR > 1' procstat.out
} }