Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Nov 2017 00:14:54 +0100
From:      Oliver Pinter <oliver.pinter@hardenedbsd.org>
To:        Brooks Davis <brooks@freebsd.org>
Cc:        "src-committers@freebsd.org" <src-committers@freebsd.org>,  "svn-src-all@freebsd.org" <svn-src-all@freebsd.org>,  "svn-src-head@freebsd.org" <svn-src-head@freebsd.org>
Subject:   Re: svn commit: r324619 - in head/usr.bin/procstat: . tests
Message-ID:  <CAPQ4ffvP90Mj_GDtzLhCbzM7TQQ=Xju3u_bSC7cBJo0uYw8kgw@mail.gmail.com>
In-Reply-To: <201710141838.v9EIcaOQ047300@repo.freebsd.org>
References:  <201710141838.v9EIcaOQ047300@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Saturday, October 14, 2017, Brooks Davis <brooks@freebsd.org> wrote:

> 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 <javascript:;>
>   Differential Revision:        https://reviews.freebsd.org/D10916


+= Release notes?


>
> 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-head@freebsd.org <javascript:;> mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-head
> To unsubscribe, send any mail to "svn-src-head-unsubscribe@freebsd.org
> <javascript:;>"
>



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