From 1ee1e8e921515f9bd5071990a405f99aa50366f5 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Sun, 30 Dec 1979 00:46:42 -0800 Subject: [PATCH] BSD 3 development Work on file usr/src/cmd/ps.c Synthesized-from: 3bsd --- usr/src/cmd/ps.c | 702 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 702 insertions(+) create mode 100644 usr/src/cmd/ps.c diff --git a/usr/src/cmd/ps.c b/usr/src/cmd/ps.c new file mode 100644 index 0000000000..ac451c301a --- /dev/null +++ b/usr/src/cmd/ps.c @@ -0,0 +1,702 @@ +/* + * ps - process status + * This is the augmented UCB ps for UCB/VM Unix (9/79) + * examine and print certain things about processes + * usage: ps [acgklrt#uvwx] [corefile] [swapfile] [system] + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct nlist nl[] = { + { "_proc" }, +#define X_PROC 0 + { "_swapdev" }, +#define X_SWAPDEV 1 + { "_swplo" }, +#define X_SWPLO 2 + { "_Usrptma" }, +#define X_USRPTMA 3 + { "_usrpt" }, +#define X_USRPT 4 + { "_text" }, +#define X_TEXT 5 + { "_nswap" }, +#define X_NSWAP 6 + { 0 }, +}; + +struct proc mproc; +struct text text[NTEXT]; + +#define INTPPG (NBPG/sizeof(int)) /* ints per page */ +union { + struct user yy; + int xx[INTPPG][UPAGES]; + } zz; +#define clear(x) ((int)x & 0x7fffffff) +#define u zz.yy +int chkpid = 0; +int aflg; /* -a: all processes, not just mine */ +int cflg; /* -c: complete listing of args, not just comm. */ +int gflg; /* -g: complete listing including group headers, etc */ +int kflg; /* -k: read from core file instead of real memory */ +int lflg; /* -l: long listing form */ +int rflg; /* -r: raw output in style */ +int sflg; /* -s: stack depth */ +int uflg; /* -u: user name */ +int vflg; /* -v: virtual memory statistics */ +int wflg; /* -w[w]: wide terminal */ +int xflg; /* -x: ALL processes, even those without ttys */ +int login; /* -: this is a login shell */ +char *tptr; +char *gettty(); +int pscomp(); +struct pte pagetbl[NPTEPG]; +int kmem; +int mem; +int swap; +daddr_t swplo; +int nswap; +int Usrptma; +int usrpt; + +int ndev; +struct devl { + char dname[DIRSIZ]; + dev_t dev; +} devl[256]; + +struct psout outargs[NPROC]; /* info for first npr processes */ +int npr; /* number of processes found so far */ +int argwidth; /* number of chars of args to print */ + +char *coref; + +main(argc, argv) +char **argv; +{ + int i; + char *ap; + int uid, puid; + char obuf[BUFSIZ]; + register struct nlist *nlp; + + setbuf(stdout, obuf); + argc--, argv++; + if (argc>0) { + ap = argv[0]; + while (*ap) switch (*ap++) { + case '-': + break; + + case 'a': + aflg++; + break; + + case 'c': + cflg++; + break; + + case 'g': + gflg++; + break; + + case 'k': + kflg++; + break; + + case 'l': + lflg++; + break; + + case 'r': + rflg++; + break; + + case 's': + sflg++; + break; + + case 't': + if(*ap) + tptr = ap; + aflg++; + gflg++; + if (*tptr == '?') + xflg++; + while (*ap) + ap++; + break; + + case 'u': + uflg++; + break; + + case 'v': + vflg++; + break; + + case 'w': + wflg++; + break; + + case 'x': + xflg++; + break; + + default: + chkpid=atoi(--ap); + *ap = '\0'; + aflg++; + xflg++; + break; + } + } + coref = "/dev/kmem"; + if(kflg) + coref = argc > 1 ? argv[1] : "/vmcore"; + + if ((kmem = open(coref, 0)) < 0) { + perror(coref); + done(1); + } + if ((mem = open("/dev/mem", 0)) < 0) { + fprintf(stderr, "No mem\n"); + done(1); + } + if (kflg) + mem = kmem; + + if ((swap = open(argc>2 ? argv[2]: "/dev/drum", 0)) < 0) { + fprintf(stderr, "Can't open /dev/drum\n"); + done(1); + } + + nlist(argc>3 ? argv[3] : "/vmunix", nl); + if (nl[0].n_type==0) { + fprintf(stderr, "No namelist\n"); + done(1); + } + + if(chdir("/dev") < 0) { + fprintf(stderr, "Can't change to /dev\n"); + done(1); + } + if (kflg) + for (nlp= nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++) + nlp->n_value &= 0x7ffffffff; + Usrptma = nl[X_USRPTMA].n_value; + usrpt = nl[X_USRPT].n_value; + /* + * read kmem to find swap dev. + */ + lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0); + read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value)); + /* + * Find base and size of swap + */ + lseek(kmem, (long)nl[X_SWPLO].n_value, 0); + read(kmem, &swplo, sizeof(swplo)); + lseek(kmem, (long)nl[X_NSWAP].n_value, 0); + read(kmem, &nswap, sizeof (nswap)); + /* + * If v flag get text table + */ + if (vflg) { + lseek(kmem, (long)nl[X_TEXT].n_value, 0); + read(kmem, text, sizeof (text)); + } + if (kflg) + swplo = 0; + getdev(); + uid = getuid(); + if (sflg + lflg + vflg + uflg > 1) { + printf("Cannot combine s, l, v, and/or u.\n"); + exit(1); + } + /* different psout widths depending on how much printed & w flag */ + if (wflg <= 1) { + argwidth = 63; + if (wflg) argwidth += 52; /* 132 col term */ + if (lflg) argwidth -= 49; /* extra junk printed */ + if (vflg) argwidth -= 48; /* extra junk for -v */ + if (sflg) argwidth -= 4; /* 4 cols of stack size */ + if (uflg) argwidth -= 27; /* user name */ + } else argwidth = 127; + if (rflg) + ; /* No heading for raw output */ + else if (lflg) + printf(" F S UID PID PPID CPU PRI NICE ADDR SZ RSS WCHAN TTY TIME COMMAND\n"); + else if (vflg) + printf("F PID TT TIME TIM SL MINFLT MAJFLT SIZE RSS SRS TSIZ TRS PF COMMAND\n"); + else if (uflg) + printf("USER PID %%CPU NICE SZ RSS TTY TIME COMMAND\n"); + else if (chkpid==0) { + if (sflg) + printf(" SSIZ"); + printf(" PID TTY TIME COMMAND\n"); + } + fflush(stdout); + for (i=0; i + register FILE *df; + struct stat sbuf; + struct direct dbuf; + + if ((df = fopen("/dev", "r")) == NULL) { + fprintf(stderr, "Can't open /dev\n"); + done(1); + } + ndev = 0; + while (fread(&dbuf, sizeof(dbuf), 1, df) == 1) { + if(dbuf.d_ino == 0) + continue; + if(stat(dbuf.d_name, &sbuf) < 0) + continue; + if ((sbuf.st_mode&S_IFMT) != S_IFCHR) + continue; + strcpy(devl[ndev].dname, dbuf.d_name); + devl[ndev].dev = sbuf.st_rdev; + ndev++; + } + fclose(df); +} + +savcom(puid) +{ + int abuf[INTPPG]; + long addr; + register int *ip; + register struct psout *a; + register char *cp, *cp1; + long tm; + int cc, nbad; + int szpt, p0br; + register char *tp; + struct dblock db; + struct pte apte; + + /* skip long sleeping or dead processes if -v unless -g or -x */ + if (!gflg && vflg && !xflg) { + switch (mproc.p_stat) { + + case SSLEEP: + case SSTOP: + if (mproc.p_slptime > MAXSLP) + return (0); + break; + + case SRUN: + case SIDL: + break; + + case SZOMB: + return (0); + } + } + /* read in the user structure */ + if ((mproc.p_flag& SLOAD ) == 0) { + /* not loaded - get from swap */ + addr = (mproc.p_swaddr+swplo)<<9; + lseek(swap, addr, 0); + if (read(swap, &u, sizeof(u)) != sizeof(u)) + return(0); + } else { + /* loaded, get each page from memory separately */ + for(cc=0; cco_uid = puid; + a->o_pid = mproc.p_pid; + a->o_flag = mproc.p_flag; + a->o_ppid = mproc.p_ppid; + a->o_cpu = mproc.p_cpu; + a->o_pctcpu = 0.0; /* This needs to be fixed later */ + a->o_pri = mproc.p_pri; + a->o_nice = mproc.p_nice; + a->o_addr0 = mproc.p_addr[0]; + a->o_dsize = mproc.p_dsize; + a->o_ssize = mproc.p_ssize; + a->o_rssize = mproc.p_rssize; + a->o_swrss = mproc.p_swrss; + a->o_wchan = mproc.p_wchan; + a->o_pgrp = mproc.p_pgrp; + a->o_tty[0] = tp[0]; + a->o_tty[1] = tp[1] ? tp[1] : ' '; + a->o_ttyd = u.u_ttyd; + a->o_stat = mproc.p_stat; + a->o_flag = mproc.p_flag; + if (a->o_stat==SZOMB) return(1); + a->o_utime = u.u_utime; + a->o_stime = u.u_stime; + a->o_cutime = u.u_cutime; + a->o_cstime = u.u_cstime; + a->o_sigs = u.u_signal[SIGINT] + u.u_signal[SIGQUIT]; + a->o_time = mproc.p_time; + a->o_slptime = mproc.p_slptime; + a->o_uname[0] = 0; + if (sflg) { + for (cp = (char *)u.u_stack; cp < (char *)&u + ctob(UPAGES); cp++) + if (*cp) + break; + a->o_stksize = (int) ((char *)&u + ctob(UPAGES) - cp); + } + if (mproc.p_stat==SZOMB) return(1); + if (vflg) { + register struct text *xp; + + if (mproc.p_textp) { + xp = &text[mproc.p_textp - (struct text *)nl[5].n_value]; + a->o_xsize = xp->x_size; + a->o_xrssize = xp->x_rssize; + } else { + a->o_xsize = 0; + a->o_xrssize = 0; + } + a->o_aveflt = mproc.p_aveflt; + a->o_minorflt = u.u_minorflt; + a->o_majorflt = u.u_majorflt; + } + strcpy(a->o_comm, u.u_comm); + if (cflg) + return (1); + a->o_args[0] = 0; /* in case of early return */ + if ((mproc.p_flag & SLOAD) == 0) { + vstodb(0, 1, &u.u_smap, &db, 1); + addr = ctob(swplo + db.db_base); + lseek(swap, addr, 0); + if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf)) + goto garbage; + } else { + szpt = u.u_pcb.pcb_szpt; + p0br = kflg ? clear((int)mproc.p_p0br) : (int)mproc.p_p0br; + cc = Usrptma + (p0br + NBPG*(szpt-1) - usrpt)/NPTEPG; + lseek(kmem, cc, 0); + if (read(kmem, &apte, sizeof(apte)) != sizeof(apte)) + goto garbage; + lseek(mem, ctob(apte.pg_pfnum), 0); + if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl)) + goto garbage; + if (pagetbl[NPTEPG-1].pg_fod == 0 && pagetbl[NPTEPG-1].pg_pfnum) { + lseek(mem,ctob((pagetbl[NPTEPG-1].pg_pfnum)),0); + if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf)) + goto garbage; + } else { + vstodb(0, 1, &u.u_smap, &db, 1); + addr = ctob(swplo + db.db_base); + lseek(swap, addr, 0); + if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf)) + goto garbage; + } + } + abuf[INTPPG] = 0; + for (ip = &abuf[INTPPG-2]; ip > abuf;) { + if (*--ip == -1 || *ip == 0) { + cp = (char *)(ip+1); + if (*cp==0) + cp++; + nbad = 0; + for (cp1 = cp; cp1 < (char *)&abuf[INTPPG]; cp1++) { + cc = *cp1&0177; + if (cc==0) + *cp1 = ' '; + else if (cc < ' ' || cc > 0176) { + if (++nbad >= 5) { + *cp1++ = ' '; + break; + } + *cp1 = '?'; + } else if (cc=='=') { + *cp1 = 0; + while (cp1>cp && *--cp1!=' ') + *cp1 = 0; + break; + } + } + while (*--cp1==' ') + *cp1 = 0; + strcpy(a->o_args, cp); +garbage: + cp = a->o_args; + if (cp[0]=='-'&&cp[1]<=' ' || cp[0]=='?' || cp[0]<=' ') { + strcat(cp, " ("); + strcat(cp, u.u_comm); + strcat(cp, ")"); + } + cp[127] = 0; /* max room in psout is 128 chars */ + if (xflg || gflg || tptr || cp[0]!='-') + return(1); + return(0); + } + } + goto garbage; +} + +prcom(a) + register struct psout *a; +{ + long tm; + + if (rflg) { + write(1, a, sizeof (*a)); + return(0); + } + if (lflg) { + printf("%4x %c", 0xffff & a->o_flag, + "0SWRIZT"[a->o_stat]); + printf("%4d", a->o_uid); + } else if (vflg) { + switch (a->o_stat) { + + case SSLEEP: + case SSTOP: + if ((a->o_flag & SLOAD) == 0) + printf("W"); + else if (a->o_pri >= PZERO) + printf("S"); + else if (a->o_flag & SPAGE) + printf("P"); + else + printf("D"); + break; + + case SRUN: + case SIDL: + if (a->o_flag & SLOAD) + printf("R"); + else + printf("W"); + break; + } + if (a->o_nice > NZERO) + printf("N"); + else + printf(" "); + } else if (uflg) { + printf("%-8.8s", a->o_uname); + } + if (sflg) { + printf("%5d", a->o_stksize); + } + printf("%6u", a->o_pid); + if (lflg) + printf("%6u%4d%4d%4d%6x", a->o_ppid, a->o_cpu&0377, + a->o_pri, a->o_nice, a->o_addr0); + else if (uflg) + printf("%5.1f%4d ", a->o_pctcpu, a->o_nice); + if (lflg || uflg) + printf("%4d%5d", a->o_dsize+a->o_ssize, a->o_rssize); + if (lflg) + if (a->o_wchan) + printf("%6x", clear(a->o_wchan)); + else + printf(" "); + printf(" %-2.2s", a->o_tty); + if (a->o_stat==SZOMB) { + printf(" "); + return(1); + } + tm = (a->o_utime + a->o_stime + 30)/60; + printf("%3ld:", tm/60); + tm %= 60; + printf(tm<10?"0%ld":"%ld", tm); + if (vflg) { +/* + tm = (a->o_stime + 30) / 60; + printf(" %2ld:", tm/60); + tm %= 60; + printf(tm<10?"0%ld":"%ld", tm); +*/ + printf("%4d%3d", a->o_time, a->o_slptime); + } +#ifdef notdef + if (0 && lflg==0) { /* 0 == old tflg (print long times) */ + tm = (a->o_cstime + 30)/60; + printf(" %2ld:", tm/60); + tm %= 60; + printf(tm<10?"0%ld":"%ld", tm); + tm = (a->o_cutime + 30)/60; + printf(" %2ld:", tm/60); + tm %= 60; + printf(tm<10?"0%ld":"%ld", tm); + } +#endif + if (vflg) { + printf("%7d%7d",a->o_minorflt,a->o_majorflt); + printf("%5d%4d%4d", a->o_dsize+a->o_ssize, a->o_rssize, a->o_swrss); + printf("%5d%4d", a->o_xsize, a->o_xrssize); + printf("%3d", a->o_aveflt); + } + if (a->o_pid == 0) { + printf(" swapper"); + return(1); + } + if (a->o_pid == 2) { + printf(" pagedaemon"); + return(1); + } + if (cflg) { + printf(" %s", a->o_comm); + return(1); + } + a -> o_args[argwidth] = 0; /* force it to quit early */ + printf(" %s", a->o_args); + return (1); +} + +char * +gettty() +{ + register i; + register char *p; + + if (u.u_ttyp==0) + return("?"); + for (i=0; idm_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); +} + +panic(cp) + char *cp; +{ + +#ifdef DEBUG + printf("%s\n", cp); +#endif +} + +min(a, b) +{ + + return (a < b ? a : b); +} + +done(exitno) +{ + if (login) { + printf("Press return when done: "); + getchar(); + } + exit(exitno); +} + +/* + * fixup figures out everybodys name and sorts into a nice order. + */ +fixup(np) int np; { + register int i; + register struct passwd *pw; + struct passwd *getpwent(); + + if (uflg) { + /* + * If we want names, traverse the password file. For each + * passwd entry, look for it in the processes. + * In case of multiple entries in /etc/passwd, we believe + * the first one (same thing ls does). + */ + while ((pw=getpwent()) != NULL) { + for (i=0; i pw_uid) { + if (outargs[i].o_uname[0] == 0) + strcpy(outargs[i].o_uname, pw -> pw_name); + } + } + } + + qsort(outargs, np, sizeof(outargs[0]), pscomp); +} + +pscomp(x1, x2) struct psout *x1, *x2; { + register int c; + + c = (x1)->o_ttyd - (x2)->o_ttyd; + if (c==0) c = (x1)->o_pid - (x2)->o_pid; + return(c); +} -- 2.20.1