guy@gorodish.UUCP (01/28/87)
Index: bin/ps.c 4.3BSD Description: 1) "ps" doesn't understand that zombie processes, lacking U areas as they do, don't have controlling terminals. 2) "ps" also doesn't understand that u.u_ttyd can either be zero because a process has no controlling terminal or because the dev_t of the controlling terminal happens to be major device 0, minor device 0; since "/dev/console" is usually 0/0, this means that processes attached to the console get mixed in with unattched processes. 3) Printing the name of the closest symbol less than or equal to the value of the wait channel isn't always the right thing to do; processes in a "sigpause" are waiting on (caddr_t)&u, but unless you happen to know that already seeing "u" in the WCHAN field doesn't tell you very much. 4) A flag to restrict the output to "running" processes (runnable processes, or processes in short-term waits) might be useful; the suggestion and the code implementing this came from Rick Adams at the Center for Seismic Studies. 5) It might be useful to print the time a process started in at least one of the formats; again, this suggestion and the code implementing this (printing the start date/time in the "u" format) came from Rick Adams. 6) Some of the error messages could use a little cleaning up. 7) A couple of variables were unused. 8) The manual page could use a little cleaning up; the changes here if added, should also be documented. Repeat-By: 1) Notice that you occasionally "ps" claim that processes that you never had anything to do with are attached to your terminal. 2) Notice that on a "ps ax", a few processes attached to "co" show up in the middle of the big block of processes attached to no terminal on occasion (namely if their PIDs are less than that of a process with no terminal). Fix: *** /arch/4.3/usr/src/bin/ps.c Thu May 8 12:49:00 1986 --- ./ps.c Tue Jan 27 12:36:53 1987 *************** *** 91,96 **** --- 91,98 ---- #define X_CMAP 27 "_buffers", #define X_BUFFERS 28 + "_boottime", + #define X_BOOTTIME 29 "" }; *************** *** 117,122 **** --- 119,125 ---- dev_t a_ttyd; time_t a_cpu; size_t a_maxrss; + struct timeval a_start; }; char *lhdr; *************** *** 143,148 **** --- 146,153 ---- struct proc proc[NPROC]; /* a few, for less syscalls */ struct proc *mproc; struct text *text; + struct timeval boottime; + time_t now; union { struct user user; *************** *** 157,163 **** #endif int chkpid = -1; ! int aflg, cflg, eflg, gflg, kflg, lflg, nflg, sflg, uflg, vflg, xflg, Uflg; int nchans; /* total # of wait channels */ char *tptr; --- 162,168 ---- #endif int chkpid = -1; ! int aflg, cflg, eflg, gflg, kflg, lflg, nflg, rflg, sflg, uflg, vflg, xflg, Uflg; int nchans; /* total # of wait channels */ char *tptr; *************** *** 224,229 **** --- 229,249 ---- "calimit", NULL }; + /* + * names listed here get mapped -- this is because only a guru will + * necessarily know that something waiting on "selwait" is waiting + * for a select to finish + */ + struct wchan_map { + char *map_from; + char *map_to; + } wchan_map_list[] = { + { "proc", "child" }, + { "u", "pause" }, + { "selwait", "select" }, + { "mbutl", "socket" }, + { NULL, NULL }, + }; int npr; *************** *** 289,294 **** --- 309,317 ---- case 'n': nflg++; break; + case 'r': + rflg++; + break; case 's': sflg++; break; *************** *** 338,347 **** --- 361,373 ---- openfiles(argc, argv); getkvars(argc, argv); uid = getuid(); + (void) time(&now); printhdr(); procp = getw(nl[X_PROC].n_value); nproc = getw(nl[X_NPROC].n_value); savcom = (struct savcom *)calloc((unsigned) nproc, sizeof (*savcom)); + klseek(kmem, (long)nl[X_BOOTTIME].n_value, 0); + read(kmem, &boottime, sizeof (boottime)); for (i=0; i<nproc; i += NPROC) { klseek(kmem, (long)procp, 0); j = nproc - i; *************** *** 374,379 **** --- 400,408 ---- mproc->p_stat == SSTOP)) continue; } + if (rflg && !(mproc->p_stat == SRUN + || mproc->p_pri < PZERO)) + continue; save(); } } *************** *** 413,419 **** klseek(kmem, (long)loc, 0); if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word)) ! printf("error reading kmem at %x\n", loc); return (word); } --- 442,448 ---- klseek(kmem, (long)loc, 0); if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word)) ! printf("error reading %s at %x\n", kmemf, loc); return (word); } *************** *** 444,449 **** --- 473,479 ---- setgid(getgid()); setuid(getuid()); if ((fp = fopen(psdb, "w")) == NULL) { + fprintf(stderr, "ps: "); perror(psdb); exit(1); } else *************** *** 482,487 **** --- 512,518 ---- if ((fp = fopen(psdb, "r")) == NULL) { if (errno == ENOENT) return (0); + fprintf(stderr, "ps: "); perror(psdb); exit(1); } *************** *** 539,544 **** --- 570,576 ---- kmemf = argc > 2 ? argv[2] : "/vmcore"; kmem = open(kmemf, 0); if (kmem < 0) { + fprintf(stderr, "ps: "); perror(kmemf); exit(1); } *************** *** 549,554 **** --- 581,587 ---- memf = "/dev/mem"; mem = open(memf, 0); if (mem < 0) { + fprintf(stderr, "ps: "); perror(memf); exit(1); } *************** *** 557,562 **** --- 590,596 ---- swapf = argc>3 ? argv[3]: "/dev/drum"; swap = open(swapf, 0); if (swap < 0) { + fprintf(stderr, "ps: "); perror(swapf); exit(1); } *************** *** 588,594 **** } if (nl[0].n_type == 0) { ! fprintf(stderr, "%s: No namelist\n", nlistf); exit(1); } if (kflg) { --- 622,628 ---- } if (nl[0].n_type == 0) { ! fprintf(stderr, "ps: %s: No namelist\n", nlistf); exit(1); } if (kflg) { *************** *** 599,605 **** Sysmap = (struct pte *) calloc((unsigned) Syssize, sizeof (struct pte)); if (Sysmap == NULL) { ! fprintf(stderr, "Out of space for Sysmap\n"); exit(1); } addr = (long) nl[X_SYSMAP].n_value; --- 633,639 ---- Sysmap = (struct pte *) calloc((unsigned) Syssize, sizeof (struct pte)); if (Sysmap == NULL) { ! fprintf(stderr, "ps: Out of space for Sysmap\n"); exit(1); } addr = (long) nl[X_SYSMAP].n_value; *************** *** 636,642 **** text = (struct text *) calloc((unsigned) 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); --- 670,676 ---- text = (struct text *) calloc((unsigned) ntext, sizeof (struct text)); if (text == 0) { ! fprintf(stderr, "ps: no room for text table\n"); exit(1); } atext = (struct text *)getw(nl[X_TEXT].n_value); *************** *** 743,754 **** struct lttys *lt; if (chdir("/dev") < 0) { ! perror("/dev"); exit(1); } dialbase = -1; if ((df = opendir(".")) == NULL) { ! fprintf(stderr, "Can't open . in /dev\n"); exit(1); } while ((dbuf = readdir(df)) != NULL) --- 777,789 ---- struct lttys *lt; if (chdir("/dev") < 0) { ! perror("ps: /dev"); exit(1); } dialbase = -1; if ((df = opendir(".")) == NULL) { ! fprintf(stderr, "ps: "); ! perror("Can't open . in /dev"); exit(1); } while ((dbuf = readdir(df)) != NULL) *************** *** 907,914 **** struct stat stb; int x; ! if (u.u_ttyp == 0) return("?"); x = u.u_ttyd & 017; for (dp = &allttys[cand[x]]; dp != &allttys[-1]; dp = &allttys[dp->cand]) { --- 942,951 ---- struct stat stb; int x; ! if (u.u_ttyp == 0) { ! u.u_ttyd = -1; return("?"); + } x = u.u_ttyd & 017; for (dp = &allttys[cand[x]]; dp != &allttys[-1]; dp = &allttys[dp->cand]) { *************** *** 950,964 **** 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 *)calloc(1, sizeof (struct asav)); sp->ap->a_cmdp = cmdp; #define e(a,b) ap->a = mproc->b --- 987,1002 ---- register struct text *xp; char *ttyp, *cmdp; ! if (mproc->p_stat != SZOMB) { ! if (getu() == 0) ! return; ! ttyp = gettty(); ! } else ! ttyp = "?"; /* zombies are not attached to terminals */ if (xflg == 0 && ttyp[0] == '?' || tptr && strncmp(tptr, ttyp, 2)) return; sp = &savcom[npr]; cmdp = getcmd(); sp->ap = ap = (struct asav *)calloc(1, sizeof (struct asav)); sp->ap->a_cmdp = cmdp; #define e(a,b) ap->a = mproc->b *************** *** 1070,1076 **** return (0); (void) lseek(swap, (long)dtob(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); } --- 1108,1114 ---- return (0); (void) lseek(swap, (long)dtob(mproc->p_swaddr), 0); if (read(swap, (char *)&user.user, size) != size) { ! fprintf(stderr, "ps: can't read u for pid %d from %s\n", mproc->p_pid, swapf); return (0); } *************** *** 1081,1087 **** pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; klseek(kmem, (long)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, kmemf); return (0); } --- 1119,1125 ---- pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; klseek(kmem, (long)pteaddr, 0); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { ! printf("ps: can't read indir pte to get u for pid %d from %s\n", mproc->p_pid, kmemf); return (0); } *************** *** 1089,1095 **** (long)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, memf); return (0); } --- 1127,1133 ---- (long)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0); if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { ! printf("ps: can't read page table for u of pid %d from %s\n", mproc->p_pid, memf); return (0); } *************** *** 1103,1109 **** i = ncl * CLSIZE; lseek(mem, (long)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); } --- 1141,1147 ---- i = ncl * CLSIZE; lseek(mem, (long)ctob(arguutl[CLSIZE+i].pg_pfnum), 0); if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) { ! printf("ps: can't read page %d of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf); return(0); } *************** *** 1233,1243 **** } char *uhdr = ! "%s PID %%CPU %%MEM SZ RSS TT STAT TIME"; upr(sp) struct savcom *sp; { register struct asav *ap = sp->ap; int vmsize, rmsize; vmsize = pgtok((ap->a_size + ap->a_tsiz)); --- 1271,1282 ---- } char *uhdr = ! "%s PID %%CPU %%MEM SZ RSS TT STAT START TIME"; upr(sp) struct savcom *sp; { register struct asav *ap = sp->ap; + char *cp; int vmsize, rmsize; vmsize = pgtok((ap->a_size + ap->a_tsiz)); *************** *** 1253,1258 **** --- 1292,1304 ---- putchar(' '); ptty(ap->a_tty); printf(" %4.4s", state(ap)); + if (ap->a_start.tv_sec == 0) + ap->a_start = boottime; + cp = ctime(&ap->a_start.tv_sec); + if ((now - ap->a_start.tv_sec) > 60*60*24) + printf("%.7s", cp+3); + else + printf("%.6s ", cp+10); ptime(ap); } *************** *** 1488,1504 **** newloc = loc & ~0xc0000000; p = btop(newloc); if ((loc & 0xc0000000) == 0) { ! fprintf(stderr, "Vtophys: translating non-kernel address\n"); return((off_t) -1); } if (p >= Syssize) { ! fprintf(stderr, "Vtophys: page out of bound (%d>=%d)\n", p, Syssize); return((off_t) -1); } if (Sysmap[p].pg_v == 0 && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) { ! fprintf(stderr, "Vtophys: page not valid\n"); return((off_t) -1); } loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET)); --- 1534,1550 ---- newloc = loc & ~0xc0000000; p = btop(newloc); if ((loc & 0xc0000000) == 0) { ! fprintf(stderr, "ps: Vtophys: translating non-kernel address\n"); return((off_t) -1); } if (p >= Syssize) { ! fprintf(stderr, "ps: Vtophys: page out of bound (%d>=%d)\n", p, Syssize); return((off_t) -1); } if (Sysmap[p].pg_v == 0 && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) { ! fprintf(stderr, "ps: Vtophys: page not valid\n"); return((off_t) -1); } loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET)); *************** *** 1540,1546 **** struct nlist *list; { register struct nlist *p, *q; - register char *s1, *s2; register n, m; int maxlen, nreq; FILE *f; --- 1586,1591 ---- *************** *** 1605,1612 **** if (!nflg) addchan(&nambuf[1], (caddr_t) q->n_value); for (p = list; p->n_un.n_name && p->n_un.n_name[0]; p++) { - s1 = p->n_un.n_name; - s2 = nambuf; if (strcmp(p->n_un.n_name, nambuf) == 0) { p->n_value = q->n_value; p->n_type = q->n_type; --- 1650,1655 ---- *************** *** 1634,1639 **** --- 1677,1683 ---- static int left = 0; register struct wchan *wp; register char **p; + register struct wchan_map *mp; for (p = wchan_stop_list; *p; p++) { if (**p != *name) /* quick check first */ *************** *** 1640,1645 **** --- 1684,1695 ---- continue; if (strncmp(name, *p, WNAMESIZ) == 0) return; /* if found, don't add */ + } + for (mp = wchan_map_list; mp->map_from; mp++) { + if (*(mp->map_from) != *name) /* quick check first */ + continue; + if (strncmp(name, mp->map_from, WNAMESIZ) == 0) + name = mp->map_to; /* if found, remap */ } if (left == 0) { if (wchanhd) { *** /arch/4.3/usr/man/man1/ps.1 Mon May 12 08:52:58 1986 --- ./ps.1 Tue Jan 27 13:03:00 1987 *************** *** 11,29 **** .SH SYNOPSIS .B ps [ ! .B acegklnstuvwxU# ] .SH DESCRIPTION .I Ps prints information about processes. ! Normally, only your processes are candidates to be printed by ! .I ps; ! specifying .B a causes other users' processes to be candidates to be printed; specifying .B x ! includes processes without control terminals in the candidate pool. .PP All output formats include, for each process, the process id PID, control terminal of the process TT, cpu time used by the process TIME --- 11,34 ---- .SH SYNOPSIS .B ps [ ! .B aCcegklnsStuvwxU# ] .SH DESCRIPTION .I Ps prints information about processes. ! Normally, only processes that are running with your effective user ID and ! that have controlling terminals are printed. ! Specifying .B a causes other users' processes to be candidates to be printed; specifying .B x ! includes processes without controlling terminals in the candidate pool. ! Specifying ! .B r ! restricts the list of processes printed to ``running'' processes; i.e., ! runnable processes and processes in page wait or in disk (or other short ! term) waits. .PP All output formats include, for each process, the process id PID, control terminal of the process TT, cpu time used by the process TIME *************** *** 36,43 **** P for processes in page wait, D for those in disk (or other short term) waits, S for those sleeping for less than about 20 seconds, ! and I for idle (sleeping longer than about 20 seconds) ! processes. The second letter indicates whether a process is swapped out, showing W if it is, or a blank if it is loaded (in-core); a process which has specified a soft limit on memory requirements --- 41,50 ---- P for processes in page wait, D for those in disk (or other short term) waits, S for those sleeping for less than about 20 seconds, ! I for idle processes (those sleeping longer than about 20 seconds), ! and Z for ``zombie'' processes (those that have terminated and are ! waiting for their parent process to do a ! .IR wait (2)). The second letter indicates whether a process is swapped out, showing W if it is, or a blank if it is loaded (in-core); a process which has specified a soft limit on memory requirements *************** *** 60,74 **** Here are the options: .TP 5 .B a ! asks for information about all processes with terminals (ordinarily only one's own processes are displayed). .TP 5 .B c ! prints the command name, as stored internally in the system for purposes of accounting, rather than the command arguments, which are kept in the process' address space. This is more reliable, if less informative, since the process is free to destroy the latter information. .TP 5 .B e Asks for the environment to be printed as well as the arguments to the command. .TP 5 --- 67,84 ---- Here are the options: .TP 5 .B a ! Asks for information about all processes with terminals (ordinarily only one's own processes are displayed). .TP 5 .B c ! Prints the command name, as stored internally in the system for purposes of accounting, rather than the command arguments, which are kept in the process' address space. This is more reliable, if less informative, since the process is free to destroy the latter information. .TP 5 + .B C + Displays raw CPU time in the %CPU field instead of the decaying average. + .TP 5 .B e Asks for the environment to be printed as well as the arguments to the command. .TP 5 *************** *** 83,96 **** .TP 5 .B k causes the file ! .I /vmcore ! is used in place of ! .IR /dev/kmem " and " /dev/mem. This is used for postmortem system debugging. .TP 5 .B l ! asks for a long listing, with fields PPID, CP, PRI, NI, ADDR, SIZE, RSS and WCHAN as described below. .TP 5 .B n --- 93,106 ---- .TP 5 .B k causes the file ! .B /vmcore ! to be used in place of ! .BR /dev/kmem " and " /dev/mem . This is used for postmortem system debugging. .TP 5 .B l ! Asks for a long listing, with fields PPID, CP, PRI, NI, ADDR, SIZE, RSS and WCHAN as described below. .TP 5 .B n *************** *** 99,112 **** symbolically, or, in a user listing, the USER field is replaced by a UID field. .TP 5 .B s Adds the size SSIZ of the kernel stack of each process (for use by system maintainers) to the basic output format. .TP 5 \fBt\fIx\fR restricts output to processes whose controlling tty is \fIx\fR (which should be specified as printed by ! .I ps, e.g. .I t3 for tty3, --- 109,129 ---- symbolically, or, in a user listing, the USER field is replaced by a UID field. .TP 5 + .B r + Restricts output to ``running'' processes. + .TP 5 .B s Adds the size SSIZ of the kernel stack of each process (for use by system maintainers) to the basic output format. .TP 5 + .B S + Display accumulated CPU time used by this process and all of its reaped + children. + .TP 5 \fBt\fIx\fR restricts output to processes whose controlling tty is \fIx\fR (which should be specified as printed by ! .IR ps , e.g. .I t3 for tty3, *************** *** 123,129 **** .TP 5 .B u A user oriented output is produced. ! This includes fields USER, %CPU, NICE, SIZE, and RSS as described below. .TP 5 .B v A version of the output containing virtual memory statistics is output. --- 140,146 ---- .TP 5 .B u A user oriented output is produced. ! This includes fields USER, %CPU, %MEM, SIZE, RSS, and START as described below. .TP 5 .B v A version of the output containing virtual memory statistics is output. *************** *** 131,146 **** and %MEM, described below. .TP 5 .B w ! Use a wide output format (132 columns rather than 80); if repeated, ! e.g. ww, use arbitrarily wide output. This information is used to decide how much of long commands to print. .TP 5 .B x ! asks even about processes with no terminal. .TP .B U ! causes ps to update a private database where is keeps system ! information. Thus ``ps U'' should be included in the /etc/rc file. .TP 5 .B # A process number may be given, --- 148,169 ---- and %MEM, described below. .TP 5 .B w ! Use a wide output format (132 columns rather than 80); if repeated, ! e.g. ! .BR ww , ! use arbitrarily wide output. This information is used to decide how much of long commands to print. .TP 5 .B x ! Asks even about processes with no controlling terminal. .TP .B U ! Causes ! .I ps ! to update a private database where is keeps system ! information. Thus ``ps U'' should be included in the ! .B /etc/rc ! file. .TP 5 .B # A process number may be given, *************** *** 151,157 **** .PP A second argument is taken to be the file containing the system's ! namelist. Otherwise, /vmunix is used. A third argument tells .I ps where to look for --- 174,182 ---- .PP A second argument is taken to be the file containing the system's ! namelist. Otherwise, ! .B /vmunix ! is used. A third argument tells .I ps where to look for *************** *** 158,167 **** .I core if the .B k ! option is given, instead of /vmcore. If a fourth argument is given, it is taken to be the name of a swap file to use instead of ! the default /dev/drum. .PP Fields which are not common to all output formats: .PD 0 --- 183,194 ---- .I core if the .B k ! option is given, instead of ! .BR /vmcore . If a fourth argument is given, it is taken to be the name of a swap file to use instead of ! the default ! .BR /dev/drum . .PP Fields which are not common to all output formats: .PD 0 *************** *** 194,200 **** .IP SL 10 sleep time of the process (seconds blocked) .IP PAGEIN 10 ! number of disk i/o's resulting from references by the process to pages not loaded in core. .IP UID 10 numerical user-id of process owner --- 221,227 ---- .IP SL 10 sleep time of the process (seconds blocked) .IP PAGEIN 10 ! number of disk I/O's resulting from references by the process to pages not loaded in core. .IP UID 10 numerical user-id of process owner *************** *** 204,209 **** --- 231,239 ---- short-term cpu utilization factor (used in scheduling) .IP PRI 10 process priority (non-positive when in non-interruptible wait) + .IP START 10 + time the process was created if that was today, or the date it was + created if that was before today .IP ADDR 10 swap address of the process .IP WCHAN 10
guy@gorodish.UUCP (01/30/87)
> 5) It might be useful to print the time a process started in at > least one of the formats; again, this suggestion and the code > implementing this (printing the start date/time in the "u" format) > came from Rick Adams. Except that *his* code actually *set* "ap->a_start". Here's a corrected version of the "diff"s. *** /arch/4.3/usr/src/bin/ps.c Thu May 8 12:49:00 1986 --- ps.c Thu Jan 29 16:19:24 1987 *************** *** 91,96 **** --- 91,98 ---- #define X_CMAP 27 "_buffers", #define X_BUFFERS 28 + "_boottime", + #define X_BOOTTIME 29 "" }; *************** *** 117,122 **** --- 119,125 ---- dev_t a_ttyd; time_t a_cpu; size_t a_maxrss; + struct timeval a_start; }; char *lhdr; *************** *** 143,148 **** --- 146,153 ---- struct proc proc[NPROC]; /* a few, for less syscalls */ struct proc *mproc; struct text *text; + struct timeval boottime; + time_t now; union { struct user user; *************** *** 157,163 **** #endif int chkpid = -1; ! int aflg, cflg, eflg, gflg, kflg, lflg, nflg, sflg, uflg, vflg, xflg, Uflg; int nchans; /* total # of wait channels */ char *tptr; --- 162,168 ---- #endif int chkpid = -1; ! int aflg, cflg, eflg, gflg, kflg, lflg, nflg, rflg, sflg, uflg, vflg, xflg, Uflg; int nchans; /* total # of wait channels */ char *tptr; *************** *** 224,229 **** --- 229,249 ---- "calimit", NULL }; + /* + * names listed here get mapped -- this is because only a guru will + * necessarily know that something waiting on "selwait" is waiting + * for a select to finish + */ + struct wchan_map { + char *map_from; + char *map_to; + } wchan_map_list[] = { + { "proc", "child" }, + { "u", "pause" }, + { "selwait", "select" }, + { "mbutl", "socket" }, + { NULL, NULL }, + }; int npr; *************** *** 289,294 **** --- 309,317 ---- case 'n': nflg++; break; + case 'r': + rflg++; + break; case 's': sflg++; break; *************** *** 338,347 **** --- 361,373 ---- openfiles(argc, argv); getkvars(argc, argv); uid = getuid(); + (void) time(&now); printhdr(); procp = getw(nl[X_PROC].n_value); nproc = getw(nl[X_NPROC].n_value); savcom = (struct savcom *)calloc((unsigned) nproc, sizeof (*savcom)); + klseek(kmem, (long)nl[X_BOOTTIME].n_value, 0); + read(kmem, &boottime, sizeof (boottime)); for (i=0; i<nproc; i += NPROC) { klseek(kmem, (long)procp, 0); j = nproc - i; *************** *** 374,379 **** --- 400,408 ---- mproc->p_stat == SSTOP)) continue; } + if (rflg && !(mproc->p_stat == SRUN + || mproc->p_pri < PZERO)) + continue; save(); } } *************** *** 413,419 **** klseek(kmem, (long)loc, 0); if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word)) ! printf("error reading kmem at %x\n", loc); return (word); } --- 442,448 ---- klseek(kmem, (long)loc, 0); if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word)) ! printf("error reading %s at %x\n", kmemf, loc); return (word); } *************** *** 444,449 **** --- 473,479 ---- setgid(getgid()); setuid(getuid()); if ((fp = fopen(psdb, "w")) == NULL) { + fprintf(stderr, "ps: "); perror(psdb); exit(1); } else *************** *** 482,487 **** --- 512,518 ---- if ((fp = fopen(psdb, "r")) == NULL) { if (errno == ENOENT) return (0); + fprintf(stderr, "ps: "); perror(psdb); exit(1); } *************** *** 539,544 **** --- 570,576 ---- kmemf = argc > 2 ? argv[2] : "/vmcore"; kmem = open(kmemf, 0); if (kmem < 0) { + fprintf(stderr, "ps: "); perror(kmemf); exit(1); } *************** *** 549,554 **** --- 581,587 ---- memf = "/dev/mem"; mem = open(memf, 0); if (mem < 0) { + fprintf(stderr, "ps: "); perror(memf); exit(1); } *************** *** 557,562 **** --- 590,596 ---- swapf = argc>3 ? argv[3]: "/dev/drum"; swap = open(swapf, 0); if (swap < 0) { + fprintf(stderr, "ps: "); perror(swapf); exit(1); } *************** *** 588,594 **** } if (nl[0].n_type == 0) { ! fprintf(stderr, "%s: No namelist\n", nlistf); exit(1); } if (kflg) { --- 622,628 ---- } if (nl[0].n_type == 0) { ! fprintf(stderr, "ps: %s: No namelist\n", nlistf); exit(1); } if (kflg) { *************** *** 599,605 **** Sysmap = (struct pte *) calloc((unsigned) Syssize, sizeof (struct pte)); if (Sysmap == NULL) { ! fprintf(stderr, "Out of space for Sysmap\n"); exit(1); } addr = (long) nl[X_SYSMAP].n_value; --- 633,639 ---- Sysmap = (struct pte *) calloc((unsigned) Syssize, sizeof (struct pte)); if (Sysmap == NULL) { ! fprintf(stderr, "ps: Out of space for Sysmap\n"); exit(1); } addr = (long) nl[X_SYSMAP].n_value; *************** *** 636,642 **** text = (struct text *) calloc((unsigned) 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); --- 670,676 ---- text = (struct text *) calloc((unsigned) ntext, sizeof (struct text)); if (text == 0) { ! fprintf(stderr, "ps: no room for text table\n"); exit(1); } atext = (struct text *)getw(nl[X_TEXT].n_value); *************** *** 743,754 **** struct lttys *lt; if (chdir("/dev") < 0) { ! perror("/dev"); exit(1); } dialbase = -1; if ((df = opendir(".")) == NULL) { ! fprintf(stderr, "Can't open . in /dev\n"); exit(1); } while ((dbuf = readdir(df)) != NULL) --- 777,789 ---- struct lttys *lt; if (chdir("/dev") < 0) { ! perror("ps: /dev"); exit(1); } dialbase = -1; if ((df = opendir(".")) == NULL) { ! fprintf(stderr, "ps: "); ! perror("Can't open . in /dev"); exit(1); } while ((dbuf = readdir(df)) != NULL) *************** *** 907,914 **** struct stat stb; int x; ! if (u.u_ttyp == 0) return("?"); x = u.u_ttyd & 017; for (dp = &allttys[cand[x]]; dp != &allttys[-1]; dp = &allttys[dp->cand]) { --- 942,951 ---- struct stat stb; int x; ! if (u.u_ttyp == 0) { ! u.u_ttyd = -1; return("?"); + } x = u.u_ttyd & 017; for (dp = &allttys[cand[x]]; dp != &allttys[-1]; dp = &allttys[dp->cand]) { *************** *** 950,964 **** 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 *)calloc(1, sizeof (struct asav)); sp->ap->a_cmdp = cmdp; #define e(a,b) ap->a = mproc->b --- 987,1002 ---- register struct text *xp; char *ttyp, *cmdp; ! if (mproc->p_stat != SZOMB) { ! if (getu() == 0) ! return; ! ttyp = gettty(); ! } else ! ttyp = "?"; /* zombies are not attached to terminals */ if (xflg == 0 && ttyp[0] == '?' || tptr && strncmp(tptr, ttyp, 2)) return; sp = &savcom[npr]; cmdp = getcmd(); sp->ap = ap = (struct asav *)calloc(1, sizeof (struct asav)); sp->ap->a_cmdp = cmdp; #define e(a,b) ap->a = mproc->b *************** *** 982,987 **** --- 1020,1026 ---- ap->a_txtrss = xp->x_rssize; ap->a_xccount = xp->x_ccount; } + ap->a_start = u.u_start; } #undef e ap->a_maxrss = mproc->p_maxrss; *************** *** 1070,1076 **** return (0); (void) lseek(swap, (long)dtob(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); } --- 1109,1115 ---- return (0); (void) lseek(swap, (long)dtob(mproc->p_swaddr), 0); if (read(swap, (char *)&user.user, size) != size) { ! fprintf(stderr, "ps: can't read u for pid %d from %s\n", mproc->p_pid, swapf); return (0); } *************** *** 1081,1087 **** pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; klseek(kmem, (long)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, kmemf); return (0); } --- 1120,1126 ---- pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; klseek(kmem, (long)pteaddr, 0); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { ! printf("ps: can't read indir pte to get u for pid %d from %s\n", mproc->p_pid, kmemf); return (0); } *************** *** 1089,1095 **** (long)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, memf); return (0); } --- 1128,1134 ---- (long)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0); if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { ! printf("ps: can't read page table for u of pid %d from %s\n", mproc->p_pid, memf); return (0); } *************** *** 1103,1109 **** i = ncl * CLSIZE; lseek(mem, (long)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); } --- 1142,1148 ---- i = ncl * CLSIZE; lseek(mem, (long)ctob(arguutl[CLSIZE+i].pg_pfnum), 0); if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) { ! printf("ps: can't read page %d of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf); return(0); } *************** *** 1233,1243 **** } char *uhdr = ! "%s PID %%CPU %%MEM SZ RSS TT STAT TIME"; upr(sp) struct savcom *sp; { register struct asav *ap = sp->ap; int vmsize, rmsize; vmsize = pgtok((ap->a_size + ap->a_tsiz)); --- 1272,1283 ---- } char *uhdr = ! "%s PID %%CPU %%MEM SZ RSS TT STAT START TIME"; upr(sp) struct savcom *sp; { register struct asav *ap = sp->ap; + char *cp; int vmsize, rmsize; vmsize = pgtok((ap->a_size + ap->a_tsiz)); *************** *** 1253,1258 **** --- 1293,1305 ---- putchar(' '); ptty(ap->a_tty); printf(" %4.4s", state(ap)); + if (ap->a_start.tv_sec == 0) + ap->a_start = boottime; + cp = ctime(&ap->a_start.tv_sec); + if ((now - ap->a_start.tv_sec) > 60*60*24) + printf("%.7s", cp+3); + else + printf("%.6s ", cp+10); ptime(ap); } *************** *** 1488,1504 **** newloc = loc & ~0xc0000000; p = btop(newloc); if ((loc & 0xc0000000) == 0) { ! fprintf(stderr, "Vtophys: translating non-kernel address\n"); return((off_t) -1); } if (p >= Syssize) { ! fprintf(stderr, "Vtophys: page out of bound (%d>=%d)\n", p, Syssize); return((off_t) -1); } if (Sysmap[p].pg_v == 0 && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) { ! fprintf(stderr, "Vtophys: page not valid\n"); return((off_t) -1); } loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET)); --- 1535,1551 ---- newloc = loc & ~0xc0000000; p = btop(newloc); if ((loc & 0xc0000000) == 0) { ! fprintf(stderr, "ps: Vtophys: translating non-kernel address\n"); return((off_t) -1); } if (p >= Syssize) { ! fprintf(stderr, "ps: Vtophys: page out of bound (%d>=%d)\n", p, Syssize); return((off_t) -1); } if (Sysmap[p].pg_v == 0 && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) { ! fprintf(stderr, "ps: Vtophys: page not valid\n"); return((off_t) -1); } loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET)); *************** *** 1540,1546 **** struct nlist *list; { register struct nlist *p, *q; - register char *s1, *s2; register n, m; int maxlen, nreq; FILE *f; --- 1587,1592 ---- *************** *** 1605,1612 **** if (!nflg) addchan(&nambuf[1], (caddr_t) q->n_value); for (p = list; p->n_un.n_name && p->n_un.n_name[0]; p++) { - s1 = p->n_un.n_name; - s2 = nambuf; if (strcmp(p->n_un.n_name, nambuf) == 0) { p->n_value = q->n_value; p->n_type = q->n_type; --- 1651,1656 ---- *************** *** 1634,1639 **** --- 1678,1684 ---- static int left = 0; register struct wchan *wp; register char **p; + register struct wchan_map *mp; for (p = wchan_stop_list; *p; p++) { if (**p != *name) /* quick check first */ *************** *** 1640,1645 **** --- 1685,1696 ---- continue; if (strncmp(name, *p, WNAMESIZ) == 0) return; /* if found, don't add */ + } + for (mp = wchan_map_list; mp->map_from; mp++) { + if (*(mp->map_from) != *name) /* quick check first */ + continue; + if (strncmp(name, mp->map_from, WNAMESIZ) == 0) + name = mp->map_to; /* if found, remap */ } if (left == 0) { if (wchanhd) {