the format string gets modified by parsefmt -- don't use it twice
[unix-history] / usr / src / bin / ps / ps.c
index b1c1760..79fe0e1 100644 (file)
@@ -12,328 +12,149 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)ps.c       5.29 (Berkeley) %G%";
+static char sccsid[] = "@(#)ps.c       5.42 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-#include <machine/pte.h>
-
 #include <sys/param.h>
 #include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
 #include <sys/user.h>
 #include <sys/user.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/proc.h>
 #include <sys/proc.h>
-#include <sys/vm.h>
-#include <sys/text.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
-#include <sys/mbuf.h>
+#include <sys/ioctl.h>
+#include <sys/kinfo.h>
 #include <nlist.h>
 #include <nlist.h>
-#include <pwd.h>
-#include <math.h>
+#include <kvm.h>
 #include <errno.h>
 #include <errno.h>
-#include <stddef.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
-#include <varargs.h>
-#include <kvm.h>
-#include "pathnames.h"
-
-struct usave {
-       struct  proc *u_procp;
-       struct  timeval u_start;
-       struct  rusage u_ru;
-       struct  rusage u_cru;
-       short   u_cmask;
-       char    u_acflag;
-};
+#include <paths.h>
+#include "ps.h"
 
 
-/*
- * to compute offset in common structures
- */
-#define        POFF(x)         offsetof(struct proc, x)
-#define        EOFF(x)         offsetof(struct eproc, x)
-#define        UOFF(x)         offsetof(struct usave, x)
-#define        ROFF(x)         offsetof(struct rusage, x)
+#ifdef SPPWAIT
+#define NEWVM
+#endif
 
 
-enum type      { CHAR, UCHAR, SHORT, USHORT, LONG, ULONG, KPTR };
+KINFO *kinfo;
+struct varent *vhead, *vtail;
 
 
-#define        UIDFMT  "u"
-#define UIDLEN 5
-#define PIDFMT "d"
-#define PIDLEN 5
-#define        USERLEN 8
+int    eval;                   /* exit value */
+int    rawcpu;                 /* -C */
+int    sumrusage;              /* -S */
+int    termwidth;              /* width of screen (0 == infinity) */
+int    totwidth;               /* calculated width of requested variables */
 
 
-int needuser, needcomm, neednlist;
+static int needuser, needcomm;
 
 
-int    command(), ucomm(), logname(), pvar(), evar(), uvar(), rvar(), uname(),
-       runame(), state(), pri(), tdev(), tname(), longtname(), started(),
-       lstarted(), wchan(), vsize(), rssize(), p_rssize(), cputime(),
-       pmem(), pcpu(), pagein(), maxrss(), tsize(), trss();
-       /**
-       utime(), stime(), ixrss(), idrss(), isrss();
-       **/
+enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT;
 
 uid_t  getuid();
 char   *ttyname();
 
 
 uid_t  getuid();
 char   *ttyname();
 
-struct var {
-       char    *name[4];       /* name(s) of variable */
-       char    *header;        /* default header */
-       int     flag;
-#define        USER    0x01    /* requires user structure */
-#define        LJUST   0x02    /* left adjust on output (trailing blanks) */
-#define        COMM    0x04    /* requires exec arguments and environment (XXX) */
-#define        NLIST   0x08    /* requires nlist to get extra variables */
-       int     (*oproc)();     /* output routine */
-       short   width;          /* printing width */
-       /*
-        * The following (optional) elements are hooks for passing information
-        * to the generic output routines: pvar, evar, uvar (those which print
-        * simple elements from well known structures: proc, eproc, usave)
-        */
-       int     off;            /* offset in structure */
-       enum    type type;      /* type of element */
-       char    *fmt;           /* printf format */
-       /*
-        * glue to link selected fields together
-        */
-       struct  var *next;
-}  var[] = {
-       {{"command", "comm", "args"}, "COMMAND", USER|LJUST|COMM,
-               command, 16},
-       {{"ucomm"}, "COMMAND",  LJUST, ucomm, MAXCOMLEN},
-       {{"logname"}, "LOGNAME", LJUST, logname, MAXLOGNAME},
-       {{"flag", "f"}, "F", 0, pvar, 7, POFF(p_flag), LONG, "x"},
-       {{"uid"}, "UID", 0, pvar, UIDLEN, POFF(p_uid),USHORT, UIDFMT},
-       {{"ruid"}, "RUID", 0, pvar, UIDLEN, POFF(p_ruid), USHORT, UIDFMT},
-       {{"svuid"}, "SVUID", 0, pvar, UIDLEN, POFF(p_svuid), USHORT, UIDFMT},
-       {{"rgid"}, "RGID", 0, pvar, UIDLEN, POFF(p_rgid), USHORT, UIDFMT},
-       {{"svgid"}, "SVGID", 0, pvar, UIDLEN, POFF(p_svgid), USHORT, UIDFMT},
-       {{"pid"}, "PID", 0, pvar, PIDLEN, POFF(p_pid),SHORT, PIDFMT},
-       {{"ppid"}, "PPID", 0, pvar, PIDLEN, POFF(p_ppid), SHORT, PIDFMT},
-       {{"cp", "cpu"}, "CP", 0, pvar, 3, POFF(p_cpu), UCHAR, "d"},
-       {{"xstat"}, "XSTAT", 0, pvar, 4, POFF(p_xstat), USHORT, "x"},
-       {{"poip"}, "POIP", 0, pvar, 4, POFF(p_poip), SHORT, "d"},
-       {{"nwchan"}, "WCHAN", 0, pvar, 6, POFF(p_wchan), KPTR, "x"},
-       {{"wchan"}, "WCHAN", LJUST, wchan, 6},
-       {{"rlink"}, "RLINK", 0, pvar, 8, POFF(p_rlink), KPTR, "x"},
-       {{"ktrace", "traceflag"}, "KTRACE",
-               0, pvar, 8, POFF(p_traceflag), LONG, "x"},
-       {{"ktracep", "tracep"}, "KTRACEP",
-               0, pvar, 8, POFF(p_tracep), LONG, "x"},
-       {{"sig", "pending"}, "PENDING",
-               0, pvar, 8, POFF(p_sig), LONG, "x"},
-       {{"sigmask", "blocked"}, "BLOCKED",
-               0, pvar, 8, POFF(p_sigmask), LONG, "x"},
-       {{"sigignore", "ignored"}, "IGNORED",
-               0, pvar, 8, POFF(p_sigignore), LONG, "x"},
-       {{"sigcatch", "caught"}, "CAUGHT",
-               0, pvar, 8, POFF(p_sigcatch), LONG, "x"},
-       {{"user", "uname"}, "USER", LJUST, uname, USERLEN},
-       {{"ruser", "runame"}, "RUSER", LJUST, runame, USERLEN},
-       {{"pgid"}, "PGID", 0, evar, PIDLEN, EOFF(e_pgid), USHORT, PIDFMT},
-       {{"jobc"}, "JOBC", 0, evar, 4, EOFF(e_jobc), SHORT, "d"},
-       {{"sess", "session"}, "SESS", 0, evar, 6, EOFF(e_sess), KPTR, "x"},
-       {{"tdev", "dev"}, "TDEV", 0, tdev, 4},
-       {{"tname", "tty", "tt"}, "TT", LJUST, tname, 3},
-       {{"longtname", "longtty"}, "TT", LJUST, longtname, 8},
-       {{"tpgid"}, "TPGID", 0, evar, 4, EOFF(e_tpgid), USHORT, PIDFMT},
-       {{"tsession", "tsess"}, "TSESS",
-               0, evar, 6, EOFF(e_tsess), KPTR, "x"},
-       {{"paddr", "procaddr"}, "PADDR",
-               0, evar, 6, EOFF(e_paddr), KPTR, "x"},
-       {{"state", "stat"}, "STAT", 0, state, 4},
-       {{"pri"}, "PRI", 0, pri, 3},
-       {{"usrpri"}, "UPR", 0, pvar, 3, POFF(p_usrpri), CHAR, "d"},
-       {{"nice", "ni"}, "NI", 0, pvar, 2, POFF(p_nice), CHAR, "d"},
-       {{"vsize", "vsz"}, "VSZ", 0, vsize, 5},
-       {{"rssize", "rsz"}, "RSZ", 0, rssize, 4},
-       {{"rss", "p_rss"}, "RSS", 0, p_rssize, 4},
-       {{"u_procp", "uprocp"}, "UPROCP",
-               USER, uvar, 6, UOFF(u_procp), KPTR, "x"},
-       {{"umask", "u_cmask"}, "UMASK",
-               USER, uvar, 3, UOFF(u_cmask), CHAR, "#o"},
-       {{"acflag", "acflg"}, "ACFLG",
-               USER, uvar, 3, UOFF(u_acflag), SHORT, "x"},
-       {{"start"}, "STARTED", USER|LJUST, started, 8},
-       {{"lstart"}, "STARTED", USER|LJUST, lstarted, 28},
-       {{"cputime", "time"}, "TIME", USER, cputime, 9},
-       {{"p_ru"}, "P_RU", 0, pvar, 6, POFF(p_ru), KPTR, "x"},
-       {{"pcpu", "%cpu"}, "%CPU", NLIST, pcpu, 4},
-       {{"pmem", "%mem"}, "%MEM", NLIST, pmem, 4},
-       {{"sl", "slp", "slptime"}, "SL",
-               0, pvar, 3, POFF(p_slptime), CHAR, "d"},
-       {{"re", "resident"}, "RE",
-               0, pvar, 3, POFF(p_time), CHAR, "d"},
-       {{"pagein", "majflt"}, "PAGEIN", USER, pagein, 6},
-       {{"lim", "maxrss"}, "LIM", 0, maxrss, 5},
-       {{"tsiz"}, "TSIZ", 0, tsize, 4},
-       {{"trs"}, "TRS", 0, trss, 3},
-       /***
-       {{"utime"}, "UTIME", USER, utime, 4},
-       {{"stime"}, "STIME", USER, stime, 4},
-       {{"ixrss"}, "IXRSS", USER, ixrss, 4},
-       {{"idrss"}, "IDRSS", USER, idrss, 4},
-       {{"isrss"}, "ISRSS", USER, isrss, 4},
-       ***/
-       {{"minflt"}, "MINFLT",
-               USER, rvar, 4, ROFF(ru_minflt), LONG, "d"},
-       {{"majflt"}, "MAJFLT",
-               USER, rvar, 4, ROFF(ru_majflt), LONG, "d"},
-       {{"nswap"}, "NSWAP",
-               USER, rvar, 4, ROFF(ru_nswap), LONG, "d"},
-       {{"inblock", "inblk"}, "INBLK",
-               USER, rvar, 4, ROFF(ru_inblock), LONG, "d"},
-       {{"oublock", "oublk"}, "OUBLK",
-               USER, rvar, 4, ROFF(ru_oublock), LONG, "d"},
-       {{"msgsnd"}, "MSGSND",
-               USER, rvar, 4, ROFF(ru_msgsnd), LONG, "d"},
-       {{"msgrcv"}, "MSGRCV",
-               USER, rvar, 4, ROFF(ru_msgrcv), LONG, "d"},
-       {{"nsignals", "nsigs"}, "NSIGS",
-               USER, rvar, 4, ROFF(ru_nsignals), LONG, "d"},
-       {{"nvcsw", "vcsw"}, "VCSW",
-               USER, rvar, 5, ROFF(ru_nvcsw), LONG, "d"},
-       {{"nivcsw", "ivcsw"}, "IVCSW",
-               USER, rvar, 5, ROFF(ru_nivcsw), LONG, "d"},
-       NULL
-};
-
-/*
- * combination variables
- */
-struct combovar {
-       char *name;
-       char *replace;
-} combovar[] = {
-       "RUSAGE", "minflt majflt nswap inblock oublock \
-               msgsnd msgrcv nsigs nvcsw nivcsw",
-       0, 0
-};
-#define DFMT   "pid tname state cputime comm"
-#define LFMT \
-       "uid pid ppid cp pri nice vsz rss wchan state tname cputime comm"
-#define        JFMT    "user pid ppid pgid sess jobc state tname cputime comm"
-#define        SFMT    "uid pid sig sigmask sigignore sigcatch stat tname comm"
-#define        VFMT \
-       "pid tt state time sl re pagein vsz rss lim tsiz trs %cpu %mem comm"
-#define UFMT \
-       "uname pid %cpu %mem vsz rss tt state start time comm"
-
-struct kinfo {
-       struct proc *ki_p;      /* proc structure */
-       struct eproc *ki_e;     /* extra stuff */
-       struct usave *ki_u;     /* interesting parts of user */
-       char *ki_args;          /* exec args (should be char **) */
-       char *ki_env;           /* environment (should be char **) */
-} *kinfo;
-
-struct var *vhead, *vtail;
-int    termwidth;      /* width of screen (0 == infinity) */
-#define UNLIMITED      0
-int    totwidth;       /* calculated width of requested variables */
-int    sumrusage;
-int    rawcpu;
-int    sortby;
-#define        SORTMEM 1
-#define        SORTCPU 2
-
-int    uid = -1;
-dev_t  ttydev = NODEV;
-int    pid = -1;
-int    all;
-int    xflg;
-int    prtheader;
-int    lineno;
+char dfmt[] = "pid tt state time command";
+char jfmt[] = "user pid ppid pgid sess jobc state tt time command";
+char lfmt[] = "uid pid ppid cpu pri nice vsz rss wchan state tt time command";
+char   o1[] = "pid";
+char   o2[] = "tt state time command";
+char ufmt[] = "user pid %cpu %mem vsz rss tt state start time command";
+char vfmt[] =
+       "pid state time sl re pagein vsz rss lim tsiz trs %cpu %mem command";
 
 
-/*
- * variables retrieved via nlist
- */
-struct nlist psnl[] = {
-       {"_ecmx"},
-#define        X_ECMX          0
-       {"_fscale"},
-#define        X_FSCALE        1
-       {"_ccpu"},
-#define        X_CCPU          2
-       {NULL}
-};
-int    fscale;
-int    ecmx;
-fixpt_t        ccpu;
-
-#define USAGE  "ps [ -(o|O) fmt ] [ -wlvujnsaxSCLmcr ] [ -p pid ] [ -t tty ]"
-
-main (argc, argv)
-       char *argv[];
+main(argc, argv)
+       int argc;
+       char **argv;
 {
        extern char *optarg;
        extern int optind;
 {
        extern char *optarg;
        extern int optind;
-       int ch;
-       register int i;
-       register struct var *v;
        register struct proc *p;
        register struct proc *p;
+       register size_t nentries;
+       register struct varent *vent;
+       register int i;
        struct winsize ws;
        struct winsize ws;
-       size_t nentries;
-       int fmt = 0;
+       dev_t ttydev;
+       int all, ch, flag, fmt, lineno, pid, prtheader, uid, what, xflg;
        int pscomp();
        int pscomp();
-       int what, flag;
+       char *nlistf, *memf, *swapf;
        char *kludge_oldps_options();
 
        char *kludge_oldps_options();
 
-       if ((ioctl(1, TIOCGWINSZ, (char *)&ws) == -1 &&
-            ioctl(2, TIOCGWINSZ, (char *)&ws) == -1 &&
-            ioctl(0, TIOCGWINSZ, (char *)&ws) == -1) ||
+       if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) == -1 &&
+            ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) == -1 &&
+            ioctl(STDIN_FILENO,  TIOCGWINSZ, (char *)&ws) == -1) ||
             ws.ws_col == 0)
                termwidth = 79;
        else
                termwidth = ws.ws_col - 1;
             ws.ws_col == 0)
                termwidth = 79;
        else
                termwidth = ws.ws_col - 1;
+
        if (argc > 1)
                argv[1] = kludge_oldps_options(argv[1]);
 
        if (argc > 1)
                argv[1] = kludge_oldps_options(argv[1]);
 
-       while ((ch = getopt(argc, argv, "o:O:wlvujnsaxt:p:SCLmrhTg")) != EOF)
+       fmt = 0;
+       all = xflg = 0;
+       pid = uid = -1;
+       ttydev = NODEV;
+       memf = nlistf = swapf = NULL;
+       while ((ch = getopt(argc, argv,
+           "aCghjLlM:mN:O:o:p:rSTt:uvW:wx")) != EOF)
                switch((char)ch) {
                switch((char)ch) {
-               case 'o':
-                       parsefmt(optarg);
-                       fmt++;
+               case 'a':
+                       all = 1;
                        break;
                        break;
-               case 'O':
-                       parsefmt("pid");
-                       parsefmt(optarg);
-                       parsefmt("state tt time command");
-                       fmt++;
+               case 'C':
+                       rawcpu = 1;
                        break;
                        break;
-               case 'w':
-                       if (termwidth < 131)
-                               termwidth = 131;
-                       else
-                               termwidth = UNLIMITED;
+               case 'g':
+                       break;  /* no-op */
+               case 'h':
+                       prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
+                       break;
+               case 'j':
+                       parsefmt(jfmt);
+                       fmt = 1;
+                       jfmt[0] = '\0';
                        break;
                        break;
+               case 'L': 
+                       showkey();
+                       exit(0);
                case 'l':
                case 'l':
-                       parsefmt(LFMT);
-                       fmt++;
+                       parsefmt(lfmt);
+                       fmt = 1;
+                       lfmt[0] = '\0';
                        break;
                        break;
-               case 'v':
-                       parsefmt(VFMT);
+               case 'M':
+                       memf = optarg;
+                       break;
+               case 'm':
                        sortby = SORTMEM;
                        sortby = SORTMEM;
-                       fmt++;
                        break;
                        break;
-               case 'u':
-                       parsefmt(UFMT);
-                       sortby = SORTCPU;
-                       fmt++;
+               case 'N':
+                       nlistf = optarg;
                        break;
                        break;
-               case 'j':
-                       parsefmt(JFMT);
-                       fmt++;
+               case 'O':
+                       parsefmt(o1);
+                       parsefmt(optarg);
+                       parsefmt(o2);
+                       o1[0] = o2[0] = '\0';
+                       fmt = 1;
+                       break;
+               case 'o':
+                       parsefmt(optarg);
+                       fmt = 1;
+                       break;
+               case 'p':
+                       pid = atoi(optarg);
+                       xflg = 1;
+                       break;
+               case 'r':
+                       sortby = SORTCPU;
                        break;
                        break;
-               case 's':
-                       parsefmt(SFMT);
-                       fmt++;
+               case 'S':
+                       sumrusage = 1;
                        break;
                case 'T':
                        break;
                case 'T':
-                       if ((optarg = ttyname(0)) == NULL)
-                               error("<stdin>: not a terminal");
+                       if ((optarg = ttyname(STDIN_FILENO)) == NULL)
+                               err("stdin: not a terminal");
                        /* FALLTHROUGH */
                case 't': {
                        char *ttypath;
                        /* FALLTHROUGH */
                case 't': {
                        char *ttypath;
@@ -348,82 +169,60 @@ main (argc, argv)
                        else
                                ttypath = optarg;
                        if (stat(ttypath, &stbuf) == -1)
                        else
                                ttypath = optarg;
                        if (stat(ttypath, &stbuf) == -1)
-                               syserror(ttypath);
-                       if ((stbuf.st_mode & S_IFMT) != S_IFCHR)
-                               error("%s: not a terminal", ttypath);
+                               err("%s: %s", ttypath, strerror(errno));
+                       if (!S_ISCHR(stbuf.st_mode))
+                               err("%s: not a terminal", ttypath);
                        ttydev = stbuf.st_rdev;
                        break;
                }
                        ttydev = stbuf.st_rdev;
                        break;
                }
-               case 'p':
-                       pid = atoi(optarg);
-                       xflg++;
+               case 'u':
+                       parsefmt(ufmt);
+                       sortby = SORTCPU;
+                       fmt = 1;
+                       ufmt[0] = '\0';
                        break;
                        break;
-               case 'S':
-                       sumrusage++;
+               case 'v':
+                       parsefmt(vfmt);
+                       sortby = SORTMEM;
+                       fmt = 1;
+                       vfmt[0] = '\0';
                        break;
                        break;
-               case 'C':
-                       rawcpu++;
+               case 'W':
+                       swapf = optarg;
                        break;
                        break;
-               case 'L': {
-                       struct combovar *cb = &combovar[0];
-                       char *cp, *sep = "";
-
-                       for (i = 0, v = &var[0];;) {
-                               if (v->name[0] != NULL)
-                                       cp = v++->name[0];
-                               else if (cb->name != NULL)
-                                       cp = cb++->name;
-                               else
-                                       break;
-                               if (termwidth &&
-                                   (i += strlen(cp) + 1) > termwidth)
-                                       i = strlen(cp), sep = "\n";
-                               (void) printf("%s%s", sep, cp);
-                               sep = " ";
-                       }
-                       (void) printf("\n");
-                       exit(0);
-               }
-               case 'a':
-                       all++;
+               case 'w':
+                       if (termwidth < 131)
+                               termwidth = 131;
+                       else
+                               termwidth = UNLIMITED;
                        break;
                case 'x':
                        break;
                case 'x':
-                       xflg++;
-                       break;
-               case 'm':
-                       sortby = SORTMEM;
+                       xflg = 1;
                        break;
                        break;
-               case 'r':
-                       sortby = SORTCPU;
-                       break;
-               case 'h':
-                       prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
-                       break;
-               case 'g':
-                       break;  /* no-op */
                case '?':
                default:
                case '?':
                default:
-                       (void) fprintf(stderr, "usage: %s\n", USAGE);
-                       exit(1);
+                       usage();
                }
        argc -= optind;
        argv += optind;
 
                }
        argc -= optind;
        argv += optind;
 
+#define        BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
        if (*argv) {
        if (*argv) {
-               char *nlistf, *memf = NULL, *swapf = NULL;
 
 
-               nlistf = *argv++;
-               if (*argv) {
-                       memf = *argv++;
-                       if (*argv)
-                               swapf = *argv++;
+               nlistf = *argv;
+               if (*++argv) {
+                       memf = *argv;
+                       if (*++argv)
+                               swapf = *argv;
                }
                }
-               if (kvm_openfiles(nlistf, memf, swapf) == -1)
-                       error("kvm_openfiles: %s", kvm_geterr());
        }
        }
+#endif
+       if (kvm_openfiles(nlistf, memf, swapf) == -1)
+               err("kvm_openfiles: %s", kvm_geterr());
 
        if (!fmt)
 
        if (!fmt)
-               parsefmt(DFMT);
+               parsefmt(dfmt);
 
        if (!all && ttydev == NODEV && pid == -1)  /* XXX - should be cleaner */
                uid = getuid();
 
        if (!all && ttydev == NODEV && pid == -1)  /* XXX - should be cleaner */
                uid = getuid();
@@ -433,12 +232,6 @@ main (argc, argv)
         * and adjusting header widths as appropiate.
         */
        scanvars();
         * and adjusting header widths as appropiate.
         */
        scanvars();
-#ifdef notdef
-       if (sortby == SORTCPU)
-               neednlist = 1;
-#endif
-       if (neednlist)
-               donlist();
        /*
         * get proc list
         */
        /*
         * get proc list
         */
@@ -454,22 +247,17 @@ main (argc, argv)
        /*
         * select procs
         */
        /*
         * select procs
         */
-       if ((nentries = kvm_getprocs(what, flag)) == -1) {
-               (void) fprintf(stderr, "ps: %s\n", kvm_geterr());
-               exit(1);
-       }
-       kinfo = (struct kinfo *)malloc(nentries * sizeof (struct kinfo));
+       if ((nentries = kvm_getprocs(what, flag)) == -1)
+               err("%s", kvm_geterr());
+       kinfo = malloc(nentries * sizeof(KINFO));
        if (kinfo == NULL)
        if (kinfo == NULL)
-               error("out of memory");
-       i = 0;
-       while ((p = kvm_nextproc()) != NULL) {
-               kinfo[i].ki_p = p;
-               kinfo[i].ki_e = kvm_geteproc(p);
+               err("%s", strerror(errno));
+       for (nentries = 0; p = kvm_nextproc(); ++nentries) {
+               kinfo[nentries].ki_p = p;
+               kinfo[nentries].ki_e = kvm_geteproc(p);
                if (needuser)
                if (needuser)
-                       saveuser(&kinfo[i]);
-               i++;
+                       saveuser(&kinfo[nentries]);
        }
        }
-       nentries = i;
        /*
         * print header
         */
        /*
         * print header
         */
@@ -479,17 +267,17 @@ main (argc, argv)
        /*
         * sort proc list
         */
        /*
         * sort proc list
         */
-       qsort((void *)kinfo, nentries, sizeof (struct kinfo), pscomp);
+       qsort((void *)kinfo, nentries, sizeof(KINFO), pscomp);
        /*
         * for each proc, call each variable output function.
         */
        /*
         * for each proc, call each variable output function.
         */
-       for (i = 0; i < nentries; i++) {
+       for (i = lineno = 0; i < nentries; i++) {
                if (xflg == 0 && (kinfo[i].ki_e->e_tdev == NODEV ||
                    (kinfo[i].ki_p->p_flag & SCTTY ) == 0))
                        continue;
                if (xflg == 0 && (kinfo[i].ki_e->e_tdev == NODEV ||
                    (kinfo[i].ki_p->p_flag & SCTTY ) == 0))
                        continue;
-               for (v = vhead; v != NULL; v = v->next) {
-                       (*v->oproc)(&kinfo[i], v);
-                       if (v->next != NULL)
+               for (vent = vhead; vent; vent = vent->next) {
+                       (*vent->var->oproc)(&kinfo[i], vent->var, vent->next);
+                       if (vent->next != NULL)
                                (void) putchar(' ');
                }
                (void) putchar('\n');
                                (void) putchar(' ');
                }
                (void) putchar('\n');
@@ -499,54 +287,17 @@ main (argc, argv)
                        lineno = 0;
                }
        }
                        lineno = 0;
                }
        }
-
-       exit(0);
-}
-
-#define FMTSEP " \t,\n"
-
-parsefmt(fmt)
-       char *fmt;
-{
-       register char *cp, *hp;
-       struct var *v;
-       char *lookupcombo();
-       struct var *lookupvar();
-
-       while (fmt) {
-               while ((cp = strsep(&fmt, FMTSEP)) != NULL && *cp == '\0')
-                       /* void */;
-               if ((hp = lookupcombo(cp)) != NULL) {
-                       parsefmt(hp);
-                       continue;
-               }
-               if ((hp = index(cp, '=')) != NULL)
-                       *hp++ = '\0';
-               v = lookupvar(cp);
-               if (v == NULL)
-                       error("unknown variable in format: %s", cp);
-               if (v->next != NULL || vtail == v) {
-                       (void) fprintf(stderr,
-                           "ps: can't specify a variable twice: %s\n", cp);
-                       continue;
-               }
-               if (hp)
-                       v->header = hp;
-               if (vhead == NULL)
-                       vhead = vtail = v;
-               else {
-                       vtail->next = v;
-                       vtail = v;
-               }
-       }
+       exit(eval);
 }
 
 scanvars()
 {
 }
 
 scanvars()
 {
-       register i;
-       register struct var *v;
+       register struct varent *vent;
+       register VAR *v;
+       register int i;
 
 
-       for (v = vhead; v != NULL; v = v->next) {
+       for (vent = vhead; vent; vent = vent->next) {
+               v = vent->var;
                i = strlen(v->header);
                if (v->width < i)
                        v->width = i;
                i = strlen(v->header);
                if (v->width < i)
                        v->width = i;
@@ -555,567 +306,57 @@ scanvars()
                        needuser = 1;
                if (v->flag & COMM)
                        needcomm = 1;
                        needuser = 1;
                if (v->flag & COMM)
                        needcomm = 1;
-               if (v->flag & NLIST)
-                       neednlist = 1;
        }
        totwidth--;
 }
 
        }
        totwidth--;
 }
 
-printheader()
-{
-       register struct var *v;
-
-       for (v = vhead; v != NULL; v = v->next) {
-               if (v->flag & LJUST) {
-                       if (v->next == NULL)    /* last one */
-                               (void) printf("%s", v->header);
-                       else
-                               (void) printf("%-*s", v->width, v->header);
-               } else
-                       (void) printf("%*s", v->width, v->header);
-               if (v->next != NULL)
-                       (void) putchar(' ');
-       }
-       (void) putchar('\n');
-}
-
-command(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       if (v->next == NULL) {
-               /* last field */
-               if (termwidth == UNLIMITED)
-                       (void) printf("%s", k->ki_args);
-               else {
-                       register int left = termwidth - (totwidth - v->width);
-                       register char *cp = k->ki_args;
-
-                       if (left < 1) /* already wrapped, just use std width */
-                               left = v->width;
-                       while (--left >= 0 && *cp)
-                               (void) putchar(*cp++);
-               }
-       } else
-               (void) printf("%-*.*s", v->width, v->width, k->ki_args);
-
-}
-
-ucomm(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%-*s", v->width, k->ki_p->p_comm);
-}
-
-logname(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%-*s", v->width, k->ki_p->p_logname);
-}
-
-state(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       char buf[16];
-       register char *cp = buf;
-       register struct proc *p = k->ki_p;
-       register flag = p->p_flag;
-
-       switch (p->p_stat) {
-
-       case SSTOP:
-               *cp = 'T';
-               break;
-
-       case SSLEEP:
-               if (flag & SSINTR)      /* interuptable (long) */
-                       *cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
-               else
-                       *cp = (flag & SPAGE) ? 'P' : 'D';
-               break;
-
-       case SRUN:
-       case SIDL:
-               *cp = 'R';
-               break;
-
-       case SZOMB:
-               *cp = 'Z';
-               break;
-
-       default:
-               *cp = '?';
-       }
-       cp++;
-       if (flag & SLOAD) {
-               if (p->p_rssize > p->p_maxrss)
-                       *cp++ = '>';
-       } else
-               *cp++ = 'W';
-       if (p->p_nice < NZERO)
-               *cp++ = '<';
-       else if (p->p_nice > NZERO)
-               *cp++ = 'N';
-       if (flag & SUANOM)
-               *cp++ = 'A';
-       else if (flag & SSEQL)
-               *cp++ = 'S';
-       if (flag & STRC)
-               *cp++ = 'X';
-       if (flag & SWEXIT)
-               *cp++ = 'E';
-       if (flag & SVFORK)
-               *cp++ = 'V';
-       if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO))
-               *cp++ = 'L';
-       if (k->ki_e->e_flag & EPROC_SLEADER)
-               *cp++ = 's';
-       if ((flag & SCTTY) && k->ki_e->e_pgid == k->ki_e->e_tpgid)
-               *cp++ = '+';
-       *cp = '\0';
-       (void) printf("%-*s", v->width, buf);
-}
-
-pri(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width, k->ki_p->p_pri - PZERO);
-}
-
-uname(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_uid, 0));
-}
-
-runame(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_ruid, 0));
-}
-
-tdev(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       dev_t dev = k->ki_e->e_tdev;
-
-       if (dev == NODEV)
-               (void) printf("%*s", v->width, "??");
-       else {
-               char buff[16];
-
-               (void) sprintf(buff, "%d/%d", major(dev), minor(dev));
-               (void) printf("%*s", v->width, buff);
-       }
-}
-
-extern char *devname();
-
-tname(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       dev_t dev = k->ki_e->e_tdev;
-       char *ttname;
-
-       if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
-               (void) printf("%-*s", v->width, "??");
-       else {
-               if (strncmp(ttname, "tty", 3) == 0)
-                       ttname += 3;
-               (void) printf("%*.*s%c", v->width-1, v->width-1, ttname,
-                       k->ki_e->e_flag & EPROC_CTTY ? ' ' : '-');
-       }
-}
-
-longtname(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       dev_t dev = k->ki_e->e_tdev;
-       char *ttname;
-
-       if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
-               (void) printf("%-*s", v->width, "??");
-       else
-               (void) printf("%-*s", v->width, ttname);
-}
-
-#include <sys/time.h>
-
-started(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       extern char *attime();
-
-       (void) printf("%-*s", v->width, k->ki_u ?
-               attime(&k->ki_u->u_start.tv_sec) : "-");
-
-}
-
-lstarted(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       extern char *ctime();
-       char *tp;
-
-       if (k->ki_u)
-               (tp = ctime(&k->ki_u->u_start.tv_sec))[24] = '\0';
-       else
-               tp = "-";
-       (void) printf("%-*s", v->width, tp);
-}
-
-wchan(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       if (k->ki_p->p_wchan) {
-               if (k->ki_p->p_pri > PZERO)
-                       (void) printf("%-*.*s", v->width, v->width, k->ki_e->e_wmesg);
-               else
-                       (void) printf("%*x", v->width,
-                               (int)k->ki_p->p_wchan &~ KERNBASE);
-       } else
-               (void) printf("%-*s", v->width, "-");
-}
-
-#define pgtok(a)        (((a)*NBPG)/1024)
-
-vsize(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width,
-               pgtok(k->ki_p->p_dsize + k->ki_p->p_ssize + k->ki_e->e_xsize));
-}
-
-rssize(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width,
-               pgtok(k->ki_p->p_rssize + (k->ki_e->e_xccount ?
-                     (k->ki_e->e_xrssize / k->ki_e->e_xccount) : 0)));
-}
-
-p_rssize(k, v)         /* doesn't account for text */
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width, pgtok(k->ki_p->p_rssize));
-}
-
-cputime(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-       long secs;
-       long psecs;     /* "parts" of a second. first micro, then centi */
-       char obuff[128];
-
-       if (k->ki_p->p_stat == SZOMB || k->ki_u == NULL) {
-               secs = 0;
-               psecs = 0;
-       } else {
-               secs = k->ki_p->p_utime.tv_sec +
-                       k->ki_p->p_stime.tv_sec;
-               psecs = k->ki_p->p_utime.tv_usec +
-                       k->ki_p->p_stime.tv_usec;
-               if (sumrusage) {
-                       secs += k->ki_u->u_cru.ru_utime.tv_sec +
-                               k->ki_u->u_cru.ru_stime.tv_sec;
-                       psecs += k->ki_u->u_cru.ru_utime.tv_usec +
-                               k->ki_u->u_cru.ru_stime.tv_usec;
-               }
-               /*
-                * round and scale to 100's
-                */
-               psecs = (psecs + 5000) / 10000;
-               if (psecs >= 100) {
-                       psecs -= 100;
-                       secs++;
-               }
-       }
-       (void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
-       (void) printf("%*s", v->width, obuff);
-}
-
-double
-getpcpu(k)
-       struct kinfo *k;
-{
-       /*
-        * note: this routine requires ccpu and fscale
-        * be initialized.  If you call this routine from
-        * somewhere new, insure that the "neednlist" flag
-        * gets set.
-        */
-       struct proc *p = k->ki_p;
-#define        fxtofl(fixpt)   ((double)(fixpt) / fscale)
-
-       if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) /* XXX - I don't like this */
-               return (0.0);
-       if (rawcpu)
-               return (100.0 * fxtofl(p->p_pctcpu));
-       return (100.0 * fxtofl(p->p_pctcpu) /
-               (1.0 - exp(p->p_time * log(fxtofl(ccpu)))));
-}
-
-pcpu(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*.1f", v->width, getpcpu(k));
-}
-
-double
-getpmem(k)
-       struct kinfo *k;
-{
-       struct proc *p = k->ki_p;
-       struct eproc *e = k->ki_e;
-       double fracmem;
-       int szptudot;
-       /*
-        * note: this routine requires that ecmx
-        * be initialized.  If you call this routine from
-        * somewhere new, insure that the "neednlist" flag
-        * gets set.
-        */
-
-       if ((p->p_flag & SLOAD) == 0)
-               return (0.0);
-       szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
-       fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/ecmx;
-       if (p->p_textp && e->e_xccount)
-               fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/ecmx;
-       return (100.0 * fracmem);
-}
-
-pmem(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*.1f", v->width, getpmem(k));
-}
-
-pagein(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0);
-}
-
-maxrss(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG))
-               (void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss));
-       else
-               (void) printf("%*s", v->width, "-");
-}
-
-tsize(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize));
-}
-
-trss(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       (void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize));
-}
-
-/*
- * Generic output routines.  Print fields from various prototype
- * structures.
- */
-pvar(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       printval((char *)((char *)k->ki_p + v->off), v);
-}
-
-evar(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       printval((char *)((char *)k->ki_e + v->off), v);
-}
-
-uvar(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       if (k->ki_u)
-               printval((char *)((char *)k->ki_u + v->off), v);
-       else
-               (void) printf("%*s", v->width, "-");
-}
-
-rvar(k, v)
-       struct kinfo *k;
-       struct var *v;
-{
-
-       if (k->ki_u)
-               printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v);
-       else
-               (void) printf("%*s", v->width, "-");
-}
-
-char *
-lookupcombo(cp)
-       char *cp;
-{
-       register struct combovar *cv = &combovar[0];
-
-       for (; cv->name; cv++)
-               if (strcmp(cp, cv->name) == 0)
-                       return (cv->replace);
-       return (NULL);
-}
-
-struct var *
-lookupvar(cp)
-       char *cp;
-{
-       register int i, j;
-
-       for (i=0; var[i].name[0] != NULL; i++)
-               for (j=0; var[i].name[j] != NULL; j++)
-                       if (strcmp(cp, var[i].name[j]) == 0)
-                               return (&var[i]);
-       return (NULL);
-}
-
-printval(bp, v)
-       char *bp;
-       struct var *v;
-{
-       static char ofmt[32] = "%";
-       register char *cp = ofmt+1, *fcp = v->fmt;
-
-       if (v->flag & LJUST)
-               *cp++ = '-';
-       *cp++ = '*';
-       while (*cp++ = *fcp++)
-               ;
-
-       switch (v->type) {
-       case CHAR:
-               (void) printf(ofmt, v->width, *(char *)bp);
-               break;
-
-       case UCHAR:
-               (void) printf(ofmt, v->width, *(u_char *)bp);
-               break;
-
-       case SHORT:
-               (void) printf(ofmt, v->width, *(short *)bp);
-               break;
-
-       case USHORT:
-               (void) printf(ofmt, v->width, *(u_short *)bp);
-               break;
-
-       case LONG:
-               (void) printf(ofmt, v->width, *(long *)bp);
-               break;
-
-       case ULONG:
-               (void) printf(ofmt, v->width, *(u_long *)bp);
-               break;
-
-       case KPTR:
-               (void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
-               break;
-
-       default:
-               error("unknown type %d", v->type);
-       }
-}
 
 /* XXX - redo */
 saveuser(ki)
 
 /* XXX - redo */
 saveuser(ki)
-       struct kinfo *ki;
+       KINFO *ki;
 {
        register struct usave *usp;
        register struct user *up;
 
 {
        register struct usave *usp;
        register struct user *up;
 
-       if ((usp = (struct usave *)calloc(1, sizeof (struct usave))) == NULL) {
-               (void) fprintf(stderr, "ps: out of memory\n");
-               exit(1);
-       }
+       if ((usp = calloc(1, sizeof(struct usave))) == NULL)
+               err("%s", strerror(errno));
        ki->ki_u = usp;
        up = kvm_getu(ki->ki_p);
        /*
         * save arguments if needed
         */
        ki->ki_u = usp;
        up = kvm_getu(ki->ki_p);
        /*
         * save arguments if needed
         */
-       if (needcomm)
-               ki->ki_args = strdup(kvm_getargs(ki->ki_p, up));
-       else
-               ki->ki_args = NULL;
+       ki->ki_args = needcomm ? strdup(kvm_getargs(ki->ki_p, up)) : NULL;
        if (up != NULL) {
                /*
                 * save important fields
                 */
        if (up != NULL) {
                /*
                 * save important fields
                 */
+#ifdef NEWVM
+               usp->u_start = up->u_stats.p_start;
+               usp->u_ru = up->u_stats.p_ru;
+               usp->u_cru = up->u_stats.p_cru;
+#else
                usp->u_procp = up->u_procp;
                usp->u_start = up->u_start;
                usp->u_ru = up->u_ru;
                usp->u_cru = up->u_cru;
                usp->u_procp = up->u_procp;
                usp->u_start = up->u_start;
                usp->u_ru = up->u_ru;
                usp->u_cru = up->u_cru;
-               usp->u_cmask = up->u_cmask;
                usp->u_acflag = up->u_acflag;
                usp->u_acflag = up->u_acflag;
+#endif
        }
 }
 
        }
 }
 
-
 pscomp(k1, k2)
 pscomp(k1, k2)
-       struct kinfo *k1, *k2;
+       KINFO *k1, *k2;
 {
        int i;
 {
        int i;
+#ifdef NEWVM
+#define VSIZE(k) ((k)->ki_e->e_vm.vm_dsize + (k)->ki_e->e_vm.vm_ssize + \
+                 (k)->ki_e->e_vm.vm_tsize)
+#else
 #define VSIZE(k) ((k)->ki_p->p_dsize + (k)->ki_p->p_ssize + (k)->ki_e->e_xsize)
 #define VSIZE(k) ((k)->ki_p->p_dsize + (k)->ki_p->p_ssize + (k)->ki_e->e_xsize)
+#endif
 
        if (sortby == SORTCPU)
                return (getpcpu(k2) - getpcpu(k1));
 
        if (sortby == SORTCPU)
                return (getpcpu(k2) - getpcpu(k1));
-#ifdef notyet
-       if (sortby == SORTRUN)
-               return (proc_compare(k1->ki_p, k2->ki_p));
-#endif
        if (sortby == SORTMEM)
                return (VSIZE(k2) - VSIZE(k1));
        i =  k1->ki_e->e_tdev - k2->ki_e->e_tdev;
        if (sortby == SORTMEM)
                return (VSIZE(k2) - VSIZE(k1));
        i =  k1->ki_e->e_tdev - k2->ki_e->e_tdev;
@@ -1124,49 +365,6 @@ pscomp(k1, k2)
        return (i);
 }
 
        return (i);
 }
 
-donlist()
-{
-#define kread(x, v) \
-       kvm_read(psnl[x].n_value, (char *)&v, sizeof v) != sizeof(v)
-
-       if (kvm_nlist(psnl) != 0)
-               error("can't get namelist");
-       if (kread(X_FSCALE, fscale))
-               error("error reading fscale: %s", kvm_geterr());
-       if (kread(X_ECMX, ecmx))
-               error("error reading ecmx: %s", kvm_geterr());
-       if (kread(X_CCPU, ccpu))
-               error("error reading ccpu: %s", kvm_geterr());
-#undef kread
-}
-
-#ifdef lint
-/* VARARGS1 */
-error(fmt) char *fmt; { (void) fputs(fmt, stderr); exit(1); /* NOTREACHED */ }
-#else
-error(va_alist)
-       va_dcl
-{
-       char *fmt;
-       va_list ap;
-
-       va_start(ap);
-       fmt = va_arg(ap, char *);
-       (void) fprintf(stderr, "ps: ");
-       (void) vfprintf(stderr, fmt, ap);
-       (void) fprintf(stderr, "\n");
-       exit(1);
-}
-#endif
-
-syserror(a)
-       char *a;
-{
-       extern errno;
-
-       error("%s: %s", a, strerror(errno));
-}
-
 /*
  * ICK (all for getopt), would rather hide the ugliness
  * here than taint the main code.
 /*
  * ICK (all for getopt), would rather hide the ugliness
  * here than taint the main code.
@@ -1182,11 +380,12 @@ char *
 kludge_oldps_options(s)
        char *s;
 {
 kludge_oldps_options(s)
        char *s;
 {
-       size_t len = strlen(s);
+       size_t len;
        char *newopts, *ns, *cp;
 
        char *newopts, *ns, *cp;
 
+       len = strlen(s);
        if ((newopts = ns = malloc(len + 2)) == NULL)
        if ((newopts = ns = malloc(len + 2)) == NULL)
-               error("out of memory");
+               err("%s", strerror(errno));
        /*
         * options begin with '-'
         */
        /*
         * options begin with '-'
         */
@@ -1225,3 +424,39 @@ kludge_oldps_options(s)
 
        return (newopts);
 }
 
        return (newopts);
 }
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)fprintf(stderr, "ps: ");
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, "\n");
+       exit(1);
+       /* NOTREACHED */
+}
+
+usage()
+{
+       (void) fprintf(stderr,
+"usage: ps [-aChjlmrSTuvwx] [-O|o fmt] [-p pid] [-t tty]\n\t  [-M core] [-N system] [-W swap]\n       ps [-L]\n");
+       exit(1);
+}