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