-static char *sccsid = "@(#)ps.c 4.7 (Berkeley) %G%";
-/*
- * ps; VAX 4BSD version
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <ctype.h>
-#include <nlist.h>
-#include <pwd.h>
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ps.c 5.43 (Berkeley) 7/1/91";
+#endif /* not lint */
+
#include <sys/param.h>
-#include <sys/tty.h>
-#include <sys/dir.h>
#include <sys/user.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <sys/proc.h>
-#include <sys/pte.h>
-#include <sys/vm.h>
-#include <sys/text.h>
#include <sys/stat.h>
-#include <math.h>
-
-struct nlist nl[] = {
- { "_proc" },
-#define X_PROC 0
- { "_Usrptmap" },
-#define X_USRPTMA 1
- { "_usrpt" },
-#define X_USRPT 2
- { "_text" },
-#define X_TEXT 3
- { "_nswap" },
-#define X_NSWAP 4
- { "_maxslp" },
-#define X_MAXSLP 5
- { "_ccpu" },
-#define X_CCPU 6
- { "_ecmx" },
-#define X_ECMX 7
- { 0 },
-};
-
-struct savcom {
- union {
- struct lsav *lp;
- float u_pctcpu;
- struct vsav *vp;
- int s_ssiz;
- } sun;
- struct asav *ap;
-} savcom[NPROC];
-
-struct asav {
- char *a_cmdp;
- int a_flag;
- short a_stat, a_uid, a_pid, a_nice, a_pri, a_slptime, a_time;
- size_t a_size, a_rss, a_tsiz, a_txtrss;
- short a_xccount;
- char a_tty[DIRSIZ+1];
- dev_t a_ttyd;
- time_t a_cpu;
-};
-
-char *lhdr;
-struct lsav {
- short l_ppid;
- char l_cpu;
- int l_addr;
- caddr_t l_wchan;
-};
-
-char *uhdr;
-char *shdr;
-
-char *vhdr;
-struct vsav {
- u_int v_majflt;
- size_t v_swrss, v_txtswrss;
- float v_pctcpu;
-};
-
-struct proc proc[8]; /* 8 = a few, for less syscalls */
-struct proc *mproc;
-struct text *text;
+#include <sys/ioctl.h>
+#include <sys/kinfo.h>
+#include <nlist.h>
+#include <kvm.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include "ps.h"
-int paduser1; /* avoid hardware mem clobbering botch */
-union {
- struct user user;
- char upages[UPAGES][NBPG];
-} user;
-#define u user.user
-int paduser2; /* avoid hardware mem clobbering botch */
+#ifdef SPPWAIT
+#define NEWVM
+#endif
-#define clear(x) ((int)x & 0x7fffffff)
+KINFO *kinfo;
+struct varent *vhead, *vtail;
-int chkpid;
-int aflg, cflg, eflg, gflg, kflg, lflg, sflg, uflg, vflg, xflg;
-char *tptr;
-char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state();
-double pcpu(), pmem();
-int pscomp();
-int nswap, maxslp;
-double ccpu;
-int ecmx;
-struct pte *Usrptma, *usrpt;
+int eval; /* exit value */
+int rawcpu; /* -C */
+int sumrusage; /* -S */
+int termwidth; /* width of screen (0 == infinity) */
+int totwidth; /* calculated width of requested variables */
-struct ttys {
- char name[DIRSIZ+1];
- dev_t ttyd;
- struct ttys *next;
- struct ttys *cand;
-} *allttys, *cand[16];
+static int needuser, needcomm;
-struct savcom savcom[NPROC];
-int npr;
+enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT;
-int cmdstart;
-int twidth;
-char *kmemf, *memf, *swapf, *nlistf;
-int kmem, mem, swap;
-int rawcpu, sumcpu;
+uid_t getuid();
+char *ttyname();
-int pcbpf;
-int argaddr;
-extern char _sobuf[];
+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";
main(argc, argv)
+ int argc;
char **argv;
{
- register int i, j;
- register char *ap;
- int uid;
- off_t procp;
-
- if (chdir("/dev") < 0) {
- perror("/dev");
- exit(1);
- }
- twidth = 80;
- setbuf(stdout, _sobuf);
- argc--, argv++;
- if (argc > 0) {
- ap = argv[0];
- while (*ap) switch (*ap++) {
-
+ extern char *optarg;
+ extern int optind;
+ register struct proc *p;
+ register size_t nentries;
+ register struct varent *vent;
+ register int i;
+ struct winsize ws;
+ dev_t ttydev;
+ int all, ch, flag, fmt, lineno, pid, prtheader, uid, what, xflg;
+ int pscomp();
+ char *nlistf, *memf, *swapf;
+ char *kludge_oldps_options();
+
+ 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;
+
+ if (argc > 1)
+ argv[1] = kludge_oldps_options(argv[1]);
+
+ 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) {
+ case 'a':
+ all = 1;
+ break;
case 'C':
- rawcpu++;
+ rawcpu = 1;
break;
- case 'S':
- sumcpu++;
+ case 'g':
+ break; /* no-op */
+ case 'h':
+ prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
break;
- case 'a':
- aflg++;
+ case 'j':
+ parsefmt(jfmt);
+ fmt = 1;
+ jfmt[0] = '\0';
break;
- case 'c':
- cflg = !cflg;
+ case 'L':
+ showkey();
+ exit(0);
+ case 'l':
+ parsefmt(lfmt);
+ fmt = 1;
+ lfmt[0] = '\0';
break;
- case 'e':
- eflg++;
+ case 'M':
+ memf = optarg;
break;
- case 'g':
- gflg++;
+ case 'm':
+ sortby = SORTMEM;
break;
- case 'k':
- kflg++;
+ case 'N':
+ nlistf = optarg;
break;
- case 'l':
- lflg++;
+ case 'O':
+ parsefmt(o1);
+ parsefmt(optarg);
+ parsefmt(o2);
+ o1[0] = o2[0] = '\0';
+ fmt = 1;
break;
- case 's':
- sflg++;
+ case 'o':
+ parsefmt(optarg);
+ fmt = 1;
break;
- case 't':
- if (*ap)
- tptr = ap;
- aflg++;
- gflg++;
- if (*tptr == '?')
- xflg++;
- while (*ap)
- ap++;
+ case 'p':
+ pid = atoi(optarg);
+ xflg = 1;
break;
+ case 'r':
+ sortby = SORTCPU;
+ break;
+ case 'S':
+ sumrusage = 1;
+ break;
+ case 'T':
+ if ((optarg = ttyname(STDIN_FILENO)) == NULL)
+ err("stdin: not a terminal");
+ /* FALLTHROUGH */
+ case 't': {
+ char *ttypath;
+ struct stat stbuf;
+ char pathbuf[MAXPATHLEN];
+
+ if (strcmp(optarg, "co") == 0)
+ ttypath = _PATH_CONSOLE;
+ else if (*optarg != '/')
+ (void) sprintf(ttypath = pathbuf, "%s%s",
+ _PATH_TTY, optarg);
+ else
+ ttypath = optarg;
+ if (stat(ttypath, &stbuf) == -1)
+ err("%s: %s", ttypath, strerror(errno));
+ if (!S_ISCHR(stbuf.st_mode))
+ err("%s: not a terminal", ttypath);
+ ttydev = stbuf.st_rdev;
+ break;
+ }
case 'u':
- uflg++;
+ parsefmt(ufmt);
+ sortby = SORTCPU;
+ fmt = 1;
+ ufmt[0] = '\0';
break;
case 'v':
- cflg = 1;
- vflg++;
+ parsefmt(vfmt);
+ sortby = SORTMEM;
+ fmt = 1;
+ vfmt[0] = '\0';
+ break;
+ case 'W':
+ swapf = optarg;
break;
case 'w':
- if (twidth == 80)
- twidth = 132;
+ if (termwidth < 131)
+ termwidth = 131;
else
- twidth = BUFSIZ;
+ termwidth = UNLIMITED;
break;
case 'x':
- xflg++;
+ xflg = 1;
break;
+ case '?':
default:
- if (!isdigit(ap[-1]))
- break;
- chkpid = atoi(--ap);
- *ap = 0;
- aflg++;
- xflg++;
- break;
- }
- }
- openfiles(argc, argv);
- getkvars(argc, argv);
- getdev();
- uid = getuid();
- printhdr();
- procp = nl[X_PROC].n_value;
- for (i=0; i<NPROC; i += 8) {
- lseek(kmem, (char *)procp, 0);
- j = NPROC - i;
- if (j > 8)
- j = 8;
- j *= sizeof (struct proc);
- if (read(kmem, (char *)proc, j) != j)
- cantread("proc table", kmemf);
- procp += j;
- for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
- mproc = &proc[j];
- if (mproc->p_stat == 0 ||
- mproc->p_pgrp == 0 && xflg == 0)
- continue;
- if (tptr == 0 && gflg == 0 && xflg == 0 &&
- mproc->p_ppid == 1 && (mproc->p_flag&SDETACH) == 0)
- continue;
- if (uid != mproc->p_uid && aflg==0 ||
- chkpid != 0 && chkpid != mproc->p_pid)
- continue;
- if (vflg && gflg == 0 && xflg == 0) {
- if (mproc->p_stat == SZOMB ||
- mproc->p_flag&SWEXIT)
- continue;
- if (mproc->p_slptime > MAXSLP &&
- (mproc->p_stat == SSLEEP ||
- mproc->p_stat == SSTOP))
- continue;
- }
- save();
- }
- }
- qsort(savcom, npr, sizeof(savcom[0]), pscomp);
- for (i=0; i<npr; i++) {
- register struct savcom *sp = &savcom[i];
- if (lflg)
- lpr(sp);
- else if (vflg)
- vpr(sp);
- else if (uflg)
- upr(sp);
- else
- spr(sp);
- if (sp->ap->a_flag & SWEXIT)
- printf(" <exiting>");
- else if (sp->ap->a_stat == SZOMB)
- printf(" <defunct>");
- else if (sp->ap->a_pid == 0)
- printf(" swapper");
- else if (sp->ap->a_pid == 2)
- printf(" pagedaemon");
- else
- printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp);
- printf("\n");
- }
- exit(npr == 0);
-}
-
-openfiles(argc, argv)
- char **argv;
-{
-
- kmemf = "kmem";
- if (kflg)
- kmemf = argc > 1 ? argv[1] : "/vmcore";
- kmem = open(kmemf, 0);
- if (kmem < 0) {
- perror(kmemf);
- exit(1);
- }
- if (kflg) {
- mem = kmem;
- memf = kmemf;
- } else {
- memf = "mem";
- mem = open(memf, 0);
- if (mem < 0) {
- perror(memf);
- exit(1);
- }
- }
- swapf = argc>2 ? argv[2]: "drum";
- swap = open(swapf, 0);
- if (swap < 0) {
- perror(swapf);
- exit(1);
- }
-}
-
-getkvars(argc, argv)
- char **argv;
-{
- register struct nlist *nlp;
-
- nlistf = argc > 3 ? argv[3] : "/vmunix";
- nlist(nlistf, nl);
- if (nl[0].n_type == 0) {
- fprintf(stderr, "%s: No namelist\n", nlistf);
- exit(1);
- }
- if (kflg)
- for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++)
- nlp->n_value = clear(nlp->n_value);
- Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
- usrpt = (struct pte *)nl[X_USRPT].n_value;
- lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
- if (read(kmem, &nswap, sizeof (nswap)) != sizeof (nswap)) {
- cantread("nswap", kmemf);
- exit(1);
- }
- lseek(kmem, (long)nl[X_MAXSLP].n_value, 0);
- if (read(kmem, &maxslp, sizeof (maxslp)) != sizeof (maxslp)) {
- cantread("maxslp", kmemf);
- exit(1);
- }
- lseek(kmem, (long)nl[X_CCPU].n_value, 0);
- if (read(kmem, &ccpu, sizeof (ccpu)) != sizeof (ccpu)) {
- cantread("ccpu", kmemf);
- exit(1);
- }
- lseek(kmem, (long)nl[X_ECMX].n_value, 0);
- if (read(kmem, &ecmx, sizeof (ecmx)) != sizeof (ecmx)) {
- cantread("ecmx", kmemf);
- exit(1);
- }
- if (uflg || vflg) {
- text = (struct text *)alloc(NTEXT * sizeof (struct text));
- if (text == 0) {
- fprintf(stderr, "no room for text table\n");
- exit(1);
+ usage();
}
- lseek(kmem, (long)nl[X_TEXT].n_value, 0);
- if (read(kmem, (char *)text, NTEXT * sizeof (struct text))
- != NTEXT * sizeof (struct text)) {
- cantread("text table", kmemf);
- exit(1);
+ argc -= optind;
+ argv += optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+
+ nlistf = *argv;
+ if (*++argv) {
+ memf = *argv;
+ if (*++argv)
+ swapf = *argv;
}
}
-}
-
-printhdr()
-{
- char *hdr;
-
- if (sflg+lflg+vflg+uflg > 1) {
- fprintf(stderr, "ps: specify only one of s,l,v and u\n");
- exit(1);
- }
- hdr = lflg ? lhdr : (vflg ? vhdr : (uflg ? uhdr : shdr));
- if (lflg+vflg+uflg+sflg == 0)
- hdr += strlen("SSIZ ");
- cmdstart = strlen(hdr);
- printf("%s COMMAND\n", hdr);
- fflush(stdout);
-}
-
-cantread(what, fromwhat)
- char *what, *fromwhat;
-{
-
- fprintf(stderr, "ps: error reading %s from %s", what, fromwhat);
-}
-
-struct direct dbuf;
-int dialbase;
-
-getdev()
-{
- register FILE *df;
- register struct ttys *dp;
-
- dialbase = -1;
- if ((df = fopen(".", "r")) == NULL) {
- fprintf(stderr, "Can't open . in /dev\n");
- exit(1);
- }
- while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) {
- if (dbuf.d_ino == 0)
+#endif
+ if (kvm_openfiles(nlistf, memf, swapf) == -1)
+ err("kvm_openfiles: %s", kvm_geterr());
+
+ if (!fmt)
+ parsefmt(dfmt);
+
+ if (!all && ttydev == NODEV && pid == -1) /* XXX - should be cleaner */
+ uid = getuid();
+
+ /*
+ * scan requested variables, noting what structures are needed,
+ * and adjusting header widths as appropiate.
+ */
+ scanvars();
+ /*
+ * get proc list
+ */
+ if (uid != -1) {
+ what = KINFO_PROC_UID;
+ flag = uid;
+ } else if (ttydev != NODEV) {
+ what = KINFO_PROC_TTY;
+ flag = ttydev;
+ } else if (pid != -1) {
+ what = KINFO_PROC_PID;
+ flag = pid;
+ } else
+ what = KINFO_PROC_ALL;
+ /*
+ * select procs
+ */
+ if ((nentries = kvm_getprocs(what, flag)) == -1)
+ err("%s", kvm_geterr());
+ kinfo = malloc(nentries * sizeof(KINFO));
+ if (kinfo == NULL)
+ 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)
+ saveuser(&kinfo[nentries]);
+ }
+ /*
+ * print header
+ */
+ printheader();
+ if (nentries == 0)
+ exit(0);
+ /*
+ * sort proc list
+ */
+ qsort((void *)kinfo, nentries, sizeof(KINFO), pscomp);
+ /*
+ * for each proc, call each variable output function.
+ */
+ 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;
- maybetty(dp);
- }
- fclose(df);
-}
-
-/*
- * Attempt to avoid stats by guessing minor device
- * numbers from tty names. Console is known,
- * know that r(hp|up|mt) are unlikely as are different mem's,
- * floppy, null, tty, etc.
- */
-maybetty()
-{
- register char *cp = dbuf.d_name;
- register struct ttys *dp;
- int x;
- struct stat stb;
-
- switch (cp[0]) {
-
- case 'c':
- if (!strcmp(cp, "console")) {
- x = 0;
- goto donecand;
- }
- /* cu[la]? are possible!?! don't rule them out */
- break;
-
- case 'd':
- if (!strcmp(cp, "drum"))
- return (0);
- break;
-
- case 'f':
- if (!strcmp(cp, "floppy"))
- return (0);
- break;
-
- case 'k':
- cp++;
- if (*cp == 'U')
- cp++;
- goto trymem;
-
- case 'r':
- cp++;
- if (*cp == 'r' || *cp == 'u' || *cp == 'h')
- cp++;
-#define is(a,b) cp[0] == 'a' && cp[1] == 'b'
- if (is(r,p) || is(u,p) || is(r,k) || is(r,m) || is(m,t)) {
- cp += 2;
- if (isdigit(*cp) && cp[2] == 0)
- return (0);
- }
- break;
-
- case 'm':
-trymem:
- if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0)
- return (0);
- break;
-
- case 'n':
- if (!strcmp(cp, "null"))
- return (0);
- break;
-
- case 'v':
- if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) &&
- cp[3] == 0)
- return (0);
- break;
- }
-mightbe:
- cp = dbuf.d_name;
- while (cp < &dbuf.d_name[DIRSIZ] && *cp)
- cp++;
- --cp;
- x = 0;
- if (cp[-1] == 'd') {
- if (dialbase == -1) {
- if (stat("ttyd0", &stb) == 0)
- dialbase = stb.st_rdev & 017;
- else
- dialbase = -2;
- }
- if (dialbase == -2)
- x = 0;
- else
- x = 11;
- }
- if (cp > dbuf.d_name && isdigit(cp[-1]) && isdigit(*cp))
- x += 10 * (cp[-1] - ' ') + cp[0] - '0';
- else if (*cp >= 'a' && *cp <= 'f')
- x += 10 + *cp - 'a';
- else if (isdigit(*cp))
- x += *cp - '0';
- else
- x = -1;
-donecand:
- dp = (struct ttys *)alloc(sizeof (struct ttys));
- strncpy(dp->name, dbuf.d_name, DIRSIZ);
- dp->next = allttys;
- dp->ttyd = -1;
- allttys = dp;
- if (x == -1)
- return;
- x &= 017;
- dp->cand = cand[x];
- cand[x] = dp;
-}
-
-char *
-gettty()
-{
- register char *p;
- register struct ttys *dp;
- struct stat stb;
- int x;
-
- if (u.u_ttyp == 0)
- return("?");
- x = u.u_ttyd & 017;
- for (dp = cand[x]; dp; dp = dp->cand) {
- if (dp->ttyd == -1) {
- if (stat(dp->name, &stb) == 0 &&
- (stb.st_mode&S_IFMT)==S_IFCHR)
- dp->ttyd = stb.st_rdev;
- else
- dp->ttyd = -2;
- }
- if (dp->ttyd == u.u_ttyd)
- goto found;
- }
- /* ick */
- for (dp = allttys; dp; dp = dp->next) {
- if (dp->ttyd == -1) {
- if (stat(dp->name, &stb) == 0)
- dp->ttyd = stb.st_rdev;
- else
- dp->ttyd = -2;
- }
- if (dp->ttyd == u.u_ttyd)
- goto found;
- }
- return ("?");
-found:
- p = dp->name;
- if (p[0]=='t' && p[1]=='t' && p[2]=='y')
- p += 3;
- return (p);
-}
-
-save()
-{
- register struct savcom *sp;
- register struct asav *ap;
- register char *cp;
- register struct text *xp;
- char *ttyp, *cmdp;
-
- if (mproc->p_stat != SZOMB && getu() == 0)
- return;
- ttyp = gettty();
- if (xflg == 0 && ttyp[0] == '?' || tptr && strcmpn(tptr, ttyp, 2))
- return;
- sp = &savcom[npr];
- cmdp = getcmd();
- if (cmdp == 0)
- return;
- sp->ap = ap = (struct asav *)alloc(sizeof (struct asav));
- sp->ap->a_cmdp = cmdp;
-#define e(a,b) ap->a = mproc->b
- e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice);
- e(a_uid, p_uid); e(a_pid, p_pid); e(a_pri, p_pri);
- e(a_slptime, p_slptime); e(a_time, p_time);
- ap->a_tty[0] = ttyp[0];
- ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' ';
- if (ap->a_stat == SZOMB) {
- register struct xproc *xp = (struct xproc *)mproc;
-
- ap->a_cpu = xp->xp_vm.vm_utime + xp->xp_vm.vm_stime;
- } else {
- ap->a_size = mproc->p_dsize + mproc->p_ssize;
- e(a_rss, p_rssize);
- ap->a_ttyd = u.u_ttyd;
- ap->a_cpu = u.u_vm.vm_utime + u.u_vm.vm_stime;
- if (sumcpu)
- ap->a_cpu += u.u_cvm.vm_utime + u.u_cvm.vm_stime;
- if (mproc->p_textp && text) {
- xp = &text[mproc->p_textp -
- (struct text *)nl[X_TEXT].n_value];
- ap->a_tsiz = xp->x_size;
- ap->a_txtrss = xp->x_rssize;
- ap->a_xccount = xp->x_ccount;
- }
- }
-#undef e
- ap->a_cpu /= HZ;
- if (lflg) {
- register struct lsav *lp;
-
- sp->sun.lp = lp = (struct lsav *)alloc(sizeof (struct lsav));
-#define e(a,b) lp->a = mproc->b
- e(l_ppid, p_ppid); e(l_cpu, p_cpu);
- if (ap->a_stat != SZOMB)
- e(l_wchan, p_wchan);
-#undef e
- lp->l_addr = pcbpf;
- } else if (vflg) {
- register struct vsav *vp;
-
- sp->sun.vp = vp = (struct vsav *)alloc(sizeof (struct vsav));
-#define e(a,b) vp->a = mproc->b
- if (ap->a_stat != SZOMB) {
- e(v_swrss, p_swrss);
- vp->v_majflt = u.u_vm.vm_majflt;
- if (mproc->p_textp)
- vp->v_txtswrss = xp->x_swrss;
+ for (vent = vhead; vent; vent = vent->next) {
+ (*vent->var->oproc)(&kinfo[i], vent->var, vent->next);
+ if (vent->next != NULL)
+ (void) putchar(' ');
}
- vp->v_pctcpu = pcpu();
-#undef e
- } else if (uflg)
- sp->sun.u_pctcpu = pcpu();
- else if (sflg) {
- if (ap->a_stat != SZOMB) {
- for (cp = (char *)u.u_stack;
- cp < &user.upages[UPAGES][NBPG]; )
- if (*cp++)
- break;
- sp->sun.s_ssiz = (&user.upages[UPAGES][NBPG] - cp);
+ (void) putchar('\n');
+ if (prtheader && lineno++ == prtheader-4) {
+ (void) putchar('\n');
+ printheader();
+ lineno = 0;
}
}
- npr++;
-}
-
-double
-pmem(ap)
- register struct asav *ap;
-{
- double fracmem;
- int szptudot;
-
- if ((ap->a_flag&SLOAD) == 0)
- fracmem = 0.0;
- else {
- szptudot = UPAGES + clrnd(ctopt(ap->a_size+ap->a_tsiz));
- fracmem = ((float)ap->a_rss+szptudot)/CLSIZE/ecmx;
- if (ap->a_xccount)
- fracmem += ((float)ap->a_txtrss)/CLSIZE/
- ap->a_xccount/ecmx;
- }
- return (100.0 * fracmem);
+ exit(eval);
}
-double
-pcpu()
+scanvars()
{
- time_t time;
-
- time = mproc->p_time;
- if (time == 0 || (mproc->p_flag&SLOAD) == 0)
- return (0.0);
- if (rawcpu)
- return (100.0 * mproc->p_pctcpu);
- return (100.0 * mproc->p_pctcpu / (1.0 - exp(time * log(ccpu))));
-}
-
-getu()
-{
- struct pte *pteaddr, apte;
- int pad1; /* avoid hardware botch */
- struct pte arguutl[UPAGES+CLSIZE];
- int pad2; /* avoid hardware botch */
+ register struct varent *vent;
+ register VAR *v;
register int i;
- int ncl, size;
-
- size = sflg ? ctob(UPAGES) : sizeof (struct user);
- if ((mproc->p_flag & SLOAD) == 0) {
- lseek(swap, ctob(mproc->p_swaddr), 0);
- if (read(swap, (char *)&user.user, size) != size) {
- fprintf(stderr, "ps: cant read u for pid %d from %s\n",
- mproc->p_pid, swapf);
- return (0);
- }
- pcbpf = 0;
- argaddr = 0;
- return (1);
- }
- pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
- lseek(kmem, kflg ? clear(pteaddr) : (int)pteaddr, 0);
- if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
- printf("ps: cant read indir pte to get u for pid %d from %s\n",
- mproc->p_pid, swapf);
- return (0);
- }
- lseek(mem,
- ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0);
- if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
- printf("ps: cant read page table for u of pid %d from %s\n",
- mproc->p_pid, swapf);
- return (0);
- }
- if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
- argaddr = ctob(arguutl[0].pg_pfnum);
- else
- argaddr = 0;
- pcbpf = arguutl[CLSIZE].pg_pfnum;
- ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
- while (--ncl >= 0) {
- i = ncl * CLSIZE;
- lseek(mem, ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
- if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
- printf("ps: cant read page %d of u of pid %d from %s\n",
- arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
- return(0);
- }
- }
- return (1);
-}
-
-char *
-getcmd()
-{
- char cmdbuf[BUFSIZ];
- int pad1; /* avoid hardware botch */
- union {
- char argc[CLSIZE*NBPG];
- int argi[CLSIZE*NBPG/sizeof (int)];
- } argspac;
- int pad2; /* avoid hardware botch */
- register char *cp;
- register int *ip;
- char c;
- int nbad;
- struct dblock db;
-
- if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT))
- return ("");
- if (cflg) {
- strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm));
- return (savestr(cmdbuf));
- }
- if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) {
- vstodb(0, CLSIZE, &u.u_smap, &db, 1);
- lseek(swap, ctob(db.db_base), 0);
- if (read(swap, (char *)&argspac, sizeof(argspac))
- != sizeof(argspac))
- goto bad;
- } else {
- lseek(mem, argaddr, 0);
- if (read(mem, (char *)&argspac, sizeof (argspac))
- != sizeof (argspac))
- goto bad;
- }
- ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)];
- ip -= 2; /* last arg word and .long 0 */
- while (*--ip)
- if (ip == argspac.argi)
- goto retucomm;
- *(char *)ip = ' ';
- ip++;
- nbad = 0;
- for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) {
- c = *cp & 0177;
- if (c == 0)
- *cp = ' ';
- else if (c < ' ' || c > 0176) {
- if (++nbad >= 5*(eflg+1)) {
- *cp++ = ' ';
- break;
- }
- *cp = '?';
- } else if (eflg == 0 && c == '=') {
- while (*--cp != ' ')
- if (cp <= (char *)ip)
- break;
- break;
- }
- }
- *cp = 0;
- while (*--cp == ' ')
- *cp = 0;
- cp = (char *)ip;
- strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp);
- if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
- strcat(cmdbuf, " (");
- strncat(cmdbuf, u.u_comm, sizeof(u.u_comm));
- strcat(cmdbuf, ")");
- }
-/*
- if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-')
- return (0);
-*/
- return (savestr(cmdbuf));
-
-bad:
- fprintf(stderr, "ps: error locating command name for pid %d\n",
- mproc->p_pid);
-retucomm:
- strcpy(cmdbuf, " (");
- strncat(cmdbuf, u.u_comm, sizeof (u.u_comm));
- strcat(cmdbuf, ")");
- return (savestr(cmdbuf));
-}
-
-char *lhdr =
-" F UID PID PPID CP PRI NI ADDR SZ RSS WCHAN STAT TT TIME";
-lpr(sp)
- struct savcom *sp;
-{
- register struct asav *ap = sp->ap;
- register struct lsav *lp = sp->sun.lp;
-
- printf("%6x%4d%6u%6u%3d%4d%3d%5x%4d%5d",
- ap->a_flag, ap->a_uid,
- ap->a_pid, lp->l_ppid, lp->l_cpu&0377, ap->a_pri-PZERO,
- ap->a_nice-NZERO, lp->l_addr, ap->a_size/2, ap->a_rss/2);
- printf(lp->l_wchan ? " %5x" : " ", (int)lp->l_wchan&0xfffff);
- printf(" %4.4s ", state(ap));
- ptty(ap->a_tty);
- ptime(ap);
-}
-
-ptty(tp)
- char *tp;
-{
-
- printf("%-2.2s", tp);
-}
-
-ptime(ap)
- struct asav *ap;
-{
-
- printf("%3ld:%02ld", ap->a_cpu / HZ, ap->a_cpu % HZ);
-}
-
-char *uhdr =
-"USER PID %CPU %MEM SZ RSS TT STAT TIME";
-upr(sp)
- struct savcom *sp;
-{
- register struct asav *ap = sp->ap;
- int vmsize, rmsize;
- vmsize = (ap->a_size + ap->a_tsiz)/2;
- rmsize = ap->a_rss/2;
- if (ap->a_xccount)
- rmsize += ap->a_txtrss/ap->a_xccount/2;
- printf("%-8.8s %5d%5.1f%5.1f%5d%5d",
- getname(ap->a_uid), ap->a_pid, sp->sun.u_pctcpu, pmem(ap),
- vmsize, rmsize);
- putchar(' ');
- ptty(ap->a_tty);
- printf(" %4.4s", state(ap));
- ptime(ap);
+ for (vent = vhead; vent; vent = vent->next) {
+ v = vent->var;
+ i = strlen(v->header);
+ if (v->width < i)
+ v->width = i;
+ totwidth += v->width + 1; /* +1 for space */
+ if (v->flag & USER)
+ needuser = 1;
+ if (v->flag & COMM)
+ needcomm = 1;
+ }
+ totwidth--;
}
-char *vhdr =
-" PID TT STAT TIME SL RE PAGEIN SIZE RSS SRS TSIZ TRS %CPU %MEM";
-vpr(sp)
- struct savcom *sp;
-{
- register struct vsav *vp = sp->sun.vp;
- register struct asav *ap = sp->ap;
-
- printf("%5u ", ap->a_pid);
- ptty(ap->a_tty);
- printf(" %4.4s", state(ap));
- ptime(ap);
- printf("%3d%3d%7d%5d%5d%5d%5d%4d%5.1f%5.1f",
- ap->a_slptime, ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt,
- ap->a_size/2, ap->a_rss/2, vp->v_swrss/2,
- ap->a_tsiz/2, ap->a_txtrss/2, vp->v_pctcpu, pmem(ap));
-}
-
-char *shdr =
-"SSIZ PID TT STAT TIME";
-spr(sp)
- struct savcom *sp;
-{
- register struct asav *ap = sp->ap;
-
- if (sflg)
- printf("%4d ", sp->sun.s_ssiz);
- printf("%5u", ap->a_pid);
- putchar(' ');
- ptty(ap->a_tty);
- printf(" %4.4s", state(ap));
- ptime(ap);
-}
-
-char *
-state(ap)
- register struct asav *ap;
-{
- char stat, load, nice, anom;
- static char res[5];
-
- switch (ap->a_stat) {
-
- case SSTOP:
- stat = 'T';
- break;
-
- case SSLEEP:
- if (ap->a_pri >= PZERO)
- if (ap->a_slptime >= MAXSLP)
- stat = 'I';
- else
- stat = 'S';
- else if (ap->a_flag & SPAGE)
- stat = 'P';
- else
- stat = 'D';
- break;
- case SWAIT:
- case SRUN:
- case SIDL:
- stat = 'R';
- break;
-
- case SZOMB:
- stat = 'Z';
- break;
-
- default:
- stat = '?';
- }
- load = ap->a_flag & SLOAD ? ' ' : 'W';
- if (ap->a_nice < NZERO)
- nice = '<';
- else if (ap->a_nice > NZERO)
- nice = 'N';
- else
- nice = ' ';
- anom = ap->a_flag & (SANOM|SUANOM) ? 'A' : ' ';
- res[0] = stat; res[1] = load; res[2] = nice; res[3] = anom;
- return (res);
-}
-
-/*
- * Given a base/size pair in virtual swap area,
- * return a physical base/size pair which is the
- * (largest) initial, physically contiguous block.
- */
-vstodb(vsbase, vssize, dmp, dbp, rev)
- register int vsbase;
- int vssize;
- struct dmap *dmp;
- register struct dblock *dbp;
+/* XXX - redo */
+saveuser(ki)
+ KINFO *ki;
{
- register int blk = DMMIN;
- register swblk_t *ip = dmp->dm_map;
-
- if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
- panic("vstodb");
- while (vsbase >= blk) {
- vsbase -= blk;
- if (blk < DMMAX)
- blk *= 2;
- ip++;
- }
- if (*ip <= 0 || *ip + blk > nswap)
- panic("vstodb *ip");
- dbp->db_size = min(vssize, blk - vsbase);
- dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
-}
-
-/*ARGSUSED*/
-panic(cp)
- char *cp;
-{
-
-#ifdef DEBUG
- printf("%s\n", cp);
+ register struct usave *usp;
+ register struct user *up;
+
+ if ((usp = calloc(1, sizeof(struct usave))) == NULL)
+ err("%s", strerror(errno));
+ up = kvm_getu(ki->ki_p);
+ /*
+ * save arguments if needed
+ */
+ ki->ki_args = needcomm ? strdup(kvm_getargs(ki->ki_p, up)) : NULL;
+ if (up != NULL) {
+ ki->ki_u = usp;
+ /*
+ * 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_acflag = up->u_acflag;
#endif
+ } else
+ free(usp);
}
-min(a, b)
-{
-
- return (a < b ? a : b);
-}
-
-pscomp(s1, s2)
- struct savcom *s1, *s2;
+pscomp(k1, k2)
+ KINFO *k1, *k2;
{
- register 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)
+#endif
- if (uflg)
- return (s2->sun.u_pctcpu > s1->sun.u_pctcpu ? 1 : -1);
- if (vflg)
- return (vsize(s2) - vsize(s1));
- i = s1->ap->a_ttyd - s2->ap->a_ttyd;
+ if (sortby == SORTCPU)
+ return (getpcpu(k2) - getpcpu(k1));
+ if (sortby == SORTMEM)
+ return (VSIZE(k2) - VSIZE(k1));
+ i = k1->ki_e->e_tdev - k2->ki_e->e_tdev;
if (i == 0)
- i = s1->ap->a_pid - s2->ap->a_pid;
+ i = k1->ki_p->p_pid - k2->ki_p->p_pid;
return (i);
}
-vsize(sp)
- struct savcom *sp;
-{
- register struct asav *ap = sp->ap;
- register struct vsav *vp = sp->sun.vp;
-
- if (ap->a_flag & SLOAD)
- return (ap->a_rss +
- ap->a_txtrss / (ap->a_xccount ? ap->a_xccount : 1));
- return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss));
-}
-
-#define NMAX 8
-#define NUID 2048
-
-char names[NUID][NMAX+1];
-
/*
- * Stolen from ls...
+ * ICK (all for getopt), would rather hide the ugliness
+ * here than taint the main code.
+ *
+ * ps foo -> ps -foo
+ * ps 34 -> ps -p34
+ *
+ * The old convention that 't' with no trailing tty arg means the users
+ * tty, is only supported if argv[1] doesn't begin with a '-'. This same
+ * feature is available with the option 'T', which takes no argument.
*/
char *
-getname(uid)
+kludge_oldps_options(s)
+ char *s;
{
- register struct passwd *pw;
- static init;
- struct passwd *getpwent();
-
- if (uid >= 0 && uid < NUID && names[uid][0])
- return (&names[uid][0]);
- if (init == 2)
- return (0);
- if (init == 0)
- setpwent(), init = 1;
- while (pw = getpwent()) {
- if (pw->pw_uid >= NUID)
- continue;
- if (names[pw->pw_uid][0])
- continue;
- strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
- if (pw->pw_uid == uid)
- return (&names[uid][0]);
- }
- init = 2;
- endpwent();
- return (0);
+ size_t len;
+ char *newopts, *ns, *cp;
+
+ len = strlen(s);
+ if ((newopts = ns = malloc(len + 2)) == NULL)
+ err("%s", strerror(errno));
+ /*
+ * options begin with '-'
+ */
+ if (*s != '-')
+ *ns++ = '-'; /* add option flag */
+ /*
+ * gaze to end of argv[1]
+ */
+ cp = s + len - 1;
+ /*
+ * if last letter is a 't' flag with no argument (in the context
+ * of the oldps options -- option string NOT starting with a '-' --
+ * then convert to 'T' (meaning *this* terminal, i.e. ttyname(0)).
+ */
+ if (*cp == 't' && *s != '-')
+ *cp = 'T';
+ else {
+ /*
+ * otherwise check for trailing number, which *may* be a
+ * pid.
+ */
+ while (cp >= s && isdigit(*cp))
+ --cp;
+ }
+ cp++;
+ bcopy(s, ns, (size_t)(cp - s)); /* copy up to trailing number */
+ ns += cp - s;
+ /*
+ * if there's a trailing number, and not a preceding 'p' (pid) or
+ * 't' (tty) flag, then assume it's a pid and insert a 'p' flag.
+ */
+ if (isdigit(*cp) && (cp == s || cp[-1] != 't' && cp[-1] != 'p' &&
+ (cp - 1 == s || cp[-2] != 't')))
+ *ns++ = 'p';
+ (void) strcpy(ns, cp); /* and append the number */
+
+ return (newopts);
}
-char *freebase;
-int nleft;
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
-char *
-alloc(size)
- int size;
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
{
- register char *cp;
- register int i;
-
- if (size > nleft) {
- freebase = (char *)sbrk(i = size > 2048 ? size : 2048);
- if (freebase == 0) {
- fprintf(stderr, "ps: ran out of memory\n");
- exit(1);
- }
- nleft = i - size;
- } else
- nleft -= size;
- cp = freebase;
- for (i = size; --i >= 0; )
- *cp++ = 0;
- freebase = cp;
- return (cp - size);
+ 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 */
}
-char *
-savestr(cp)
- char *cp;
+usage()
{
- register int len;
- register char *dp;
-
- len = strlen(cp);
- dp = (char *)alloc(len+1);
- strcpy(dp, cp);
- return (dp);
+ (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);
}