Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Oct 2017 18:38:36 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324619 - in head/usr.bin/procstat: . tests
Message-ID:  <201710141838.v9EIcaOQ047300@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Sat Oct 14 18:38:36 2017
New Revision: 324619
URL: https://svnweb.freebsd.org/changeset/base/324619

Log:
  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

Modified:
  head/usr.bin/procstat/procstat.1
  head/usr.bin/procstat/procstat.c
  head/usr.bin/procstat/procstat.h
  head/usr.bin/procstat/procstat_args.c
  head/usr.bin/procstat/procstat_auxv.c
  head/usr.bin/procstat/procstat_basic.c
  head/usr.bin/procstat/procstat_bin.c
  head/usr.bin/procstat/procstat_cred.c
  head/usr.bin/procstat/procstat_cs.c
  head/usr.bin/procstat/procstat_files.c
  head/usr.bin/procstat/procstat_kstack.c
  head/usr.bin/procstat/procstat_ptlwpinfo.c
  head/usr.bin/procstat/procstat_rlimit.c
  head/usr.bin/procstat/procstat_rusage.c
  head/usr.bin/procstat/procstat_sigs.c
  head/usr.bin/procstat/procstat_threads.c
  head/usr.bin/procstat/procstat_vm.c
  head/usr.bin/procstat/tests/procstat_test.sh

Modified: head/usr.bin/procstat/procstat.1
==============================================================================
--- head/usr.bin/procstat/procstat.1	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat.1	Sat Oct 14 18:38:36 2017	(r324619)
@@ -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
@@ -110,23 +211,6 @@ of the requested process information.
 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.

Modified: head/usr.bin/procstat/procstat.c
==============================================================================
--- head/usr.bin/procstat/procstat.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -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)
 {
+	size_t i, l;
+	int multi;
 
-	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");
+	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 *k
 	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':
+			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')
@@ -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();
+	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();
+	}
 
-	/* 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
@@ -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)
@@ -382,4 +465,96 @@ main(int argc, char *argv[])
 	procstat_close(prstat);
 
 	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);
 }

Modified: head/usr.bin/procstat/procstat.h
==============================================================================
--- head/usr.bin/procstat/procstat.h	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat.h	Sat Oct 14 18:38:36 2017	(r324619)
@@ -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);

Modified: head/usr.bin/procstat/procstat_args.c
==============================================================================
--- head/usr.bin/procstat/procstat_args.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_args.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -47,7 +47,7 @@ procstat_args(struct procstat *procstat, struct kinfo_
 	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_p
 	int i;
 	char **envs;
 
-	if (!hflag) {
+	if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
 		xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
 	}
 

Modified: head/usr.bin/procstat/procstat_auxv.c
==============================================================================
--- head/usr.bin/procstat/procstat_auxv.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_auxv.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -51,7 +51,7 @@ procstat_auxv(struct procstat *procstat, struct kinfo_
 	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");
 

Modified: head/usr.bin/procstat/procstat_basic.c
==============================================================================
--- head/usr.bin/procstat/procstat_basic.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_basic.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -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");

Modified: head/usr.bin/procstat/procstat_bin.c
==============================================================================
--- head/usr.bin/procstat/procstat_bin.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_bin.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -46,7 +46,7 @@ procstat_bin(struct procstat *prstat, struct kinfo_pro
 	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");
 

Modified: head/usr.bin/procstat/procstat_cred.c
==============================================================================
--- head/usr.bin/procstat/procstat_cred.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_cred.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -48,7 +48,7 @@ procstat_cred(struct procstat *procstat, struct kinfo_
 	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");

Modified: head/usr.bin/procstat/procstat_cs.c
==============================================================================
--- head/usr.bin/procstat/procstat_cs.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_cs.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -52,7 +52,7 @@ procstat_cs(struct procstat *procstat, struct kinfo_pr
 	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");
 

Modified: head/usr.bin/procstat/procstat_files.c
==============================================================================
--- head/usr.bin/procstat/procstat_files.c	Sat Oct 14 17:51:25 2017	(r324618)
+++ head/usr.bin/procstat/procstat_files.c	Sat Oct 14 18:38:36 2017	(r324619)
@@ -303,7 +303,8 @@ procstat_files(struct procstat *procstat, struct kinfo
 	 */
 	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
 			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
 			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
 			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)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710141838.v9EIcaOQ047300>