X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/133a0b3b2569304e2f74b1b5e8dc90249d9b1c75..51851ab80a8766989bb847630bfd193fef7e1d5f:/usr/src/bin/ps/ps.c diff --git a/usr/src/bin/ps/ps.c b/usr/src/bin/ps/ps.c index 6713f36bde..79fe0e178d 100644 --- a/usr/src/bin/ps/ps.c +++ b/usr/src/bin/ps/ps.c @@ -1,1247 +1,462 @@ -static char *sccsid = "@(#)ps.c 4.14 (Berkeley) 81/09/03"; -/* - * ps; VAX 4BSD version +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% */ -#include -#include -#include -#include +#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.42 (Berkeley) %G%"; +#endif /* not lint */ + #include -#include -#include #include +#include +#include #include -#include -#include -#include #include -#include -#include - -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 - { "_nproc" }, -#define X_NPROC 8 - { "_ntext" }, -#define X_NTEXT 9 - { "_hz" }, -#define X_HZ 10 - { 0 }, -}; - -struct savcom { - union { - struct lsav *lp; - float u_pctcpu; - struct vsav *vp; - int s_ssiz; - struct sssav *ssp; /* RAND 2/81 */ - } sun; - struct asav *ap; -} *savcom; - -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; - size_t a_maxrss; -}; - -char *lhdr; -struct lsav { - short l_ppid; - char l_cpu; - int l_addr; - caddr_t l_wchan; -}; - -char *sshdr; /* RAND 2/81 */ -struct sssav { /* RAND 2/81 */ - short ss_ppid; /* RAND 2/81 */ - short ss_brother; /* RAND 2/81 */ - short ss_sons; /* RAND 2/81 */ -}; /* RAND 2/81 */ - -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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, ssflg, /* RAND 2/81 */ - nonssflg, uflg, vflg, xflg; -char *tptr; -char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state(); -char *rindex(); /* RAND 2/81 */ -double pcpu(), pmem(); -int pscomp(); -int nswap, maxslp; -struct text *atext; -double ccpu; -int ecmx; -struct pte *Usrptma, *usrpt; -int nproc, ntext, hz; +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; -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; - - if (ap = rindex(argv[0], '/')) /* RAND 2/81 */ - 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 - ap = argv[0]; - if (*ap == 's') /* If name starts with 's' */ - ssflg++; - - setbuf(stdout, _sobuf); - argc--, argv++; - if (argc > 0) { - ap = argv[0]; - while (*ap) switch (*ap++) { - + 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++; nonssflg++; + 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 'L': + showkey(); + exit(0); + case 'l': + parsefmt(lfmt); + fmt = 1; + lfmt[0] = '\0'; break; - case 'c': - cflg = !cflg; nonssflg++; + case 'M': + memf = optarg; break; - case 'e': - eflg++; nonssflg++; + case 'm': + sortby = SORTMEM; break; - case 'g': - gflg++; nonssflg++; + case 'N': + nlistf = optarg; break; - case 'k': - kflg++; nonssflg++; + case 'O': + parsefmt(o1); + parsefmt(optarg); + parsefmt(o2); + o1[0] = o2[0] = '\0'; + fmt = 1; break; - case 'l': - lflg++; nonssflg++; + case 'o': + parsefmt(optarg); + fmt = 1; + break; + case 'p': + pid = atoi(optarg); + xflg = 1; break; - case 's': - sflg++; nonssflg++; + case 'r': + sortby = SORTCPU; break; - case 't': - if (*ap) - tptr = ap; - aflg++; nonssflg++; - gflg++; - if (*tptr == '?') - xflg++; - while (*ap) - ap++; + 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++; nonssflg++; + } + case 'u': + parsefmt(ufmt); + sortby = SORTCPU; + fmt = 1; + ufmt[0] = '\0'; break; case 'v': - cflg = 1; - vflg++; nonssflg++; + 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++; - break; - case 'y': /* Rand 2/81 */ - ssflg++; + xflg = 1; break; + case '?': default: - if (!isdigit(ap[-1])) - break; - chkpid = atoi(--ap); - *ap = 0; - aflg++; nonssflg++; - xflg++; - break; - } - } - if (ssflg) { /* RAND 2/81 */ - if (nonssflg) { - fprintf (stderr, "Usage: ss [axwS]\n"); - exit(1); - } - uflg++; - gflg++; - } - - openfiles(argc, argv); - getkvars(argc, argv); - getdev(); - uid = getuid(); - printhdr(); - procp = getw(nl[X_PROC].n_value); - nproc = getw(nl[X_NPROC].n_value); - hz = getw(nl[X_HZ].n_value); - savcom = (struct savcom *)calloc(nproc, sizeof (*savcom)); - for (i=0; i 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(); + usage(); } - } - qsort(savcom, npr, sizeof(savcom[0]), pscomp); - if (ssflg) { /* RAND 2/81 */ - walk(npr); - exit (npr == 0); - } - for (i=0; iap->a_flag & SWEXIT) - printf(" "); - else if (sp->ap->a_stat == SZOMB) - printf(" "); - else if (sp->ap->a_pid == 0) - printf(" swapper"); - else if (sp->ap->a_pid == 2) - printf(" pagedaemon"); - else if (sp->ap->a_pid == 3 && sp->ap->a_flag & SSYS) - printf(" ip input"); - else - printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp); - printf("\n"); - } - exit(npr == 0); -} - -getw(loc) - off_t loc; -{ - long word; - - lseek(kmem, loc, 0); - if (read(kmem, &word, sizeof (word)) != sizeof (word)) - printf("error reading kmem at %x\n", loc); - return (word); -} - -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); + argc -= optind; + argv += optind; + +#define BACKWARD_COMPATIBILITY +#ifdef BACKWARD_COMPATIBILITY + if (*argv) { + + nlistf = *argv; + if (*++argv) { + memf = *argv; + if (*++argv) + swapf = *argv; } } - 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) { - ntext = getw(nl[X_NTEXT].n_value); - text = (struct text *)alloc(ntext * sizeof (struct text)); - if (text == 0) { - fprintf(stderr, "no room for text table\n"); - exit(1); - } - atext = (struct text *)getw(nl[X_TEXT].n_value); - lseek(kmem, (int)atext, 0); - if (read(kmem, (char *)text, ntext * sizeof (struct text)) - != ntext * sizeof (struct text)) { - cantread("text table", kmemf); - exit(1); - } - } -} - -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 = ssflg ? sshdr : /* RAND 2/81 */ - (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; + /* + * 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); - if (cp[0] == 'm' && cp[1] == 't') - 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 && - (stb.st_mode&S_IFMT)==S_IFCHR) - 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 && strncmp(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 - atext]; - ap->a_tsiz = xp->x_size; - ap->a_txtrss = xp->x_rssize; - ap->a_xccount = xp->x_ccount; - } - } -#undef e - ap->a_cpu /= hz; - ap->a_maxrss = mproc->p_maxrss; - 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; - } - vp->v_pctcpu = pcpu(); -#undef e - } else if (uflg) { - if (!ssflg) /* RAND 2/18 */ - sp->sun.u_pctcpu = pcpu(); - else { - register struct sssav *ssp; - - sp->sun.ssp =ssp= (struct sssav *)alloc(sizeof (struct sssav)); - ssp->ss_ppid = mproc->p_ppid; + for (vent = vhead; vent; vent = vent->next) { + (*vent->var->oproc)(&kinfo[i], vent->var, vent->next); + if (vent->next != NULL) + (void) putchar(' '); } - } else if (sflg) { - if (ap->a_stat != SZOMB) { - for (cp = (char *)u.u_stack; - cp < &user.upages[UPAGES][0]; ) - if (*cp++) - break; - sp->sun.s_ssiz = (&user.upages[UPAGES][0] - 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); -} - -double -pcpu() -{ - 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)))); + exit(eval); } -getu() +scanvars() { - 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); -} - -char *vhdr = -" PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM 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", - ap->a_slptime > 99 ? 99 : ap-> a_slptime, - ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt, - ap->a_size/2, ap->a_rss/2); - if (ap->a_maxrss == (INFINITY/NBPG)) - printf(" xx"); - else - printf("%5d", ap->a_maxrss/2); - printf("%5d%4d%5.1f%5.1f", - 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 ? (ap->a_rss>ap->a_maxrss ? '>' : ' ') : 'W'; - if (ap->a_nice < NZERO) - nice = '<'; - else if (ap->a_nice > NZERO) - nice = 'N'; - else - nice = ' '; - anom = (ap->a_flag&SUANOM) ? 'A' : ((ap->a_flag&SSEQL) ? 'S' : ' '); - 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; -{ - 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++; + 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--; +} + + +/* XXX - redo */ +saveuser(ki) + KINFO *ki; +{ + register struct usave *usp; + register struct user *up; + + 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_args = needcomm ? strdup(kvm_getargs(ki->ki_p, up)) : NULL; + 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_acflag = up->u_acflag; +#endif } - 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; +pscomp(k1, k2) + KINFO *k1, *k2; { - -#ifdef DEBUG - printf("%s\n", cp); + 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 -} - -min(a, b) -{ - - return (a < b ? a : b); -} - -pscomp(s1, s2) - struct savcom *s1, *s2; -{ - register int i; - if (uflg && !ssflg) - 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) -{ - 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); -} - -char *freebase; -int nleft; - -char * -alloc(size) - int size; -{ - 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); -} - -char * -savestr(cp) - char *cp; -{ - register int len; - register char *dp; - - len = strlen(cp); - dp = (char *)alloc(len+1); - strcpy(dp, cp); - return (dp); -} - -walk(np) - int np; -{ - register int i, j, k, l, m; -#undef afl -#undef sfl -#define afl(i,f) savcom[i].ap -> f -#define sfl(i,f) savcom[i].sun.ssp -> f - - for(i = 0; i < np; i = j) { - for(j = i; afl(j,a_ttyd) == afl(i,a_ttyd); j++) { - sfl(j,ss_brother) = -1; - sfl(j,ss_sons) = -1; - } - for(k = i+1; k < j; k++) { - if(sfl(k,ss_ppid) == sfl(i,ss_ppid)) { - for(l=i; sfl(l,ss_brother) != -1; - l=sfl(l,ss_brother)) ; - sfl(l,ss_brother) = k; - goto next; - } - for(l = i; l < j; l++) { - if(l == k) continue; - if(sfl(k,ss_ppid) == afl(l,a_pid)) { - if(sfl(l,ss_sons) == -1) - sfl(l,ss_sons) = k; - else { - for(m = sfl(l,ss_sons); - sfl(m,ss_brother) != -1; - m = sfl(m,ss_brother)) ; - sfl(m,ss_brother) = k; - } - goto next; - } - } - for(l = i; l < j; l++) { - if(l == k) continue; - if(sfl(k,ss_ppid) == sfl(l,ss_ppid)) { - for(m = k; sfl(m,ss_brother) != -1; - m = sfl(m,ss_brother)) ; - sfl(m,ss_brother) = l; - } - } - next: ; - } - walk1(i, 0); - } -} +kludge_oldps_options(s) + char *s; +{ + 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); +} + +#if __STDC__ +#include +#else +#include +#endif -walk1(pno, depth) - int pno, depth; +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif { - if(pno == -1) - return; -/*** printf("%5d, %d\n",outargs[pno].o_pid, depth); ***/ - walkpr(&savcom[pno], depth); - walk1(sfl(pno,ss_sons), depth+1); - walk1(sfl(pno,ss_brother), depth); + 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 *sshdr = -"TTY User SZ RSS CPU S PID "; - -walkpr(a, depth) - register struct savcom *a; - int depth; +usage() { - long tm; - - if(!depth) { - printf("%-2.2s", a->ap->a_tty); - printf(" %-8.8s", getname(a->ap->a_uid)); - } else - printf(" %-8s", &".......*"[8-(depth<=8?depth:8)]); - printf("%4d%4d", a->ap->a_size/2, a->ap->a_rss/2); - ptime(a->ap); - /* Once there was a "CCPU" field here. Subsumed by -S now. */ - printf(" %4.4s", state(a->ap)); - printf("%6u ", a->ap->a_pid); - if (a->ap->a_pid == 0) - printf(" swapper"); - else if (a->ap->a_pid == 2) - printf(" pagedaemon"); - else - printf(" %.*s", twidth - cmdstart - 2, a->ap->a_cmdp); - putchar('\n'); + (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); }