Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145515817
D10916.id31070.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
32 KB
Referenced Files
None
Subscribers
None
D10916.id31070.diff
View Options
Index: usr.bin/procstat/procstat.h
===================================================================
--- usr.bin/procstat/procstat.h
+++ usr.bin/procstat/procstat.h
@@ -35,23 +35,34 @@
#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);
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);
Index: usr.bin/procstat/procstat.1
===================================================================
--- usr.bin/procstat/procstat.1
+++ usr.bin/procstat/procstat.1
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 26, 2017
+.Dd May 31, 2017
.Dt PROCSTAT 1
.Os
.Sh NAME
@@ -34,12 +34,36 @@
.Sh SYNOPSIS
.Nm
.Op Fl -libxo
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.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 CHhn
.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 ...
+.Op Ar pid | Ar core ...
+.Nm
+.Op Fl -libxo
+.Fl a
+.Op Fl CHhn
+.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
.Sh DESCRIPTION
The
.Nm
@@ -51,49 +75,88 @@
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
+sub-command 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
+sub-command 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
+sub-command 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
+sub-command 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
+sub-command 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
@@ -110,23 +173,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.
Index: usr.bin/procstat/procstat.c
===================================================================
--- usr.bin/procstat/procstat.c
+++ usr.bin/procstat/procstat.c
@@ -42,26 +42,110 @@
#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 **);
+ int cmp;
+};
+
+int procstat_opts = 0;
+
+static void cmdopt_none(int argc, char *argv[]);
+static void cmdopt_verbose(int argc, char *argv[]);
+static void cmdopt_signals(int argc, char *argv[]);
+static void cmdopt_rusage(int argc, char *argv[]);
+static void cmdopt_files(int argc, char *argv[]);
+static void cmdopt_cpuset(int argc, char *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 },
+ { "credential", "credentials", NULL, &procstat_cred, &cmdopt_none,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "cs", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL },
+ { "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)
{
+ size_t i;
+ size_t l;
+ int multi;
- xo_error("usage: procstat [--libxo] [-CHhn] [-M core] "
- "[-N system] [-w interval]\n"
- " [-b | -c | -e | -f | -i | -j | -k | "
- "-l | -L | -r | -s | \n"
+ xo_error("usage: procstat [--libxo] [-h] [-M core] [-N system]"
+ " [-w interval]\n"
+ " command [pid | core ...]\n"
+ " procstat [--libxo] -a [-h] [-M core] [-N system] "
+ " [-w interval]\n"
+ " command\n"
+ " procstat [--libxo] [-CHhn] [-M core]"
+ " [-N system] [-w interval]\n"
+ " [-b | -c | -e | -f | -i | -j | -k |"
+ " -l | -L | -r | -s |\n"
+ " -S | -t | -v | -x] [pid | core ...]\n"
+ " procstat [--libxo] -a [-CHhn] [-M core]"
+ " [-N system] [-w interval]\n"
+ " [-b | -c | -e | -f | -i | -j | -k |"
+ " -l | -L | -r | -s |\n"
" -S | -t | -v | -x]\n"
- " [-a | pid | 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;
@@ -69,40 +153,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);
}
@@ -146,122 +197,160 @@
return (name);
}
+static const struct procstat_cmd *
+getcmd(const char *str)
+{
+ const struct procstat_cmd *cmd;
+ size_t i;
+ size_t l;
+ int cmp;
+ int 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)
+ 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':
+ nlistf = optarg;
+ break;
case 'n':
- nflag++;
+ procstat_opts |= PS_OPT_SIGNUM;
break;
-
- case 'h':
- hflag++;
- 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')
@@ -270,12 +359,11 @@
usage();
interval = l;
break;
-
case 'x':
- xflag++;
- xocontainer = "auxv";
+ if (cmd != NULL)
+ usage();
+ cmd = getcmd("auxv");
break;
-
case '?':
default:
usage();
@@ -285,24 +373,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();
+ if (cmd == NULL && argv[0] != NULL && (cmd = getcmd(argv[0])) != NULL) {
+ if (procstat_opts & PS_SUBCOMMAND_OPTS)
+ 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))
+ usage();
+ }
- /* We allow -k to be specified up to twice, but not more. */
- if (kflag > 2)
- 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
@@ -312,7 +407,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);
@@ -320,10 +415,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);
@@ -340,7 +435,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]);
@@ -353,15 +448,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)
@@ -371,4 +466,96 @@
procstat_close(prstat);
exit(0);
+}
+
+void
+cmdopt_none(int argc, char *argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ case '?':
+ default:
+ usage();
+ }
+ }
+}
+
+void
+cmdopt_verbose(int argc, char *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 *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 *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 *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 *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)) {
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)) {
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))
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))
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))
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))
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))
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,7 @@
*/
capwidth = 0;
head = procstat_getfiles(procstat, kipp, 0);
- if (head != NULL && Cflag) {
+ if (head != NULL && (procstat_opts & PS_OPT_CAPABILITIES)) {
STAILQ_FOREACH(fst, head, next) {
width = width_capability(&fst->fs_cap_rights);
if (width > capwidth)
@@ -313,8 +313,8 @@
capwidth = strlen("CAPABILITIES");
}
- if (!hflag) {
- if (Cflag)
+ if (!(procstat_opts & PS_OPT_NOHEADER)) {
+ if (procstat_opts & PS_OPT_CAPABILITIES)
xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s "
"%-3s %-12s}\n", "PID", "COMM", "FD", "T",
"FLAGS", capwidth, "CAPABILITIES", "PRO",
@@ -412,7 +412,7 @@
break;
}
xo_emit("{d:fd_type/%1s/%s} ", str);
- if (!Cflag) {
+ if (!(procstat_opts & PS_OPT_CAPABILITIES)) {
str = "-";
if (fst->fs_type == PS_FST_TYPE_VNODE) {
error = procstat_get_vnode_info(procstat, fst,
@@ -509,7 +509,7 @@
xo_emit("{elq:fd_flags/lock_held}");
xo_close_list("fd_flags");
- if (!Cflag) {
+ if (!(procstat_opts & PS_OPT_CAPABILITIES)) {
if (fst->fs_ref_count > -1)
xo_emit("{:ref_count/%3d/%d} ",
fst->fs_ref_count);
@@ -521,7 +521,7 @@
else
xo_emit("{q:offset/%7c/%c} ", '-');
}
- if (Cflag) {
+ if (procstat_opts & PS_OPT_CAPABILITIES) {
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))
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) ? 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) ? 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))
xo_emit("{:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{:/%s}{]:}"
" {:/%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)) {
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)
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) {
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) {
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)) {
xo_emit("{d:ta/%5s} ", "PID");
- if (Hflag)
+ if (procstat_opts & PS_OPT_PERTHREAD)
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)) {
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) && 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) && 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))
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))
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))
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))
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
@@ -1,3 +1,4 @@
+#!/bin/sh
#
# Copyright (c) 2017 Ngie Cooper <ngie@FreeBSD.org>
# All rights reserved.
@@ -63,8 +64,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 +88,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 +113,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 +136,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
Sat, Feb 21, 8:49 PM (20 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28927551
Default Alt Text
D10916.id31070.diff (32 KB)
Attached To
Mode
D10916: usr.bin/procstat: Switch procstat from subcommand flags to verbs
Attached
Detach File
Event Timeline
Log In to Comment