date and time created 80/10/01 17:27:49 by bill
[unix-history] / usr / src / bin / ps / ps.c
CommitLineData
aafc2e2f
BJ
1static char *sccsid = "@(#)ps.c 4.1 (Berkeley) %G%";
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>
19
20struct nlist nl[] = {
21 { "_proc" },
22#define X_PROC 0
23 { "_Usrptmap" },
24#define X_USRPTMA 1
25 { "_usrpt" },
26#define X_USRPT 2
27 { "_text" },
28#define X_TEXT 3
29 { "_nswap" },
30#define X_NSWAP 4
31 { 0 },
32};
33
34struct savcom {
35 union {
36 struct lsav *lp;
37 float u_pctcpu;
38 struct vsav *vp;
39 int s_ssiz;
40 } sun;
41 struct asav *ap;
42} savcom[NPROC];
43
44struct asav {
45 char *a_cmdp;
46 int a_flag;
47 short a_stat, a_uid, a_pid, a_nice;
48 size_t a_size, a_rss;
49 char a_tty[DIRSIZ+1];
50 dev_t a_ttyd;
51 time_t a_time;
52};
53
54char *lhdr;
55/* F S UID PID PPID CP PRI NICE ADDR SZ RSS WCHAN TTY TIME */
56struct lsav {
57 short l_ppid;
58 char l_cpu, l_pri;
59 int l_addr;
60 caddr_t l_wchan;
61};
62
63char *uhdr;
64/* USER PID %CPU NICE SZ RSS TTY TIME */
65
66char *shdr;
67/* SSIZ PID TTY TIME */
68
69char *vhdr;
70/* F PID TTY TIME TIM SL MINFLT MAJFLT SIZE RSS SRS TSIZ TRS PF*/
71struct vsav {
72 short v_slptime, v_pri;
73 u_int v_minflt, v_majflt;
74 size_t v_swrss, v_tsiz, v_txtrss, v_txtswrss;
75 short v_xccount;
76 short v_aveflt;
77};
78
79struct proc proc[8]; /* 8 = a few, for less syscalls */
80struct proc *mproc;
81struct text *text;
82
83union {
84 struct user user;
85 char upages[UPAGES][NBPG];
86} user;
87#define u user.user
88
89#define clear(x) ((int)x & 0x7fffffff)
90
91int chkpid;
92int aflg, cflg, eflg, gflg, kflg, lflg, sflg, uflg, vflg, xflg;
93char *tptr;
94char *gettty(), *getcmd(), *getname(), *savestr(), *alloc();
95int pscomp();
96int nswap;
97struct pte *Usrptma, *usrpt;
98
99struct ttys {
100 char name[DIRSIZ+1];
101 dev_t ttyd;
102 struct ttys *next;
103 struct ttys *cand;
104} *allttys, *cand[16];
105
106struct savcom savcom[NPROC];
107int npr;
108
109int cmdstart;
110int twidth;
111char *kmemf, *memf, *swapf, *nlistf;
112int kmem, mem, swap;
113
114int pcbpf;
115int argaddr;
116extern char _sobuf[];
117
118main(argc, argv)
119 char **argv;
120{
121 register int i, j;
122 register char *ap;
123 int uid;
124 off_t procp;
125
126 if (chdir("/dev") < 0) {
127 perror("/dev");
128 exit(1);
129 }
130 twidth = 80;
131 setbuf(stdout, _sobuf);
132 argc--, argv++;
133 if (argc > 0) {
134 ap = argv[0];
135 while (*ap) switch (*ap++) {
136
137 case 'a':
138 aflg++;
139 break;
140 case 'c':
141 cflg = !cflg;
142 break;
143 case 'e':
144 eflg++;
145 break;
146 case 'g':
147 gflg++;
148 break;
149 case 'k':
150 kflg++;
151 break;
152 case 'l':
153 lflg++;
154 break;
155 case 's':
156 sflg++;
157 break;
158 case 't':
159 if (*ap)
160 tptr = ap;
161 aflg++;
162 gflg++;
163 if (*tptr == '?')
164 xflg++;
165 while (*ap)
166 ap++;
167 break;
168 case 'u':
169 uflg++;
170 break;
171 case 'v':
172 cflg = 1;
173 vflg++;
174 break;
175 case 'w':
176 if (twidth == 80)
177 twidth = 132;
178 else
179 twidth = BUFSIZ;
180 break;
181 case 'x':
182 xflg++;
183 break;
184 default:
185 if (!isdigit(ap[-1]))
186 break;
187 chkpid = atoi(--ap);
188 *ap = 0;
189 aflg++;
190 xflg++;
191 break;
192 }
193 }
194 openfiles(argc, argv);
195 getkvars(argc, argv);
196 getdev();
197 uid = getuid();
198 printhdr();
199 procp = nl[X_PROC].n_value;
200 for (i=0; i<NPROC; i += 8) {
201 lseek(kmem, (char *)procp, 0);
202 j = NPROC - i;
203 if (j > 8)
204 j = 8;
205 j *= sizeof (struct proc);
206 if (read(kmem, (char *)proc, j) != j)
207 cantread("proc table", kmemf);
208 procp += j;
209 for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
210 mproc = &proc[j];
211 if (mproc->p_stat == 0 ||
212 mproc->p_pgrp == 0 && xflg == 0)
213 continue;
214 if (tptr == 0 && gflg == 0 && xflg == 0 &&
215 mproc->p_ppid == 1 && (mproc->p_flag&SDETACH) == 0)
216 continue;
217 if (uid != mproc->p_uid && aflg==0 ||
218 chkpid != 0 && chkpid != mproc->p_pid)
219 continue;
220 if (vflg && gflg == 0 && xflg == 0) {
221 if (mproc->p_stat == SZOMB ||
222 mproc->p_flag&SWEXIT)
223 continue;
224 if (mproc->p_slptime > MAXSLP &&
225 (mproc->p_stat == SSLEEP ||
226 mproc->p_stat == SSTOP))
227 continue;
228 }
229 save();
230 }
231 }
232 qsort(savcom, npr, sizeof(savcom[0]), pscomp);
233 for (i=0; i<npr; i++) {
234 register struct savcom *sp = &savcom[i];
235 if (lflg)
236 lpr(sp);
237 else if (vflg)
238 vpr(sp);
239 else if (uflg)
240 upr(sp);
241 else
242 spr(sp);
243 if (sp->ap->a_flag & SWEXIT)
244 printf(" <exiting>");
245 else if (sp->ap->a_stat == SZOMB)
246 printf(" <defunct>");
247 else if (sp->ap->a_pid == 0)
248 printf(" swapper");
249 else if (sp->ap->a_pid == 2)
250 printf(" pagedaemon");
251 else
252 printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp);
253 printf("\n");
254 }
255 exit(npr == 0);
256}
257
258openfiles(argc, argv)
259 char **argv;
260{
261
262 kmemf = "kmem";
263 if (kflg)
264 kmemf = argc > 1 ? argv[1] : "/vmcore";
265 kmem = open(kmemf, 0);
266 if (kmem < 0) {
267 perror(kmemf);
268 exit(1);
269 }
270 if (kflg) {
271 mem = kmem;
272 memf = kmemf;
273 } else {
274 memf = "mem";
275 mem = open(memf, 0);
276 if (mem < 0) {
277 perror(memf);
278 exit(1);
279 }
280 }
281 swapf = argc>2 ? argv[2]: "drum";
282 swap = open(swapf, 0);
283 if (swap < 0) {
284 perror(swapf);
285 exit(1);
286 }
287}
288
289getkvars(argc, argv)
290 char **argv;
291{
292 register struct nlist *nlp;
293
294 nlistf = argc > 3 ? argv[3] : "/vmunix";
295 nlist(nlistf, nl);
296 if (nl[0].n_type == 0) {
297 fprintf(stderr, "%s: No namelist\n", nlistf);
298 exit(1);
299 }
300 if (kflg)
301 for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++)
302 nlp->n_value = clear(nlp->n_value);
303 Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
304 usrpt = (struct pte *)nl[X_USRPT].n_value;
305 lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
306 if (read(kmem, &nswap, sizeof (nswap)) != sizeof (nswap)) {
307 cantread("nswap", kmemf);
308 exit(1);
309 }
310 if (vflg) {
311 text = (struct text *)alloc(NTEXT * sizeof (struct text));
312 if (text == 0) {
313 fprintf(stderr, "no room for text table\n");
314 exit(1);
315 }
316 lseek(kmem, (long)nl[X_TEXT].n_value, 0);
317 if (read(kmem, (char *)text, NTEXT * sizeof (struct text))
318 != NTEXT * sizeof (struct text)) {
319 cantread("text table", kmemf);
320 exit(1);
321 }
322 }
323}
324
325printhdr()
326{
327 char *hdr;
328
329 if (sflg+lflg+vflg+uflg > 1) {
330 fprintf(stderr, "ps: specify only one of s,l,v and u\n");
331 exit(1);
332 }
333 hdr = lflg ? lhdr : (vflg ? vhdr : (uflg ? uhdr : shdr));
334 if (lflg+vflg+uflg+sflg == 0)
335 hdr += strlen(" SSIZ");
336 cmdstart = strlen(hdr);
337 printf("%s COMMAND\n", hdr);
338 fflush(stdout);
339}
340
341cantread(what, fromwhat)
342 char *what, *fromwhat;
343{
344
345 fprintf(stderr, "ps: error reading %s from %s", what, fromwhat);
346}
347
348struct direct dbuf;
349int dialbase;
350
351getdev()
352{
353 register FILE *df;
354 register struct ttys *dp;
355
356 dialbase = -1;
357 if ((df = fopen(".", "r")) == NULL) {
358 fprintf(stderr, "Can't open . in /dev\n");
359 exit(1);
360 }
361 while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) {
362 if (dbuf.d_ino == 0)
363 continue;
364 maybetty(dp);
365 }
366 fclose(df);
367}
368
369/*
370 * Attempt to avoid stats by guessing minor device
371 * numbers from tty names. Console is known,
372 * know that r(hp|up|mt) are unlikely as are different mem's,
373 * floppy, null, tty, etc.
374 */
375maybetty()
376{
377 register char *cp = dbuf.d_name;
378 register struct ttys *dp;
379 int x;
380 struct stat stb;
381
382 switch (cp[0]) {
383
384 case 'c':
385 if (!strcmp(cp, "console")) {
386 x = 0;
387 goto donecand;
388 }
389 /* cu[la]? are possible!?! don't rule them out */
390 break;
391
392 case 'd':
393 if (!strcmp(cp, "drum"))
394 return (0);
395 break;
396
397 case 'f':
398 if (!strcmp(cp, "floppy"))
399 return (0);
400 break;
401
402 case 'k':
403 cp++;
404 if (*cp == 'U')
405 cp++;
406 goto trymem;
407
408 case 'r':
409 cp++;
410 if (*cp == 'r' || *cp == 'u' || *cp == 'h')
411 cp++;
412#define is(a,b) cp[0] == 'a' && cp[1] == 'b'
413 if (is(r,p) || is(u,p) || is(r,k) || is(r,m) || is(m,t)) {
414 cp += 2;
415 if (isdigit(*cp) && cp[2] == 0)
416 return (0);
417 }
418 break;
419
420 case 'm':
421trymem:
422 if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0)
423 return (0);
424 break;
425
426 case 'n':
427 if (!strcmp(cp, "null"))
428 return (0);
429 break;
430
431 case 'v':
432 if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) &&
433 cp[3] == 0)
434 return (0);
435 break;
436 }
437mightbe:
438 cp = dbuf.d_name;
439 while (cp < &dbuf.d_name[DIRSIZ] && *cp)
440 cp++;
441 --cp;
442 x = 0;
443 if (cp[-1] == 'd') {
444 if (dialbase == -1) {
445 if (stat("ttyd0", &stb) == 0)
446 dialbase = stb.st_rdev & 017;
447 else
448 dialbase = -2;
449 }
450 if (dialbase == -2)
451 x = 0;
452 else
453 x = 11;
454 }
455 if (cp > dbuf.d_name && isdigit(cp[-1]) && isdigit(*cp))
456 x += 10 * (cp[-1] - ' ') + cp[0] - '0';
457 else if (*cp >= 'a' && *cp <= 'f')
458 x += 10 + *cp - 'a';
459 else if (isdigit(*cp))
460 x += *cp - '0';
461 else
462 x = -1;
463donecand:
464 dp = (struct ttys *)alloc(sizeof (struct ttys));
465 strncpy(dp->name, dbuf.d_name, DIRSIZ);
466 dp->next = allttys;
467 dp->ttyd = -1;
468 allttys = dp;
469 if (x == -1)
470 return;
471 x &= 017;
472 dp->cand = cand[x];
473 cand[x] = dp;
474}
475
476char *
477gettty()
478{
479 register char *p;
480 register struct ttys *dp;
481 struct stat stb;
482 int x;
483
484 if (u.u_ttyp == 0)
485 return("?");
486 x = u.u_ttyd & 017;
487 for (dp = cand[x]; dp; dp = dp->cand) {
488 if (dp->ttyd == -1) {
489 if (stat(dp->name, &stb) == 0)
490 dp->ttyd = stb.st_rdev;
491 else
492 dp->ttyd = -2;
493 }
494 if (dp->ttyd == u.u_ttyd)
495 goto found;
496 }
497 /* ick */
498 for (dp = allttys; dp; dp = dp->next) {
499 if (dp->ttyd == -1) {
500 if (stat(dp->name, &stb) == 0)
501 dp->ttyd = stb.st_rdev;
502 else
503 dp->ttyd = -2;
504 }
505 if (dp->ttyd == u.u_ttyd)
506 goto found;
507 }
508 return ("?");
509found:
510 p = dp->name;
511 if (p[0]=='t' && p[1]=='t' && p[2]=='y')
512 p += 3;
513 return (p);
514}
515
516save()
517{
518 register struct savcom *sp;
519 register struct asav *ap;
520 register char *cp;
521 char *ttyp, *cmdp;
522
523 if (mproc->p_stat != SZOMB && getu() == 0)
524 return;
525 ttyp = gettty();
526 if (xflg == 0 && ttyp[0] == '?' || tptr && strcmpn(tptr, ttyp, 2))
527 return;
528 sp = &savcom[npr];
529 cmdp = getcmd();
530 if (cmdp == 0)
531 return;
532 sp->ap = ap = (struct asav *)alloc(sizeof (struct asav));
533 sp->ap->a_cmdp = cmdp;
534#define e(a,b) ap->a = mproc->b
535 e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice);
536 e(a_uid, p_uid); e(a_pid, p_pid); e(a_rss, p_rssize);
537#undef e
538 ap->a_tty[0] = ttyp[0];
539 ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' ';
540 if (ap->a_stat == SZOMB) {
541 register struct xproc *xp = (struct xproc *)mproc;
542
543 ap->a_time = xp->xp_vm.vm_utime + xp->xp_vm.vm_stime;
544 } else {
545 ap->a_size = mproc->p_dsize + mproc->p_ssize;
546 ap->a_ttyd = u.u_ttyd;
547 ap->a_time = u.u_vm.vm_utime + u.u_vm.vm_stime;
548 }
549 ap->a_time /= HZ;
550 if (lflg) {
551 register struct lsav *lp;
552
553 sp->sun.lp = lp = (struct lsav *)alloc(sizeof (struct lsav));
554#define e(a,b) lp->a = mproc->b
555 e(l_ppid, p_ppid); e(l_cpu, p_cpu); e(l_pri, p_pri);
556 if (ap->a_stat != SZOMB)
557 e(l_wchan, p_wchan);
558#undef e
559 lp->l_addr = pcbpf;
560 } else if (vflg) {
561 register struct vsav *vp;
562 register struct text *xp;
563
564 sp->sun.vp = vp = (struct vsav *)alloc(sizeof (struct vsav));
565#define e(a,b) vp->a = mproc->b
566 e(v_slptime, p_slptime); e(v_pri, p_pri);
567 if (ap->a_stat != SZOMB) {
568 e(v_swrss, p_swrss); e(v_aveflt, p_aveflt);
569 vp->v_minflt = u.u_vm.vm_minflt;
570 vp->v_majflt = u.u_vm.vm_majflt;
571 if (mproc->p_textp) {
572 xp = &text[mproc->p_textp -
573 (struct text *)nl[X_TEXT].n_value];
574 vp->v_tsiz = xp->x_size;
575 vp->v_txtrss = xp->x_rssize;
576 vp->v_txtswrss = xp->x_swrss;
577 vp->v_xccount = xp->x_ccount;
578 }
579 }
580#undef e
581 } else if (uflg)
582 sp->sun.u_pctcpu = 0.0;
583 else if (sflg) {
584 if (ap->a_stat != SZOMB) {
585 for (cp = (char *)u.u_stack;
586 cp < &user.upages[UPAGES][NBPG]; )
587 if (*cp++)
588 break;
589 sp->sun.s_ssiz = (&user.upages[UPAGES][NBPG] - cp);
590 }
591 }
592 npr++;
593}
594
595getu()
596{
597 struct pte *pteaddr, apte, arguutl[UPAGES+CLSIZE];
598 register int i;
599 int ncl, size;
600
601 size = sflg ? ctob(UPAGES) : sizeof (struct user);
602 if ((mproc->p_flag & SLOAD) == 0) {
603 lseek(swap, ctob(mproc->p_swaddr), 0);
604 if (read(swap, (char *)&user.user, size) != size) {
605 fprintf(stderr, "ps: cant read u for pid %d from %s\n",
606 mproc->p_pid, swapf);
607 return (0);
608 }
609 pcbpf = 0;
610 argaddr = 0;
611 return (1);
612 }
613 pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
614 lseek(kmem, kflg ? clear(pteaddr) : (int)pteaddr, 0);
615 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
616 printf("ps: cant read indir pte to get u for pid %d from %s\n",
617 mproc->p_pid, swapf);
618 return (0);
619 }
620 lseek(mem,
621 ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0);
622 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
623 printf("ps: cant read page table for u of pid %d from %s\n",
624 mproc->p_pid, swapf);
625 return (0);
626 }
627 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
628 argaddr = ctob(arguutl[0].pg_pfnum);
629 else
630 argaddr = 0;
631 pcbpf = arguutl[CLSIZE].pg_pfnum;
632 ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
633 while (--ncl >= 0) {
634 i = ncl * CLSIZE;
635 lseek(mem, ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
636 if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
637 printf("ps: cant read page %d of u of pid %d from %s\n",
638 arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
639 return(0);
640 }
641 }
642 return (1);
643}
644
645char *
646getcmd()
647{
648 char cmdbuf[BUFSIZ];
649 union {
650 char argc[CLSIZE*NBPG];
651 int argi[CLSIZE*NBPG/sizeof (int)];
652 } argspac;
653 register char *cp;
654 register int *ip;
655 char c;
656 int nbad;
657 struct dblock db;
658
659 if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT))
660 return ("");
661 if (cflg) {
662 strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm));
663 return (savestr(cmdbuf));
664 }
665 if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) {
666 vstodb(0, CLSIZE, &u.u_smap, &db, 1);
667 lseek(swap, ctob(db.db_base), 0);
668 if (read(swap, (char *)&argspac, sizeof(argspac))
669 != sizeof(argspac))
670 goto bad;
671 } else {
672 lseek(mem, argaddr, 0);
673 if (read(mem, (char *)&argspac, sizeof (argspac))
674 != sizeof (argspac))
675 goto bad;
676 }
677 ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)];
678 ip -= 2; /* last arg word and .long 0 */
679 while (*--ip)
680 if (ip == argspac.argi)
681 goto retucomm;
682 *(char *)ip = ' ';
683 ip++;
684 nbad = 0;
685 for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) {
686 c = *cp & 0177;
687 if (c == 0)
688 *cp = ' ';
689 else if (c < ' ' || c > 0176) {
690 if (++nbad >= 5*(eflg+1)) {
691 *cp++ = ' ';
692 break;
693 }
694 *cp = '?';
695 } else if (eflg == 0 && c == '=') {
696 while (*--cp != ' ')
697 if (cp <= (char *)ip)
698 break;
699 break;
700 }
701 }
702 *cp = 0;
703 while (*--cp == ' ')
704 *cp = 0;
705 cp = (char *)ip;
706 strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp);
707 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
708 strcat(cmdbuf, " (");
709 strncat(cmdbuf, u.u_comm, sizeof(u.u_comm));
710 strcat(cmdbuf, ")");
711 }
712 if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-')
713 return (0);
714 return (savestr(cmdbuf));
715
716bad:
717 fprintf(stderr, "ps: error locating command name for pid %d\n",
718 mproc->p_pid);
719retucomm:
720 strcpy(cmdbuf, " (");
721 strncat(cmdbuf, u.u_comm, sizeof (u.u_comm));
722 strcat(cmdbuf, ")");
723 return (savestr(cmdbuf));
724}
725
726char *lhdr =
727" F S UID PID PPID CP PRI NI ADDR SZ RSS WCHAN TTY TIME";
728lpr(sp)
729 struct savcom *sp;
730{
731 register struct asav *ap = sp->ap;
732 register struct lsav *lp = sp->sun.lp;
733
734 printf("%6x %c%4d%6u%6u%3d%4d%2d%6x%4d%5d",
735 ap->a_flag, "0SWRIZT"[ap->a_stat], ap->a_uid,
736 ap->a_pid, lp->l_ppid, lp->l_cpu&0377, lp->l_pri-PZERO,
737 ap->a_nice-NZERO, lp->l_addr, ap->a_size, ap->a_rss);
738 printf(lp->l_wchan ? " %5x" : " ", (int)lp->l_wchan&0xfffff);
739 ptty(ap->a_tty);
740 ptime(ap);
741}
742
743ptty(tp)
744 char *tp;
745{
746
747 printf(" %-2.2s", tp);
748}
749
750ptime(ap)
751 struct asav *ap;
752{
753
754 printf("%3ld:%02ld", ap->a_time / HZ, ap->a_time % HZ);
755}
756
757char *uhdr =
758"USER PID %CPU NICE SZ RSS TTY TIME";
759upr(sp)
760 struct savcom *sp;
761{
762 register struct asav *ap = sp->ap;
763
764 printf("%-8.8s %5u%5.1f%5d%4d%5d",
765 getname(ap->a_uid), ap->a_pid, sp->sun.u_pctcpu, ap->a_nice-NZERO,
766 ap->a_size, ap->a_rss);
767 ptty(ap->a_tty);
768 ptime(ap);
769}
770
771char *vhdr =
772"F PID TTY TIME RES SL MINFLT MAJFLT SIZE RSS SRS TSIZ TRS PF";
773vpr(sp)
774 struct savcom *sp;
775{
776 register struct vsav *vp = sp->sun.vp;
777 register struct asav *ap = sp->ap;
778 char stat, nice, anom;
779
780 switch (ap->a_stat) {
781
782 case SSLEEP:
783 case SSTOP:
784 if ((ap->a_flag & SLOAD) == 0)
785 stat = 'W';
786 else if (vp->v_pri >= PZERO)
787 stat = 'S';
788 else if (ap->a_flag & SPAGE)
789 stat = 'P';
790 else
791 stat = 'D';
792 break;
793
794 case SRUN:
795 case SIDL:
796 stat = ap->a_flag & SLOAD ? 'R' : 'W';
797 break;
798 }
799 nice = ap->a_nice > NZERO ? 'N' : ' ';
800 anom = ap->a_flag & (SANOM|SUANOM) ? 'A' : ' ';
801 printf("%c%c%c%6u ", stat, nice, anom, ap->a_pid);
802 ptty(ap->a_tty);
803 ptime(ap);
804 printf("%4d%3d%8d%8d%5d%5d%5d%5d%4d%3d",
805 ap->a_time, vp->v_slptime, vp->v_minflt, vp->v_majflt,
806 ap->a_size, ap->a_rss / 2, vp->v_swrss / 2,
807 vp->v_tsiz / 2, vp->v_txtrss / 2, vp->v_aveflt);
808}
809
810char *shdr =
811" SSIZ PID TTY TIME";
812spr(sp)
813 struct savcom *sp;
814{
815 register struct asav *ap = sp->ap;
816
817 if (sflg)
818 printf("%5d", sp->sun.s_ssiz);
819 printf(" %5u", ap->a_pid);
820 ptty(ap->a_tty);
821 ptime(ap);
822}
823
824/*
825 * Given a base/size pair in virtual swap area,
826 * return a physical base/size pair which is the
827 * (largest) initial, physically contiguous block.
828 */
829vstodb(vsbase, vssize, dmp, dbp, rev)
830 register int vsbase;
831 int vssize;
832 struct dmap *dmp;
833 register struct dblock *dbp;
834{
835 register int blk = DMMIN;
836 register swblk_t *ip = dmp->dm_map;
837
838 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
839 panic("vstodb");
840 while (vsbase >= blk) {
841 vsbase -= blk;
842 if (blk < DMMAX)
843 blk *= 2;
844 ip++;
845 }
846 if (*ip <= 0 || *ip + blk > nswap)
847 panic("vstodb *ip");
848 dbp->db_size = min(vssize, blk - vsbase);
849 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
850}
851
852/*ARGSUSED*/
853panic(cp)
854 char *cp;
855{
856
857#ifdef DEBUG
858 printf("%s\n", cp);
859#endif
860}
861
862min(a, b)
863{
864
865 return (a < b ? a : b);
866}
867
868pscomp(s1, s2)
869 struct savcom *s1, *s2;
870{
871 register int i;
872
873 if (vflg)
874 return (vsize(s2) - vsize(s1));
875 i = s1->ap->a_ttyd - s2->ap->a_ttyd;
876 if (i == 0)
877 i = s1->ap->a_pid - s2->ap->a_pid;
878 return (i);
879}
880
881vsize(sp)
882 struct savcom *sp;
883{
884 register struct asav *ap = sp->ap;
885 register struct vsav *vp = sp->sun.vp;
886
887 if (ap->a_flag & SLOAD)
888 return (ap->a_rss +
889 vp->v_txtrss / (vp->v_xccount ? vp->v_xccount : 1));
890 return (vp->v_swrss + (vp->v_xccount ? 0 : vp->v_txtswrss));
891}
892
893#define NMAX 8
894#define NUID 2048
895
896char names[NUID][NMAX+1];
897
898/*
899 * Stolen from ls...
900 */
901char *
902getname(uid)
903{
904 register struct passwd *pw;
905 static init;
906 struct passwd *getpwent();
907
908 if (names[uid][0])
909 return (&names[uid][0]);
910 if (init == 2)
911 return (0);
912 if (init == 0)
913 setpwent(), init = 1;
914 while (pw = getpwent()) {
915 if (pw->pw_uid >= NUID)
916 continue;
917 if (names[pw->pw_uid][0])
918 continue;
919 strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
920 if (pw->pw_uid == uid)
921 return (&names[uid][0]);
922 }
923 init = 2;
924 endpwent();
925 return (0);
926}
927
928char *freebase;
929int nleft;
930
931char *
932alloc(size)
933 int size;
934{
935 register char *cp;
936 register int i;
937
938 if (size > nleft) {
939 freebase = (char *)sbrk(i = size > 2048 ? size : 2048);
940 if (freebase == 0) {
941 fprintf(stderr, "ps: ran out of memory\n");
942 exit(1);
943 }
944 nleft = i - size;
945 } else
946 nleft -= size;
947 cp = freebase;
948 for (i = size; --i >= 0; )
949 *cp++ = 0;
950 freebase = cp;
951 return (cp - size);
952}
953
954char *
955savestr(cp)
956 char *cp;
957{
958 register int len;
959 register char *dp;
960
961 len = strlen(cp);
962 dp = (char *)alloc(len+1);
963 strcpy(dp, cp);
964 return (dp);
965}