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