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: kdrak...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to