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