security merged with biff
[unix-history] / usr / src / bin / ps / ps.c
CommitLineData
8b6d0a7f 1static char *sccsid = "@(#)ps.c 4.15 (Berkeley) %G%";
aafc2e2f
BJ
2/*
3 * ps; VAX 4BSD version
4 */
5
6#include <stdio.h>
7#include <ctype.h>
8#include <nlist.h>
9#include <pwd.h>
10#include <sys/param.h>
11#include <sys/tty.h>
12#include <sys/dir.h>
13#include <sys/user.h>
14#include <sys/proc.h>
15#include <sys/pte.h>
16#include <sys/vm.h>
17#include <sys/text.h>
18#include <sys/stat.h>
7f0fa372 19#include <math.h>
79de1ed3 20#include <sys/vlimit.h>
aafc2e2f
BJ
21
22struct nlist nl[] = {
23 { "_proc" },
24#define X_PROC 0
25 { "_Usrptmap" },
26#define X_USRPTMA 1
27 { "_usrpt" },
28#define X_USRPT 2
29 { "_text" },
30#define X_TEXT 3
31 { "_nswap" },
32#define X_NSWAP 4
c67277e8
BJ
33 { "_maxslp" },
34#define X_MAXSLP 5
7f0fa372
BJ
35 { "_ccpu" },
36#define X_CCPU 6
0f0e0052
BJ
37 { "_ecmx" },
38#define X_ECMX 7
bdb1f95f
BJ
39 { "_nproc" },
40#define X_NPROC 8
41 { "_ntext" },
42#define X_NTEXT 9
43 { "_hz" },
44#define X_HZ 10
aafc2e2f
BJ
45 { 0 },
46};
47
48struct savcom {
49 union {
50 struct lsav *lp;
51 float u_pctcpu;
52 struct vsav *vp;
53 int s_ssiz;
133a0b3b 54 struct sssav *ssp; /* RAND 2/81 */
aafc2e2f
BJ
55 } sun;
56 struct asav *ap;
bdb1f95f 57} *savcom;
aafc2e2f
BJ
58
59struct asav {
60 char *a_cmdp;
61 int a_flag;
c67277e8 62 short a_stat, a_uid, a_pid, a_nice, a_pri, a_slptime, a_time;
0f0e0052
BJ
63 size_t a_size, a_rss, a_tsiz, a_txtrss;
64 short a_xccount;
aafc2e2f
BJ
65 char a_tty[DIRSIZ+1];
66 dev_t a_ttyd;
c67277e8 67 time_t a_cpu;
79de1ed3 68 size_t a_maxrss;
aafc2e2f
BJ
69};
70
71char *lhdr;
aafc2e2f
BJ
72struct lsav {
73 short l_ppid;
c67277e8 74 char l_cpu;
aafc2e2f
BJ
75 int l_addr;
76 caddr_t l_wchan;
77};
78
133a0b3b
MH
79char *sshdr; /* RAND 2/81 */
80struct sssav { /* RAND 2/81 */
81 short ss_ppid; /* RAND 2/81 */
82 short ss_brother; /* RAND 2/81 */
83 short ss_sons; /* RAND 2/81 */
84}; /* RAND 2/81 */
85
aafc2e2f 86char *uhdr;
aafc2e2f 87char *shdr;
aafc2e2f
BJ
88
89char *vhdr;
aafc2e2f 90struct vsav {
0f0e0052
BJ
91 u_int v_majflt;
92 size_t v_swrss, v_txtswrss;
93 float v_pctcpu;
aafc2e2f
BJ
94};
95
96struct proc proc[8]; /* 8 = a few, for less syscalls */
97struct proc *mproc;
98struct text *text;
99
f700a7ee 100int paduser1; /* avoid hardware mem clobbering botch */
aafc2e2f
BJ
101union {
102 struct user user;
103 char upages[UPAGES][NBPG];
104} user;
105#define u user.user
f700a7ee 106int paduser2; /* avoid hardware mem clobbering botch */
aafc2e2f
BJ
107
108#define clear(x) ((int)x & 0x7fffffff)
109
110int chkpid;
133a0b3b
MH
111int aflg, cflg, eflg, gflg, kflg, lflg, sflg, ssflg, /* RAND 2/81 */
112 nonssflg, uflg, vflg, xflg;
aafc2e2f 113char *tptr;
c67277e8 114char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state();
133a0b3b 115char *rindex(); /* RAND 2/81 */
0f0e0052 116double pcpu(), pmem();
aafc2e2f 117int pscomp();
c67277e8 118int nswap, maxslp;
bdb1f95f 119struct text *atext;
7f0fa372 120double ccpu;
0f0e0052 121int ecmx;
aafc2e2f 122struct pte *Usrptma, *usrpt;
bdb1f95f 123int nproc, ntext, hz;
aafc2e2f
BJ
124
125struct ttys {
126 char name[DIRSIZ+1];
127 dev_t ttyd;
128 struct ttys *next;
129 struct ttys *cand;
130} *allttys, *cand[16];
131
aafc2e2f
BJ
132int npr;
133
134int cmdstart;
135int twidth;
136char *kmemf, *memf, *swapf, *nlistf;
137int kmem, mem, swap;
1fb6a666 138int rawcpu, sumcpu;
aafc2e2f
BJ
139
140int pcbpf;
141int argaddr;
142extern char _sobuf[];
143
144main(argc, argv)
145 char **argv;
146{
147 register int i, j;
148 register char *ap;
149 int uid;
150 off_t procp;
151
152 if (chdir("/dev") < 0) {
153 perror("/dev");
154 exit(1);
155 }
156 twidth = 80;
133a0b3b
MH
157
158 if (ap = rindex(argv[0], '/')) /* RAND 2/81 */
159 ap++;
160 else
161 ap = argv[0];
162 if (*ap == 's') /* If name starts with 's' */
163 ssflg++;
164
aafc2e2f
BJ
165 setbuf(stdout, _sobuf);
166 argc--, argv++;
167 if (argc > 0) {
168 ap = argv[0];
169 while (*ap) switch (*ap++) {
170
0f0e0052 171 case 'C':
133a0b3b 172 rawcpu++; nonssflg++;
0f0e0052 173 break;
1fb6a666
BJ
174 case 'S':
175 sumcpu++;
176 break;
aafc2e2f
BJ
177 case 'a':
178 aflg++;
179 break;
180 case 'c':
133a0b3b 181 cflg = !cflg; nonssflg++;
aafc2e2f
BJ
182 break;
183 case 'e':
133a0b3b 184 eflg++; nonssflg++;
aafc2e2f
BJ
185 break;
186 case 'g':
133a0b3b 187 gflg++; nonssflg++;
aafc2e2f
BJ
188 break;
189 case 'k':
133a0b3b 190 kflg++; nonssflg++;
aafc2e2f
BJ
191 break;
192 case 'l':
133a0b3b 193 lflg++; nonssflg++;
aafc2e2f
BJ
194 break;
195 case 's':
133a0b3b 196 sflg++; nonssflg++;
aafc2e2f
BJ
197 break;
198 case 't':
199 if (*ap)
200 tptr = ap;
133a0b3b 201 aflg++; nonssflg++;
aafc2e2f
BJ
202 gflg++;
203 if (*tptr == '?')
204 xflg++;
205 while (*ap)
206 ap++;
207 break;
133a0b3b
MH
208 case 'u':
209 uflg++; nonssflg++;
aafc2e2f
BJ
210 break;
211 case 'v':
212 cflg = 1;
133a0b3b 213 vflg++; nonssflg++;
aafc2e2f
BJ
214 break;
215 case 'w':
216 if (twidth == 80)
217 twidth = 132;
218 else
219 twidth = BUFSIZ;
220 break;
221 case 'x':
222 xflg++;
223 break;
133a0b3b
MH
224 case 'y': /* Rand 2/81 */
225 ssflg++;
226 break;
aafc2e2f
BJ
227 default:
228 if (!isdigit(ap[-1]))
229 break;
230 chkpid = atoi(--ap);
231 *ap = 0;
133a0b3b 232 aflg++; nonssflg++;
aafc2e2f
BJ
233 xflg++;
234 break;
235 }
236 }
133a0b3b
MH
237 if (ssflg) { /* RAND 2/81 */
238 if (nonssflg) {
239 fprintf (stderr, "Usage: ss [axwS]\n");
240 exit(1);
241 }
242 uflg++;
243 gflg++;
244 }
245
aafc2e2f
BJ
246 openfiles(argc, argv);
247 getkvars(argc, argv);
248 getdev();
249 uid = getuid();
250 printhdr();
bdb1f95f
BJ
251 procp = getw(nl[X_PROC].n_value);
252 nproc = getw(nl[X_NPROC].n_value);
253 hz = getw(nl[X_HZ].n_value);
254 savcom = (struct savcom *)calloc(nproc, sizeof (*savcom));
255 for (i=0; i<nproc; i += 8) {
aafc2e2f 256 lseek(kmem, (char *)procp, 0);
bdb1f95f 257 j = nproc - i;
aafc2e2f
BJ
258 if (j > 8)
259 j = 8;
260 j *= sizeof (struct proc);
261 if (read(kmem, (char *)proc, j) != j)
262 cantread("proc table", kmemf);
263 procp += j;
264 for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
265 mproc = &proc[j];
266 if (mproc->p_stat == 0 ||
267 mproc->p_pgrp == 0 && xflg == 0)
c67277e8 268 continue;
aafc2e2f
BJ
269 if (tptr == 0 && gflg == 0 && xflg == 0 &&
270 mproc->p_ppid == 1 && (mproc->p_flag&SDETACH) == 0)
271 continue;
272 if (uid != mproc->p_uid && aflg==0 ||
273 chkpid != 0 && chkpid != mproc->p_pid)
274 continue;
275 if (vflg && gflg == 0 && xflg == 0) {
276 if (mproc->p_stat == SZOMB ||
277 mproc->p_flag&SWEXIT)
278 continue;
279 if (mproc->p_slptime > MAXSLP &&
280 (mproc->p_stat == SSLEEP ||
281 mproc->p_stat == SSTOP))
282 continue;
283 }
284 save();
285 }
286 }
287 qsort(savcom, npr, sizeof(savcom[0]), pscomp);
133a0b3b
MH
288 if (ssflg) { /* RAND 2/81 */
289 walk(npr);
290 exit (npr == 0);
291 }
aafc2e2f
BJ
292 for (i=0; i<npr; i++) {
293 register struct savcom *sp = &savcom[i];
294 if (lflg)
295 lpr(sp);
296 else if (vflg)
297 vpr(sp);
298 else if (uflg)
299 upr(sp);
300 else
301 spr(sp);
302 if (sp->ap->a_flag & SWEXIT)
303 printf(" <exiting>");
304 else if (sp->ap->a_stat == SZOMB)
305 printf(" <defunct>");
306 else if (sp->ap->a_pid == 0)
307 printf(" swapper");
308 else if (sp->ap->a_pid == 2)
309 printf(" pagedaemon");
d4e18729 310 else if (sp->ap->a_pid == 3 && sp->ap->a_flag & SSYS)
3bbec3da 311 printf(" ip input");
aafc2e2f
BJ
312 else
313 printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp);
314 printf("\n");
315 }
316 exit(npr == 0);
317}
318
bdb1f95f
BJ
319getw(loc)
320 off_t loc;
321{
322 long word;
323
324 lseek(kmem, loc, 0);
325 if (read(kmem, &word, sizeof (word)) != sizeof (word))
326 printf("error reading kmem at %x\n", loc);
327 return (word);
328}
329
aafc2e2f
BJ
330openfiles(argc, argv)
331 char **argv;
332{
333
334 kmemf = "kmem";
335 if (kflg)
336 kmemf = argc > 1 ? argv[1] : "/vmcore";
337 kmem = open(kmemf, 0);
338 if (kmem < 0) {
339 perror(kmemf);
340 exit(1);
341 }
342 if (kflg) {
343 mem = kmem;
344 memf = kmemf;
345 } else {
346 memf = "mem";
347 mem = open(memf, 0);
348 if (mem < 0) {
349 perror(memf);
350 exit(1);
351 }
352 }
353 swapf = argc>2 ? argv[2]: "drum";
354 swap = open(swapf, 0);
355 if (swap < 0) {
356 perror(swapf);
357 exit(1);
358 }
359}
360
361getkvars(argc, argv)
362 char **argv;
363{
364 register struct nlist *nlp;
365
366 nlistf = argc > 3 ? argv[3] : "/vmunix";
367 nlist(nlistf, nl);
368 if (nl[0].n_type == 0) {
369 fprintf(stderr, "%s: No namelist\n", nlistf);
370 exit(1);
371 }
372 if (kflg)
373 for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++)
374 nlp->n_value = clear(nlp->n_value);
375 Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
376 usrpt = (struct pte *)nl[X_USRPT].n_value;
377 lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
378 if (read(kmem, &nswap, sizeof (nswap)) != sizeof (nswap)) {
379 cantread("nswap", kmemf);
380 exit(1);
381 }
c67277e8
BJ
382 lseek(kmem, (long)nl[X_MAXSLP].n_value, 0);
383 if (read(kmem, &maxslp, sizeof (maxslp)) != sizeof (maxslp)) {
384 cantread("maxslp", kmemf);
385 exit(1);
386 }
7f0fa372
BJ
387 lseek(kmem, (long)nl[X_CCPU].n_value, 0);
388 if (read(kmem, &ccpu, sizeof (ccpu)) != sizeof (ccpu)) {
389 cantread("ccpu", kmemf);
390 exit(1);
391 }
0f0e0052
BJ
392 lseek(kmem, (long)nl[X_ECMX].n_value, 0);
393 if (read(kmem, &ecmx, sizeof (ecmx)) != sizeof (ecmx)) {
394 cantread("ecmx", kmemf);
395 exit(1);
396 }
397 if (uflg || vflg) {
bdb1f95f
BJ
398 ntext = getw(nl[X_NTEXT].n_value);
399 text = (struct text *)alloc(ntext * sizeof (struct text));
aafc2e2f
BJ
400 if (text == 0) {
401 fprintf(stderr, "no room for text table\n");
402 exit(1);
403 }
bdb1f95f
BJ
404 atext = (struct text *)getw(nl[X_TEXT].n_value);
405 lseek(kmem, (int)atext, 0);
406 if (read(kmem, (char *)text, ntext * sizeof (struct text))
407 != ntext * sizeof (struct text)) {
aafc2e2f
BJ
408 cantread("text table", kmemf);
409 exit(1);
410 }
411 }
412}
413
414printhdr()
415{
416 char *hdr;
417
418 if (sflg+lflg+vflg+uflg > 1) {
419 fprintf(stderr, "ps: specify only one of s,l,v and u\n");
420 exit(1);
421 }
133a0b3b
MH
422 hdr = ssflg ? sshdr : /* RAND 2/81 */
423 (lflg ? lhdr :
424 (vflg ? vhdr :
425 (uflg ? uhdr : shdr)));
aafc2e2f 426 if (lflg+vflg+uflg+sflg == 0)
c67277e8 427 hdr += strlen("SSIZ ");
aafc2e2f
BJ
428 cmdstart = strlen(hdr);
429 printf("%s COMMAND\n", hdr);
430 fflush(stdout);
431}
432
433cantread(what, fromwhat)
434 char *what, *fromwhat;
435{
436
437 fprintf(stderr, "ps: error reading %s from %s", what, fromwhat);
438}
439
440struct direct dbuf;
441int dialbase;
442
443getdev()
444{
445 register FILE *df;
446 register struct ttys *dp;
447
448 dialbase = -1;
449 if ((df = fopen(".", "r")) == NULL) {
450 fprintf(stderr, "Can't open . in /dev\n");
451 exit(1);
452 }
453 while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) {
454 if (dbuf.d_ino == 0)
455 continue;
456 maybetty(dp);
457 }
458 fclose(df);
459}
460
461/*
462 * Attempt to avoid stats by guessing minor device
463 * numbers from tty names. Console is known,
464 * know that r(hp|up|mt) are unlikely as are different mem's,
465 * floppy, null, tty, etc.
466 */
467maybetty()
468{
469 register char *cp = dbuf.d_name;
470 register struct ttys *dp;
471 int x;
472 struct stat stb;
473
474 switch (cp[0]) {
475
476 case 'c':
477 if (!strcmp(cp, "console")) {
478 x = 0;
479 goto donecand;
480 }
481 /* cu[la]? are possible!?! don't rule them out */
482 break;
483
484 case 'd':
485 if (!strcmp(cp, "drum"))
486 return (0);
487 break;
488
489 case 'f':
490 if (!strcmp(cp, "floppy"))
491 return (0);
492 break;
493
494 case 'k':
495 cp++;
496 if (*cp == 'U')
497 cp++;
498 goto trymem;
499
500 case 'r':
501 cp++;
502 if (*cp == 'r' || *cp == 'u' || *cp == 'h')
503 cp++;
504#define is(a,b) cp[0] == 'a' && cp[1] == 'b'
505 if (is(r,p) || is(u,p) || is(r,k) || is(r,m) || is(m,t)) {
506 cp += 2;
507 if (isdigit(*cp) && cp[2] == 0)
508 return (0);
509 }
510 break;
511
512 case 'm':
513trymem:
514 if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0)
515 return (0);
3bbec3da
BJ
516 if (cp[0] == 'm' && cp[1] == 't')
517 return (0);
aafc2e2f
BJ
518 break;
519
520 case 'n':
521 if (!strcmp(cp, "null"))
522 return (0);
523 break;
524
525 case 'v':
526 if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) &&
527 cp[3] == 0)
528 return (0);
529 break;
530 }
531mightbe:
532 cp = dbuf.d_name;
533 while (cp < &dbuf.d_name[DIRSIZ] && *cp)
534 cp++;
535 --cp;
536 x = 0;
537 if (cp[-1] == 'd') {
538 if (dialbase == -1) {
539 if (stat("ttyd0", &stb) == 0)
540 dialbase = stb.st_rdev & 017;
541 else
542 dialbase = -2;
543 }
544 if (dialbase == -2)
545 x = 0;
546 else
547 x = 11;
548 }
549 if (cp > dbuf.d_name && isdigit(cp[-1]) && isdigit(*cp))
550 x += 10 * (cp[-1] - ' ') + cp[0] - '0';
551 else if (*cp >= 'a' && *cp <= 'f')
552 x += 10 + *cp - 'a';
553 else if (isdigit(*cp))
554 x += *cp - '0';
555 else
556 x = -1;
557donecand:
558 dp = (struct ttys *)alloc(sizeof (struct ttys));
559 strncpy(dp->name, dbuf.d_name, DIRSIZ);
560 dp->next = allttys;
561 dp->ttyd = -1;
562 allttys = dp;
563 if (x == -1)
564 return;
565 x &= 017;
566 dp->cand = cand[x];
567 cand[x] = dp;
568}
569
570char *
571gettty()
572{
573 register char *p;
574 register struct ttys *dp;
575 struct stat stb;
576 int x;
577
578 if (u.u_ttyp == 0)
579 return("?");
580 x = u.u_ttyd & 017;
581 for (dp = cand[x]; dp; dp = dp->cand) {
582 if (dp->ttyd == -1) {
c67277e8
BJ
583 if (stat(dp->name, &stb) == 0 &&
584 (stb.st_mode&S_IFMT)==S_IFCHR)
aafc2e2f
BJ
585 dp->ttyd = stb.st_rdev;
586 else
587 dp->ttyd = -2;
588 }
589 if (dp->ttyd == u.u_ttyd)
590 goto found;
591 }
592 /* ick */
593 for (dp = allttys; dp; dp = dp->next) {
594 if (dp->ttyd == -1) {
3bbec3da
BJ
595 if (stat(dp->name, &stb) == 0 &&
596 (stb.st_mode&S_IFMT)==S_IFCHR)
aafc2e2f
BJ
597 dp->ttyd = stb.st_rdev;
598 else
599 dp->ttyd = -2;
600 }
601 if (dp->ttyd == u.u_ttyd)
602 goto found;
603 }
604 return ("?");
605found:
606 p = dp->name;
607 if (p[0]=='t' && p[1]=='t' && p[2]=='y')
608 p += 3;
609 return (p);
610}
611
612save()
613{
614 register struct savcom *sp;
615 register struct asav *ap;
616 register char *cp;
0f0e0052 617 register struct text *xp;
aafc2e2f
BJ
618 char *ttyp, *cmdp;
619
620 if (mproc->p_stat != SZOMB && getu() == 0)
621 return;
622 ttyp = gettty();
133a0b3b 623 if (xflg == 0 && ttyp[0] == '?' || tptr && strncmp(tptr, ttyp, 2))
aafc2e2f
BJ
624 return;
625 sp = &savcom[npr];
626 cmdp = getcmd();
627 if (cmdp == 0)
628 return;
629 sp->ap = ap = (struct asav *)alloc(sizeof (struct asav));
630 sp->ap->a_cmdp = cmdp;
631#define e(a,b) ap->a = mproc->b
632 e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice);
0f0e0052 633 e(a_uid, p_uid); e(a_pid, p_pid); e(a_pri, p_pri);
c67277e8 634 e(a_slptime, p_slptime); e(a_time, p_time);
aafc2e2f
BJ
635 ap->a_tty[0] = ttyp[0];
636 ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' ';
637 if (ap->a_stat == SZOMB) {
638 register struct xproc *xp = (struct xproc *)mproc;
639
c67277e8 640 ap->a_cpu = xp->xp_vm.vm_utime + xp->xp_vm.vm_stime;
aafc2e2f
BJ
641 } else {
642 ap->a_size = mproc->p_dsize + mproc->p_ssize;
0f0e0052 643 e(a_rss, p_rssize);
aafc2e2f 644 ap->a_ttyd = u.u_ttyd;
c67277e8 645 ap->a_cpu = u.u_vm.vm_utime + u.u_vm.vm_stime;
1fb6a666
BJ
646 if (sumcpu)
647 ap->a_cpu += u.u_cvm.vm_utime + u.u_cvm.vm_stime;
b2867a35 648 if (mproc->p_textp && text) {
bdb1f95f 649 xp = &text[mproc->p_textp - atext];
0f0e0052
BJ
650 ap->a_tsiz = xp->x_size;
651 ap->a_txtrss = xp->x_rssize;
652 ap->a_xccount = xp->x_ccount;
653 }
aafc2e2f 654 }
0f0e0052 655#undef e
bdb1f95f 656 ap->a_cpu /= hz;
79de1ed3 657 ap->a_maxrss = mproc->p_maxrss;
aafc2e2f
BJ
658 if (lflg) {
659 register struct lsav *lp;
660
661 sp->sun.lp = lp = (struct lsav *)alloc(sizeof (struct lsav));
662#define e(a,b) lp->a = mproc->b
c67277e8 663 e(l_ppid, p_ppid); e(l_cpu, p_cpu);
aafc2e2f
BJ
664 if (ap->a_stat != SZOMB)
665 e(l_wchan, p_wchan);
666#undef e
667 lp->l_addr = pcbpf;
668 } else if (vflg) {
669 register struct vsav *vp;
aafc2e2f
BJ
670
671 sp->sun.vp = vp = (struct vsav *)alloc(sizeof (struct vsav));
672#define e(a,b) vp->a = mproc->b
aafc2e2f 673 if (ap->a_stat != SZOMB) {
7f0fa372 674 e(v_swrss, p_swrss);
aafc2e2f 675 vp->v_majflt = u.u_vm.vm_majflt;
0f0e0052 676 if (mproc->p_textp)
aafc2e2f 677 vp->v_txtswrss = xp->x_swrss;
aafc2e2f 678 }
7f0fa372 679 vp->v_pctcpu = pcpu();
aafc2e2f 680#undef e
133a0b3b
MH
681 } else if (uflg) {
682 if (!ssflg) /* RAND 2/18 */
683 sp->sun.u_pctcpu = pcpu();
684 else {
685 register struct sssav *ssp;
686
687 sp->sun.ssp =ssp= (struct sssav *)alloc(sizeof (struct sssav));
688 ssp->ss_ppid = mproc->p_ppid;
689 }
690 } else if (sflg) {
aafc2e2f
BJ
691 if (ap->a_stat != SZOMB) {
692 for (cp = (char *)u.u_stack;
bdb1f95f 693 cp < &user.upages[UPAGES][0]; )
aafc2e2f
BJ
694 if (*cp++)
695 break;
bdb1f95f 696 sp->sun.s_ssiz = (&user.upages[UPAGES][0] - cp);
aafc2e2f
BJ
697 }
698 }
133a0b3b 699
aafc2e2f
BJ
700 npr++;
701}
702
0f0e0052
BJ
703double
704pmem(ap)
705 register struct asav *ap;
706{
707 double fracmem;
708 int szptudot;
709
710 if ((ap->a_flag&SLOAD) == 0)
711 fracmem = 0.0;
712 else {
713 szptudot = UPAGES + clrnd(ctopt(ap->a_size+ap->a_tsiz));
714 fracmem = ((float)ap->a_rss+szptudot)/CLSIZE/ecmx;
715 if (ap->a_xccount)
716 fracmem += ((float)ap->a_txtrss)/CLSIZE/
717 ap->a_xccount/ecmx;
718 }
719 return (100.0 * fracmem);
720}
721
7f0fa372
BJ
722double
723pcpu()
724{
0f0e0052 725 time_t time;
7f0fa372 726
0f0e0052
BJ
727 time = mproc->p_time;
728 if (time == 0 || (mproc->p_flag&SLOAD) == 0)
7f0fa372 729 return (0.0);
0f0e0052
BJ
730 if (rawcpu)
731 return (100.0 * mproc->p_pctcpu);
732 return (100.0 * mproc->p_pctcpu / (1.0 - exp(time * log(ccpu))));
7f0fa372
BJ
733}
734
aafc2e2f
BJ
735getu()
736{
f700a7ee
BJ
737 struct pte *pteaddr, apte;
738 int pad1; /* avoid hardware botch */
739 struct pte arguutl[UPAGES+CLSIZE];
740 int pad2; /* avoid hardware botch */
aafc2e2f
BJ
741 register int i;
742 int ncl, size;
743
744 size = sflg ? ctob(UPAGES) : sizeof (struct user);
745 if ((mproc->p_flag & SLOAD) == 0) {
746 lseek(swap, ctob(mproc->p_swaddr), 0);
747 if (read(swap, (char *)&user.user, size) != size) {
748 fprintf(stderr, "ps: cant read u for pid %d from %s\n",
749 mproc->p_pid, swapf);
750 return (0);
751 }
752 pcbpf = 0;
753 argaddr = 0;
754 return (1);
755 }
756 pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
757 lseek(kmem, kflg ? clear(pteaddr) : (int)pteaddr, 0);
758 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
759 printf("ps: cant read indir pte to get u for pid %d from %s\n",
760 mproc->p_pid, swapf);
761 return (0);
762 }
763 lseek(mem,
764 ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0);
765 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
766 printf("ps: cant read page table for u of pid %d from %s\n",
767 mproc->p_pid, swapf);
768 return (0);
769 }
770 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
771 argaddr = ctob(arguutl[0].pg_pfnum);
772 else
773 argaddr = 0;
774 pcbpf = arguutl[CLSIZE].pg_pfnum;
775 ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
776 while (--ncl >= 0) {
777 i = ncl * CLSIZE;
778 lseek(mem, ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
779 if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
780 printf("ps: cant read page %d of u of pid %d from %s\n",
781 arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
782 return(0);
783 }
784 }
785 return (1);
786}
787
788char *
789getcmd()
790{
791 char cmdbuf[BUFSIZ];
f700a7ee 792 int pad1; /* avoid hardware botch */
aafc2e2f
BJ
793 union {
794 char argc[CLSIZE*NBPG];
795 int argi[CLSIZE*NBPG/sizeof (int)];
796 } argspac;
f700a7ee 797 int pad2; /* avoid hardware botch */
aafc2e2f
BJ
798 register char *cp;
799 register int *ip;
800 char c;
801 int nbad;
802 struct dblock db;
803
804 if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT))
805 return ("");
806 if (cflg) {
807 strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm));
808 return (savestr(cmdbuf));
809 }
810 if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) {
811 vstodb(0, CLSIZE, &u.u_smap, &db, 1);
812 lseek(swap, ctob(db.db_base), 0);
813 if (read(swap, (char *)&argspac, sizeof(argspac))
814 != sizeof(argspac))
815 goto bad;
816 } else {
817 lseek(mem, argaddr, 0);
818 if (read(mem, (char *)&argspac, sizeof (argspac))
819 != sizeof (argspac))
820 goto bad;
821 }
822 ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)];
823 ip -= 2; /* last arg word and .long 0 */
824 while (*--ip)
825 if (ip == argspac.argi)
826 goto retucomm;
827 *(char *)ip = ' ';
828 ip++;
829 nbad = 0;
830 for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) {
831 c = *cp & 0177;
832 if (c == 0)
833 *cp = ' ';
834 else if (c < ' ' || c > 0176) {
835 if (++nbad >= 5*(eflg+1)) {
836 *cp++ = ' ';
837 break;
838 }
839 *cp = '?';
840 } else if (eflg == 0 && c == '=') {
841 while (*--cp != ' ')
842 if (cp <= (char *)ip)
843 break;
844 break;
845 }
846 }
847 *cp = 0;
848 while (*--cp == ' ')
849 *cp = 0;
850 cp = (char *)ip;
851 strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp);
852 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
853 strcat(cmdbuf, " (");
854 strncat(cmdbuf, u.u_comm, sizeof(u.u_comm));
855 strcat(cmdbuf, ")");
856 }
c67277e8 857/*
aafc2e2f
BJ
858 if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-')
859 return (0);
c67277e8 860*/
aafc2e2f
BJ
861 return (savestr(cmdbuf));
862
863bad:
864 fprintf(stderr, "ps: error locating command name for pid %d\n",
865 mproc->p_pid);
866retucomm:
867 strcpy(cmdbuf, " (");
868 strncat(cmdbuf, u.u_comm, sizeof (u.u_comm));
869 strcat(cmdbuf, ")");
870 return (savestr(cmdbuf));
871}
872
873char *lhdr =
0f0e0052 874" F UID PID PPID CP PRI NI ADDR SZ RSS WCHAN STAT TT TIME";
aafc2e2f
BJ
875lpr(sp)
876 struct savcom *sp;
877{
878 register struct asav *ap = sp->ap;
879 register struct lsav *lp = sp->sun.lp;
880
c67277e8
BJ
881 printf("%6x%4d%6u%6u%3d%4d%3d%5x%4d%5d",
882 ap->a_flag, ap->a_uid,
883 ap->a_pid, lp->l_ppid, lp->l_cpu&0377, ap->a_pri-PZERO,
884 ap->a_nice-NZERO, lp->l_addr, ap->a_size/2, ap->a_rss/2);
aafc2e2f 885 printf(lp->l_wchan ? " %5x" : " ", (int)lp->l_wchan&0xfffff);
0f0e0052 886 printf(" %4.4s ", state(ap));
aafc2e2f
BJ
887 ptty(ap->a_tty);
888 ptime(ap);
889}
890
891ptty(tp)
892 char *tp;
893{
894
c67277e8 895 printf("%-2.2s", tp);
aafc2e2f
BJ
896}
897
898ptime(ap)
899 struct asav *ap;
900{
901
bdb1f95f 902 printf("%3ld:%02ld", ap->a_cpu / hz, ap->a_cpu % hz);
aafc2e2f
BJ
903}
904
905char *uhdr =
0f0e0052 906"USER PID %CPU %MEM SZ RSS TT STAT TIME";
aafc2e2f
BJ
907upr(sp)
908 struct savcom *sp;
909{
910 register struct asav *ap = sp->ap;
0f0e0052
BJ
911 int vmsize, rmsize;
912
913 vmsize = (ap->a_size + ap->a_tsiz)/2;
914 rmsize = ap->a_rss/2;
915 if (ap->a_xccount)
916 rmsize += ap->a_txtrss/ap->a_xccount/2;
917 printf("%-8.8s %5d%5.1f%5.1f%5d%5d",
918 getname(ap->a_uid), ap->a_pid, sp->sun.u_pctcpu, pmem(ap),
919 vmsize, rmsize);
c67277e8 920 putchar(' ');
aafc2e2f 921 ptty(ap->a_tty);
0f0e0052 922 printf(" %4.4s", state(ap));
aafc2e2f
BJ
923 ptime(ap);
924}
925
926char *vhdr =
79de1ed3 927" PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM TSIZ TRS %CPU %MEM";
aafc2e2f
BJ
928vpr(sp)
929 struct savcom *sp;
930{
931 register struct vsav *vp = sp->sun.vp;
932 register struct asav *ap = sp->ap;
c67277e8 933
0f0e0052 934 printf("%5u ", ap->a_pid);
c67277e8 935 ptty(ap->a_tty);
0f0e0052 936 printf(" %4.4s", state(ap));
c67277e8 937 ptime(ap);
79de1ed3
BJ
938 printf("%3d%3d%7d%5d%5d",
939 ap->a_slptime > 99 ? 99 : ap-> a_slptime,
940 ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt,
941 ap->a_size/2, ap->a_rss/2);
942 if (ap->a_maxrss == (INFINITY/NBPG))
8fb17030 943 printf(" xx");
79de1ed3
BJ
944 else
945 printf("%5d", ap->a_maxrss/2);
946 printf("%5d%4d%5.1f%5.1f",
0f0e0052 947 ap->a_tsiz/2, ap->a_txtrss/2, vp->v_pctcpu, pmem(ap));
c67277e8
BJ
948}
949
950char *shdr =
0f0e0052 951"SSIZ PID TT STAT TIME";
c67277e8
BJ
952spr(sp)
953 struct savcom *sp;
954{
955 register struct asav *ap = sp->ap;
956
957 if (sflg)
958 printf("%4d ", sp->sun.s_ssiz);
959 printf("%5u", ap->a_pid);
960 putchar(' ');
961 ptty(ap->a_tty);
0f0e0052 962 printf(" %4.4s", state(ap));
c67277e8
BJ
963 ptime(ap);
964}
965
966char *
967state(ap)
968 register struct asav *ap;
969{
970 char stat, load, nice, anom;
971 static char res[5];
aafc2e2f
BJ
972
973 switch (ap->a_stat) {
974
aafc2e2f 975 case SSTOP:
c67277e8
BJ
976 stat = 'T';
977 break;
978
979 case SSLEEP:
980 if (ap->a_pri >= PZERO)
981 if (ap->a_slptime >= MAXSLP)
982 stat = 'I';
983 else
984 stat = 'S';
aafc2e2f
BJ
985 else if (ap->a_flag & SPAGE)
986 stat = 'P';
987 else
988 stat = 'D';
989 break;
990
c67277e8 991 case SWAIT:
aafc2e2f
BJ
992 case SRUN:
993 case SIDL:
c67277e8
BJ
994 stat = 'R';
995 break;
996
997 case SZOMB:
998 stat = 'Z';
aafc2e2f 999 break;
c67277e8
BJ
1000
1001 default:
1002 stat = '?';
aafc2e2f 1003 }
79de1ed3 1004 load = ap->a_flag & SLOAD ? (ap->a_rss>ap->a_maxrss ? '>' : ' ') : 'W';
0f0e0052
BJ
1005 if (ap->a_nice < NZERO)
1006 nice = '<';
1007 else if (ap->a_nice > NZERO)
1008 nice = 'N';
1009 else
1010 nice = ' ';
8fb17030 1011 anom = (ap->a_flag&SUANOM) ? 'A' : ((ap->a_flag&SSEQL) ? 'S' : ' ');
c67277e8
BJ
1012 res[0] = stat; res[1] = load; res[2] = nice; res[3] = anom;
1013 return (res);
aafc2e2f
BJ
1014}
1015
1016/*
1017 * Given a base/size pair in virtual swap area,
1018 * return a physical base/size pair which is the
1019 * (largest) initial, physically contiguous block.
1020 */
1021vstodb(vsbase, vssize, dmp, dbp, rev)
1022 register int vsbase;
1023 int vssize;
1024 struct dmap *dmp;
1025 register struct dblock *dbp;
1026{
1027 register int blk = DMMIN;
1028 register swblk_t *ip = dmp->dm_map;
1029
1030 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
1031 panic("vstodb");
1032 while (vsbase >= blk) {
1033 vsbase -= blk;
1034 if (blk < DMMAX)
1035 blk *= 2;
1036 ip++;
1037 }
1038 if (*ip <= 0 || *ip + blk > nswap)
1039 panic("vstodb *ip");
1040 dbp->db_size = min(vssize, blk - vsbase);
1041 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
1042}
1043
1044/*ARGSUSED*/
1045panic(cp)
1046 char *cp;
1047{
1048
1049#ifdef DEBUG
1050 printf("%s\n", cp);
1051#endif
1052}
1053
1054min(a, b)
1055{
1056
1057 return (a < b ? a : b);
1058}
1059
1060pscomp(s1, s2)
1061 struct savcom *s1, *s2;
1062{
1063 register int i;
1064
133a0b3b 1065 if (uflg && !ssflg)
7f0fa372 1066 return (s2->sun.u_pctcpu > s1->sun.u_pctcpu ? 1 : -1);
aafc2e2f
BJ
1067 if (vflg)
1068 return (vsize(s2) - vsize(s1));
1069 i = s1->ap->a_ttyd - s2->ap->a_ttyd;
1070 if (i == 0)
1071 i = s1->ap->a_pid - s2->ap->a_pid;
1072 return (i);
1073}
1074
1075vsize(sp)
1076 struct savcom *sp;
1077{
1078 register struct asav *ap = sp->ap;
1079 register struct vsav *vp = sp->sun.vp;
1080
1081 if (ap->a_flag & SLOAD)
1082 return (ap->a_rss +
0f0e0052
BJ
1083 ap->a_txtrss / (ap->a_xccount ? ap->a_xccount : 1));
1084 return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss));
aafc2e2f
BJ
1085}
1086
1087#define NMAX 8
1088#define NUID 2048
1089
1090char names[NUID][NMAX+1];
1091
1092/*
1093 * Stolen from ls...
1094 */
1095char *
1096getname(uid)
1097{
1098 register struct passwd *pw;
1099 static init;
1100 struct passwd *getpwent();
1101
0f0e0052 1102 if (uid >= 0 && uid < NUID && names[uid][0])
aafc2e2f
BJ
1103 return (&names[uid][0]);
1104 if (init == 2)
1105 return (0);
1106 if (init == 0)
1107 setpwent(), init = 1;
1108 while (pw = getpwent()) {
1109 if (pw->pw_uid >= NUID)
1110 continue;
1111 if (names[pw->pw_uid][0])
1112 continue;
1113 strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
1114 if (pw->pw_uid == uid)
1115 return (&names[uid][0]);
1116 }
1117 init = 2;
1118 endpwent();
1119 return (0);
1120}
1121
1122char *freebase;
1123int nleft;
1124
1125char *
1126alloc(size)
1127 int size;
1128{
1129 register char *cp;
1130 register int i;
1131
1132 if (size > nleft) {
1133 freebase = (char *)sbrk(i = size > 2048 ? size : 2048);
1134 if (freebase == 0) {
1135 fprintf(stderr, "ps: ran out of memory\n");
1136 exit(1);
1137 }
1138 nleft = i - size;
1139 } else
1140 nleft -= size;
1141 cp = freebase;
1142 for (i = size; --i >= 0; )
1143 *cp++ = 0;
1144 freebase = cp;
1145 return (cp - size);
1146}
1147
1148char *
1149savestr(cp)
1150 char *cp;
1151{
1152 register int len;
1153 register char *dp;
1154
1155 len = strlen(cp);
1156 dp = (char *)alloc(len+1);
1157 strcpy(dp, cp);
1158 return (dp);
1159}
133a0b3b
MH
1160
1161walk(np)
1162 int np;
1163{
1164 register int i, j, k, l, m;
1165#undef afl
1166#undef sfl
1167#define afl(i,f) savcom[i].ap -> f
1168#define sfl(i,f) savcom[i].sun.ssp -> f
1169
1170 for(i = 0; i < np; i = j) {
1171 for(j = i; afl(j,a_ttyd) == afl(i,a_ttyd); j++) {
1172 sfl(j,ss_brother) = -1;
1173 sfl(j,ss_sons) = -1;
1174 }
1175 for(k = i+1; k < j; k++) {
1176 if(sfl(k,ss_ppid) == sfl(i,ss_ppid)) {
1177 for(l=i; sfl(l,ss_brother) != -1;
1178 l=sfl(l,ss_brother)) ;
1179 sfl(l,ss_brother) = k;
1180 goto next;
1181 }
1182 for(l = i; l < j; l++) {
1183 if(l == k) continue;
1184 if(sfl(k,ss_ppid) == afl(l,a_pid)) {
1185 if(sfl(l,ss_sons) == -1)
1186 sfl(l,ss_sons) = k;
1187 else {
1188 for(m = sfl(l,ss_sons);
1189 sfl(m,ss_brother) != -1;
1190 m = sfl(m,ss_brother)) ;
1191 sfl(m,ss_brother) = k;
1192 }
1193 goto next;
1194 }
1195 }
1196 for(l = i; l < j; l++) {
1197 if(l == k) continue;
1198 if(sfl(k,ss_ppid) == sfl(l,ss_ppid)) {
1199 for(m = k; sfl(m,ss_brother) != -1;
1200 m = sfl(m,ss_brother)) ;
1201 sfl(m,ss_brother) = l;
1202 }
1203 }
1204 next: ;
1205 }
1206 walk1(i, 0);
1207 }
1208}
1209
1210walk1(pno, depth)
1211 int pno, depth;
1212{
1213 if(pno == -1)
1214 return;
1215/*** printf("%5d, %d\n",outargs[pno].o_pid, depth); ***/
1216 walkpr(&savcom[pno], depth);
1217 walk1(sfl(pno,ss_sons), depth+1);
1218 walk1(sfl(pno,ss_brother), depth);
1219}
1220
1221char *sshdr =
1222"TTY User SZ RSS CPU S PID ";
1223
1224walkpr(a, depth)
1225 register struct savcom *a;
1226 int depth;
1227{
1228 long tm;
1229
1230 if(!depth) {
1231 printf("%-2.2s", a->ap->a_tty);
1232 printf(" %-8.8s", getname(a->ap->a_uid));
1233 } else
1234 printf(" %-8s", &".......*"[8-(depth<=8?depth:8)]);
1235 printf("%4d%4d", a->ap->a_size/2, a->ap->a_rss/2);
1236 ptime(a->ap);
1237 /* Once there was a "CCPU" field here. Subsumed by -S now. */
1238 printf(" %4.4s", state(a->ap));
1239 printf("%6u ", a->ap->a_pid);
1240 if (a->ap->a_pid == 0)
1241 printf(" swapper");
1242 else if (a->ap->a_pid == 2)
1243 printf(" pagedaemon");
1244 else
1245 printf(" %.*s", twidth - cmdstart - 2, a->ap->a_cmdp);
1246 putchar('\n');
1247}