use the right macros
[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
8590462f 14static char sccsid[] = "@(#)ps.c 5.18 (Berkeley) %G%";
761330fe 15#endif not lint
3d9f6a35 16
aafc2e2f 17#include <sys/param.h>
8590462f 18#include <sys/types.h>
417dadf5 19#include <sys/ioctl.h>
aafc2e2f 20#include <sys/tty.h>
b38b1b3a 21#include <sys/dir.h>
aafc2e2f
BJ
22#include <sys/user.h>
23#include <sys/proc.h>
aafc2e2f
BJ
24#include <sys/vm.h>
25#include <sys/text.h>
26#include <sys/stat.h>
066ec2ef 27#include <sys/mbuf.h>
a5ae2576
KB
28#include <machine/pte.h>
29#include <a.out.h>
30#include <pwd.h>
7f0fa372 31#include <math.h>
e8807835 32#include <errno.h>
a5ae2576
KB
33#include <stdio.h>
34#include <ctype.h>
35#include "pathnames.h"
aafc2e2f 36
3180e1ce
KM
37char *nl_names[] = {
38 "_proc",
aafc2e2f 39#define X_PROC 0
3180e1ce 40 "_Usrptmap",
e8807835 41#define X_USRPTMAP 1
3180e1ce 42 "_usrpt",
aafc2e2f 43#define X_USRPT 2
3180e1ce 44 "_text",
aafc2e2f 45#define X_TEXT 3
3180e1ce 46 "_nswap",
aafc2e2f 47#define X_NSWAP 4
3180e1ce 48 "_maxslp",
c67277e8 49#define X_MAXSLP 5
3180e1ce 50 "_ccpu",
7f0fa372 51#define X_CCPU 6
3180e1ce 52 "_ecmx",
0f0e0052 53#define X_ECMX 7
3180e1ce 54 "_nproc",
bdb1f95f 55#define X_NPROC 8
3180e1ce 56 "_ntext",
bdb1f95f 57#define X_NTEXT 9
3180e1ce 58 "_dmmin",
b38b1b3a 59#define X_DMMIN 10
3180e1ce 60 "_dmmax",
b38b1b3a 61#define X_DMMAX 11
3180e1ce 62 "_Sysmap",
e8807835 63#define X_SYSMAP 12
3180e1ce 64 "_Syssize",
e8807835 65#define X_SYSSIZE 13
3180e1ce
KM
66 "_inode",
67#define X_INODE 14
68 "_file",
69#define X_FILE 15
70 "_cfree",
71#define X_CFREE 16
72 "_callout",
73#define X_CALLOUT 17
74 "_swapmap",
75#define X_SWAPMAP 18
76 "_argmap",
77#define X_ARGMAP 19
78 "_kernelmap",
79#define X_KERNELMAP 20
80 "_mbmap",
81#define X_MBMAP 21
db3eb2dc 82 "_namecache",
3180e1ce
KM
83#define X_NCH 22
84 "_quota",
85#define X_QUOTA 23
86 "_dquot",
87#define X_DQUOT 24
88 "_swbuf",
89#define X_SWBUF 25
90 "_buf",
91#define X_BUF 26
92 "_cmap",
93#define X_CMAP 27
94 "_buffers",
95#define X_BUFFERS 28
8590462f
KM
96 "_fscale",
97#define X_FSCALE 29
3180e1ce 98 ""
aafc2e2f
BJ
99};
100
3180e1ce
KM
101struct nlist *nl; /* all because we can't init unions */
102int nllen; /* # of nlist entries */
103
aafc2e2f
BJ
104struct savcom {
105 union {
106 struct lsav *lp;
107 float u_pctcpu;
108 struct vsav *vp;
109 int s_ssiz;
066ec2ef 110 } s_un;
aafc2e2f 111 struct asav *ap;
bdb1f95f 112} *savcom;
aafc2e2f
BJ
113
114struct asav {
115 char *a_cmdp;
116 int a_flag;
c67277e8 117 short a_stat, a_uid, a_pid, a_nice, a_pri, a_slptime, a_time;
0f0e0052
BJ
118 size_t a_size, a_rss, a_tsiz, a_txtrss;
119 short a_xccount;
3d9f6a35 120 char a_tty[MAXNAMLEN+1];
aafc2e2f 121 dev_t a_ttyd;
c67277e8 122 time_t a_cpu;
79de1ed3 123 size_t a_maxrss;
aafc2e2f
BJ
124};
125
126char *lhdr;
3180e1ce 127int wcwidth; /* width of the wchan field for sprintf*/
aafc2e2f
BJ
128struct lsav {
129 short l_ppid;
ed325f47 130 u_char l_cpu;
aafc2e2f
BJ
131 int l_addr;
132 caddr_t l_wchan;
133};
134
135char *uhdr;
aafc2e2f 136char *shdr;
aafc2e2f
BJ
137
138char *vhdr;
aafc2e2f 139struct vsav {
0f0e0052
BJ
140 u_int v_majflt;
141 size_t v_swrss, v_txtswrss;
142 float v_pctcpu;
aafc2e2f
BJ
143};
144
e8807835
RC
145#define NPROC 16
146
147struct proc proc[NPROC]; /* a few, for less syscalls */
aafc2e2f
BJ
148struct proc *mproc;
149struct text *text;
150
151union {
152 struct user user;
153 char upages[UPAGES][NBPG];
154} user;
155#define u user.user
156
e8807835 157#ifndef PSFILE
a5ae2576 158char *psdb = _PATH_PSDATABASE;
e8807835
RC
159#else
160char *psdb = PSFILE;
161#endif
aafc2e2f 162
2e06a8e0 163int chkpid = -1;
3180e1ce 164int aflg, cflg, eflg, gflg, kflg, lflg, nflg, sflg,
e8807835 165 uflg, vflg, xflg, Uflg;
3180e1ce 166int nchans; /* total # of wait channels */
aafc2e2f 167char *tptr;
e8807835 168char *gettty(), *getcmd(), *getname(), *savestr(), *state();
3d9f6a35 169char *rindex(), *calloc(), *sbrk(), *strcpy(), *strcat(), *strncat();
963be923 170char *strncpy(), *index(), *ttyname(), mytty[MAXPATHLEN+1];
3180e1ce 171char *malloc(), *getchan();
3d9f6a35 172long lseek();
e8807835 173off_t vtophys();
0f0e0052 174double pcpu(), pmem();
3180e1ce 175int wchancomp();
aafc2e2f 176int pscomp();
c67277e8 177int nswap, maxslp;
bdb1f95f 178struct text *atext;
8590462f 179fixpt_t ccpu;
0f0e0052 180int ecmx;
e8807835 181struct pte *Usrptmap, *usrpt;
8590462f 182int nproc, ntext, fscale;
b38b1b3a 183int dmmin, dmmax;
e8807835
RC
184struct pte *Sysmap;
185int Syssize;
186
e8807835 187int nttys;
aafc2e2f
BJ
188
189struct ttys {
aafc2e2f 190 dev_t ttyd;
3bc0950e 191 int cand;
e8807835 192 char name[MAXNAMLEN+1];
3bc0950e
KM
193} *allttys;
194int cand[16] = {-1, -1, -1, -1, -1, -1, -1, -1,
195 -1, -1, -1, -1, -1, -1, -1, -1};
196struct lttys {
197 struct ttys ttys;
198 struct lttys *next;
199} *lallttys;
200
3180e1ce
KM
201/*
202 * struct for the symbolic wait channel info
203 *
204 * WNAMESIZ is the max # of chars saved of the symbolic wchan gleaned
205 * from the namelist. Normally, only WSNAMESIZ are printed in the long
206 * format, unless the terminal width is greater than WTSIZ wide.
207 */
208#define WNAMESIZ 12
209#define WSNAMESIZ 6
210#define WTSIZ 95
211
212struct wchan {
213 char wc_name[WNAMESIZ+1]; /* symbolic name */
214 caddr_t wc_caddr; /* addr in kmem */
215} *wchanhd; /* an array sorted by wc_caddr */
216
217#define NWCINDEX 10 /* the size of the index array */
218
219caddr_t wchan_index[NWCINDEX]; /* used to speed searches */
220/*
221 * names listed here are not kept as wait channels -- this is used to
222 * remove names that confuse ps, like symbols that define the end of an
223 * array that happen to be equal to the next symbol.
224 */
225char *wchan_stop_list[] = {
226 "umbabeg",
227 "umbaend",
228 "calimit",
229 NULL
230};
aafc2e2f 231
aafc2e2f
BJ
232int npr;
233
234int cmdstart;
235int twidth;
ceb20920 236struct winsize win;
aafc2e2f 237char *kmemf, *memf, *swapf, *nlistf;
25659ede 238int kmem, mem, swap = -1;
1fb6a666 239int rawcpu, sumcpu;
aafc2e2f
BJ
240
241int pcbpf;
242int argaddr;
aafc2e2f 243
72db1f59 244#define pgtok(a) ((a)/(1024/NBPG))
066ec2ef 245
aafc2e2f
BJ
246main(argc, argv)
247 char **argv;
248{
249 register int i, j;
250 register char *ap;
251 int uid;
252 off_t procp;
417dadf5 253 int width;
aafc2e2f 254
78d22f16 255 if (ioctl(1, TIOCGWINSZ, &win) == -1)
417dadf5
JB
256 twidth = 80;
257 else
258 twidth = (win.ws_col == 0 ? 80 : win.ws_col);
aafc2e2f
BJ
259 argc--, argv++;
260 if (argc > 0) {
261 ap = argv[0];
262 while (*ap) switch (*ap++) {
263
0f0e0052 264 case 'C':
066ec2ef 265 rawcpu++;
0f0e0052 266 break;
1fb6a666
BJ
267 case 'S':
268 sumcpu++;
269 break;
e8807835
RC
270
271 case 'U':
272 Uflg++;
273 break;
274
aafc2e2f
BJ
275 case 'a':
276 aflg++;
277 break;
278 case 'c':
066ec2ef 279 cflg = !cflg;
aafc2e2f
BJ
280 break;
281 case 'e':
066ec2ef 282 eflg++;
aafc2e2f
BJ
283 break;
284 case 'g':
066ec2ef 285 gflg++;
aafc2e2f
BJ
286 break;
287 case 'k':
066ec2ef 288 kflg++;
aafc2e2f
BJ
289 break;
290 case 'l':
066ec2ef 291 lflg++;
aafc2e2f 292 break;
3180e1ce
KM
293 case 'n':
294 nflg++;
295 break;
aafc2e2f 296 case 's':
066ec2ef 297 sflg++;
aafc2e2f
BJ
298 break;
299 case 't':
300 if (*ap)
301 tptr = ap;
963be923
MK
302 else if ((tptr = ttyname(0)) != 0) {
303 tptr = strcpy(mytty, tptr);
a5ae2576
KB
304 if (strncmp(tptr, _PATH_DEV,
305 sizeof(_PATH_DEV) - 1) == 0)
963be923 306 tptr += 5;
e13b2716 307 }
963be923
MK
308 if (strncmp(tptr, "tty", 3) == 0)
309 tptr += 3;
066ec2ef 310 aflg++;
aafc2e2f 311 gflg++;
066ec2ef 312 if (tptr && *tptr == '?')
aafc2e2f
BJ
313 xflg++;
314 while (*ap)
315 ap++;
316 break;
133a0b3b 317 case 'u':
066ec2ef 318 uflg++;
aafc2e2f
BJ
319 break;
320 case 'v':
321 cflg = 1;
066ec2ef 322 vflg++;
aafc2e2f
BJ
323 break;
324 case 'w':
417dadf5 325 if (twidth < 132)
aafc2e2f
BJ
326 twidth = 132;
327 else
328 twidth = BUFSIZ;
329 break;
330 case 'x':
331 xflg++;
332 break;
333 default:
334 if (!isdigit(ap[-1]))
335 break;
336 chkpid = atoi(--ap);
337 *ap = 0;
066ec2ef 338 aflg++;
aafc2e2f
BJ
339 xflg++;
340 break;
341 }
342 }
343 openfiles(argc, argv);
344 getkvars(argc, argv);
aafc2e2f
BJ
345 uid = getuid();
346 printhdr();
bdb1f95f
BJ
347 procp = getw(nl[X_PROC].n_value);
348 nproc = getw(nl[X_NPROC].n_value);
e8807835
RC
349 savcom = (struct savcom *)calloc((unsigned) nproc, sizeof (*savcom));
350 for (i=0; i<nproc; i += NPROC) {
3d9f6a35 351 klseek(kmem, (long)procp, 0);
bdb1f95f 352 j = nproc - i;
e8807835
RC
353 if (j > NPROC)
354 j = NPROC;
aafc2e2f 355 j *= sizeof (struct proc);
25659ede 356 if (read(kmem, (char *)proc, j) != j) {
aafc2e2f 357 cantread("proc table", kmemf);
25659ede
BJ
358 exit(1);
359 }
aafc2e2f
BJ
360 procp += j;
361 for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
362 mproc = &proc[j];
363 if (mproc->p_stat == 0 ||
364 mproc->p_pgrp == 0 && xflg == 0)
c67277e8 365 continue;
aafc2e2f 366 if (tptr == 0 && gflg == 0 && xflg == 0 &&
6e515893 367 mproc->p_ppid == 1)
aafc2e2f 368 continue;
e8807835
RC
369 if (uid != mproc->p_uid && aflg==0)
370 continue;
2e06a8e0 371 if (chkpid != -1 && chkpid != mproc->p_pid)
aafc2e2f
BJ
372 continue;
373 if (vflg && gflg == 0 && xflg == 0) {
374 if (mproc->p_stat == SZOMB ||
375 mproc->p_flag&SWEXIT)
376 continue;
377 if (mproc->p_slptime > MAXSLP &&
378 (mproc->p_stat == SSLEEP ||
379 mproc->p_stat == SSTOP))
380 continue;
381 }
382 save();
383 }
384 }
417dadf5
JB
385 width = twidth - cmdstart - 2;
386 if (width < 0)
387 width = 0;
e8807835 388 qsort((char *) savcom, npr, sizeof(savcom[0]), pscomp);
aafc2e2f
BJ
389 for (i=0; i<npr; i++) {
390 register struct savcom *sp = &savcom[i];
391 if (lflg)
392 lpr(sp);
393 else if (vflg)
394 vpr(sp);
395 else if (uflg)
396 upr(sp);
397 else
398 spr(sp);
963be923 399 if (sp->ap->a_stat == SZOMB)
ed325f47 400 printf(" %.*s", twidth - cmdstart - 2, "<defunct>");
963be923 401 else if (sp->ap->a_flag & SWEXIT)
ed325f47 402 printf(" %.*s", twidth - cmdstart - 2, "<exiting>");
aafc2e2f 403 else if (sp->ap->a_pid == 0)
ed325f47 404 printf(" %.*s", twidth - cmdstart - 2, "swapper");
aafc2e2f 405 else if (sp->ap->a_pid == 2)
ed325f47 406 printf(" %.*s", twidth - cmdstart - 2, "pagedaemon");
aafc2e2f
BJ
407 else
408 printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp);
409 printf("\n");
410 }
411 exit(npr == 0);
412}
413
bdb1f95f 414getw(loc)
3d9f6a35 415 unsigned long loc;
bdb1f95f 416{
e8807835 417 int word;
bdb1f95f 418
3d9f6a35
KM
419 klseek(kmem, (long)loc, 0);
420 if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word))
bdb1f95f
BJ
421 printf("error reading kmem at %x\n", loc);
422 return (word);
423}
424
6e515893 425klseek(fd, loc, off)
3d9f6a35
KM
426 int fd;
427 long loc;
428 int off;
6e515893 429{
e8807835
RC
430 if (kflg) {
431 if ((loc = vtophys(loc)) == -1)
432 return;
433 }
3d9f6a35 434 (void) lseek(fd, (long)loc, off);
6e515893
BJ
435}
436
916caac0
KM
437/*
438 * Version allows change of db format w/o temporarily bombing ps's
439 */
440char thisversion[4] = "V2"; /* length must remain 4 */
441
e8807835
RC
442writepsdb(unixname)
443 char *unixname;
444{
e8807835 445 register FILE *fp;
3bc0950e 446 struct lttys *lt;
916caac0 447 struct stat stb;
e8807835 448
963be923 449 setgid(getgid());
e8807835
RC
450 setuid(getuid());
451 if ((fp = fopen(psdb, "w")) == NULL) {
452 perror(psdb);
453 exit(1);
454 } else
455 fchmod(fileno(fp), 0644);
916caac0 456
3baf21ed 457 fwrite(thisversion, sizeof thisversion, 1, fp);
916caac0
KM
458 fwrite(unixname, strlen(unixname) + 1, 1, fp);
459 if (stat(unixname, &stb) < 0)
460 stb.st_mtime = 0;
3baf21ed 461 fwrite((char *) &stb.st_mtime, sizeof stb.st_mtime, 1, fp);
916caac0 462
e8807835
RC
463 fwrite((char *) &nllen, sizeof nllen, 1, fp);
464 fwrite((char *) nl, sizeof (struct nlist), nllen, fp);
3bc0950e 465 fwrite((char *) cand, sizeof (cand), 1, fp);
e8807835 466 fwrite((char *) &nttys, sizeof nttys, 1, fp);
3bc0950e
KM
467 for (lt = lallttys ; lt ; lt = lt->next)
468 fwrite((char *)&lt->ttys, sizeof (struct ttys), 1, fp);
3180e1ce
KM
469 fwrite((char *) &nchans, sizeof nchans, 1, fp);
470 fwrite((char *) wchanhd, sizeof (struct wchan), nchans, fp);
471 fwrite((char *) wchan_index, sizeof (caddr_t), NWCINDEX, fp);
e8807835
RC
472 fclose(fp);
473}
474
475readpsdb(unixname)
476 char *unixname;
477{
e8807835
RC
478 register i;
479 register FILE *fp;
480 char unamebuf[BUFSIZ];
481 char *p = unamebuf;
916caac0
KM
482 char dbversion[sizeof thisversion];
483 struct stat stb;
484 time_t dbmtime;
e8807835
RC
485 extern int errno;
486
487 if ((fp = fopen(psdb, "r")) == NULL) {
488 if (errno == ENOENT)
489 return (0);
490 perror(psdb);
491 exit(1);
492 }
493
916caac0
KM
494 /*
495 * Does the db file match this unix?
496 */
497 fread(dbversion, sizeof dbversion, 1, fp);
498 if (bcmp(thisversion, dbversion, sizeof thisversion))
499 goto bad;
500 while ((*p = getc(fp)) != '\0')
501 p++;
502 if (strcmp(unixname, unamebuf))
503 goto bad;
504 fread((char *) &dbmtime, sizeof dbmtime, 1, fp);
505 if (stat(unixname, &stb) < 0)
506 stb.st_mtime = 0;
507 if (stb.st_mtime != dbmtime)
508 goto bad;
509
e8807835 510 fread((char *) &nllen, sizeof nllen, 1, fp);
3180e1ce 511 nl = (struct nlist *) malloc (nllen * sizeof (struct nlist));
e8807835 512 fread((char *) nl, sizeof (struct nlist), nllen, fp);
3bc0950e 513 fread((char *) cand, sizeof (cand), 1, fp);
e8807835 514 fread((char *) &nttys, sizeof nttys, 1, fp);
3bc0950e
KM
515 allttys = (struct ttys *)malloc(sizeof(struct ttys)*nttys);
516 if (allttys == NULL) {
517 fprintf(stderr, "ps: Can't malloc space for tty table\n");
518 exit(1);
519 }
e8807835 520 fread((char *) allttys, sizeof (struct ttys), nttys, fp);
3180e1ce
KM
521 fread((char *) &nchans, sizeof nchans, 1, fp);
522 wchanhd = (struct wchan *) malloc(nchans * sizeof (struct wchan));
523 if (wchanhd == NULL) {
524 fprintf(stderr, "ps: Can't malloc space for wait channels\n");
525 nflg++;
526 fseek(fp, (long) nchans * sizeof (struct wchan), 1);
527 } else
528 fread((char *) wchanhd, sizeof (struct wchan), nchans, fp);
529 fread((char *) wchan_index, sizeof (caddr_t), NWCINDEX, fp);
916caac0
KM
530 fclose(fp);
531 return(1);
532
533bad:
534 fclose(fp);
535 return(0);
e8807835
RC
536}
537
aafc2e2f
BJ
538openfiles(argc, argv)
539 char **argv;
540{
541
a5ae2576 542 kmemf = _PATH_KMEM;
aafc2e2f 543 if (kflg)
a5ae2576 544 kmemf = argc > 2 ? argv[2] : _PATH_VMCORE;
aafc2e2f
BJ
545 kmem = open(kmemf, 0);
546 if (kmem < 0) {
547 perror(kmemf);
548 exit(1);
549 }
550 if (kflg) {
551 mem = kmem;
552 memf = kmemf;
553 } else {
a5ae2576 554 memf = _PATH_MEM;
aafc2e2f
BJ
555 mem = open(memf, 0);
556 if (mem < 0) {
557 perror(memf);
558 exit(1);
559 }
560 }
25659ede 561 if (kflg == 0 || argc > 3) {
a5ae2576 562 swapf = argc>3 ? argv[3]: _PATH_DRUM;
25659ede
BJ
563 swap = open(swapf, 0);
564 if (swap < 0) {
565 perror(swapf);
566 exit(1);
567 }
aafc2e2f
BJ
568 }
569}
570
571getkvars(argc, argv)
572 char **argv;
573{
3180e1ce 574 int faildb = 0; /* true if psdatabase init failed */
916caac0 575 int i;
aafc2e2f 576
a5ae2576 577 nlistf = argc > 1 ? argv[1] : _PATH_UNIX;
e8807835 578 if (Uflg) {
3180e1ce 579 init_nlist();
e8807835 580 nlist(nlistf, nl);
3180e1ce 581 getvchans();
e8807835
RC
582 getdev();
583 writepsdb(nlistf);
584 exit (0);
585 } else if (!readpsdb(nlistf)) {
3180e1ce 586 init_nlist();
e8807835 587 if (!kflg)
3180e1ce
KM
588 nl[X_SYSMAP].n_un.n_name = "";
589 faildb = 1;
e8807835 590 nlist(nlistf, nl);
963be923 591 nttys = 0;
e8807835
RC
592 getdev();
593 }
594
aafc2e2f
BJ
595 if (nl[0].n_type == 0) {
596 fprintf(stderr, "%s: No namelist\n", nlistf);
597 exit(1);
598 }
e8807835
RC
599 if (kflg) {
600 /* We must do the sys map first because klseek uses it */
601 long addr;
602
603 Syssize = nl[X_SYSSIZE].n_value;
604 Sysmap = (struct pte *)
605 calloc((unsigned) Syssize, sizeof (struct pte));
606 if (Sysmap == NULL) {
607 fprintf(stderr, "Out of space for Sysmap\n");
608 exit(1);
609 }
610 addr = (long) nl[X_SYSMAP].n_value;
f20270fc 611 addr &= ~KERNBASE;
e8807835
RC
612 (void) lseek(kmem, addr, 0);
613 read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte));
614 }
3180e1ce
KM
615 if (faildb)
616 getvchans();
e8807835
RC
617 usrpt = (struct pte *)nl[X_USRPT].n_value;
618 Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
6e515893 619 klseek(kmem, (long)nl[X_NSWAP].n_value, 0);
3d9f6a35 620 if (read(kmem, (char *)&nswap, sizeof (nswap)) != sizeof (nswap)) {
aafc2e2f
BJ
621 cantread("nswap", kmemf);
622 exit(1);
623 }
6e515893 624 klseek(kmem, (long)nl[X_MAXSLP].n_value, 0);
3d9f6a35 625 if (read(kmem, (char *)&maxslp, sizeof (maxslp)) != sizeof (maxslp)) {
c67277e8
BJ
626 cantread("maxslp", kmemf);
627 exit(1);
628 }
6e515893 629 klseek(kmem, (long)nl[X_CCPU].n_value, 0);
3d9f6a35 630 if (read(kmem, (char *)&ccpu, sizeof (ccpu)) != sizeof (ccpu)) {
7f0fa372
BJ
631 cantread("ccpu", kmemf);
632 exit(1);
633 }
6e515893 634 klseek(kmem, (long)nl[X_ECMX].n_value, 0);
3d9f6a35 635 if (read(kmem, (char *)&ecmx, sizeof (ecmx)) != sizeof (ecmx)) {
0f0e0052
BJ
636 cantread("ecmx", kmemf);
637 exit(1);
638 }
639 if (uflg || vflg) {
bdb1f95f 640 ntext = getw(nl[X_NTEXT].n_value);
e8807835
RC
641 text = (struct text *)
642 calloc((unsigned) ntext, sizeof (struct text));
aafc2e2f
BJ
643 if (text == 0) {
644 fprintf(stderr, "no room for text table\n");
645 exit(1);
646 }
bdb1f95f 647 atext = (struct text *)getw(nl[X_TEXT].n_value);
3d9f6a35 648 klseek(kmem, (long)atext, 0);
bdb1f95f
BJ
649 if (read(kmem, (char *)text, ntext * sizeof (struct text))
650 != ntext * sizeof (struct text)) {
aafc2e2f
BJ
651 cantread("text table", kmemf);
652 exit(1);
653 }
654 }
b38b1b3a
SL
655 dmmin = getw(nl[X_DMMIN].n_value);
656 dmmax = getw(nl[X_DMMAX].n_value);
8590462f 657 fscale = getw(nl[X_FSCALE].n_value);
aafc2e2f
BJ
658}
659
3180e1ce
KM
660/*
661 * get the valloc'ed kernel variables for symbolic wait channels
662 */
663getvchans()
664{
665 int i, tmp;
666
667 if (nflg)
668 return;
669
670#define addv(i) addchan(&nl[i].n_un.n_name[1], getw(nl[i].n_value))
671 addv(X_INODE);
672 addv(X_FILE);
673 addv(X_PROC);
674 addv(X_TEXT);
675 addv(X_CFREE);
676 addv(X_CALLOUT);
677 addv(X_SWAPMAP);
678 addv(X_ARGMAP);
679 addv(X_KERNELMAP);
680 addv(X_MBMAP);
681 addv(X_NCH);
682 if (nl[X_QUOTA].n_value != 0) { /* these are #ifdef QUOTA */
683 addv(X_QUOTA);
684 addv(X_DQUOT);
685 }
686 addv(X_SWBUF);
687 addv(X_BUF);
688 addv(X_CMAP);
689 addv(X_BUFFERS);
690 qsort(wchanhd, nchans, sizeof (struct wchan), wchancomp);
691 for (i = 0; i < NWCINDEX; i++) {
692 tmp = i * nchans;
693 wchan_index[i] = wchanhd[tmp / NWCINDEX].wc_caddr;
694 }
695#undef addv
696}
aafc2e2f
BJ
697printhdr()
698{
699 char *hdr;
700
701 if (sflg+lflg+vflg+uflg > 1) {
702 fprintf(stderr, "ps: specify only one of s,l,v and u\n");
703 exit(1);
704 }
3180e1ce
KM
705 if (lflg) {
706 if (nflg)
707 wcwidth = 6;
708 else if (twidth > WTSIZ)
709 wcwidth = -WNAMESIZ;
710 else
711 wcwidth = -WSNAMESIZ;
712 if ((hdr = malloc(strlen(lhdr) + WNAMESIZ)) == NULL) {
713 fprintf(stderr, "ps: out of memory\n");
714 exit(1);
715 }
6521d648 716 (void)sprintf(hdr, lhdr, wcwidth, "WCHAN");
3180e1ce
KM
717 } else if (vflg)
718 hdr = vhdr;
719 else if (uflg) {
720 /* add enough on so that it can hold the sprintf below */
721 if ((hdr = malloc(strlen(uhdr) + 10)) == NULL) {
722 fprintf(stderr, "ps: out of memory\n");
723 exit(1);
724 }
6521d648 725 (void)sprintf(hdr, uhdr, nflg ? " UID" : "USER ");
3180e1ce
KM
726 } else
727 hdr = shdr;
aafc2e2f 728 if (lflg+vflg+uflg+sflg == 0)
c67277e8 729 hdr += strlen("SSIZ ");
aafc2e2f
BJ
730 cmdstart = strlen(hdr);
731 printf("%s COMMAND\n", hdr);
3d9f6a35 732 (void) fflush(stdout);
aafc2e2f
BJ
733}
734
735cantread(what, fromwhat)
736 char *what, *fromwhat;
737{
738
25659ede 739 fprintf(stderr, "ps: error reading %s from %s\n", what, fromwhat);
aafc2e2f
BJ
740}
741
3d9f6a35 742struct direct *dbuf;
aafc2e2f
BJ
743int dialbase;
744
745getdev()
746{
3d9f6a35 747 register DIR *df;
3bc0950e
KM
748 struct ttys *t;
749 struct lttys *lt;
aafc2e2f 750
a5ae2576
KB
751 if (chdir(_PATH_DEV) < 0) {
752 perror(_PATH_DEV);
e8807835
RC
753 exit(1);
754 }
aafc2e2f 755 dialbase = -1;
3d9f6a35 756 if ((df = opendir(".")) == NULL) {
a5ae2576 757 fprintf(stderr, "ps: can't open . in %s\n", _PATH_DEV);
aafc2e2f
BJ
758 exit(1);
759 }
3d9f6a35
KM
760 while ((dbuf = readdir(df)) != NULL)
761 maybetty();
762 closedir(df);
3bc0950e
KM
763 allttys = (struct ttys *)malloc(sizeof(struct ttys)*nttys);
764 if (allttys == NULL) {
a5ae2576 765 fprintf(stderr, "ps: can't malloc space for tty table\n");
3bc0950e
KM
766 exit(1);
767 }
768 for (lt = lallttys, t = allttys; lt ; lt = lt->next, t++)
769 *t = lt->ttys;
aafc2e2f
BJ
770}
771
772/*
773 * Attempt to avoid stats by guessing minor device
774 * numbers from tty names. Console is known,
775 * know that r(hp|up|mt) are unlikely as are different mem's,
776 * floppy, null, tty, etc.
777 */
778maybetty()
779{
3d9f6a35 780 register char *cp = dbuf->d_name;
3bc0950e
KM
781 static struct lttys *dp;
782 struct lttys *olddp;
aafc2e2f
BJ
783 int x;
784 struct stat stb;
785
786 switch (cp[0]) {
787
788 case 'c':
789 if (!strcmp(cp, "console")) {
790 x = 0;
791 goto donecand;
792 }
793 /* cu[la]? are possible!?! don't rule them out */
794 break;
795
796 case 'd':
797 if (!strcmp(cp, "drum"))
3d9f6a35 798 return;
aafc2e2f
BJ
799 break;
800
801 case 'f':
802 if (!strcmp(cp, "floppy"))
3d9f6a35 803 return;
aafc2e2f
BJ
804 break;
805
806 case 'k':
807 cp++;
808 if (*cp == 'U')
809 cp++;
810 goto trymem;
811
812 case 'r':
813 cp++;
aafc2e2f 814#define is(a,b) cp[0] == 'a' && cp[1] == 'b'
ceb20920
MK
815 if (is(h,p) || is(r,a) || is(u,p) || is(h,k)
816 || is(r,b) || is(m,t)) {
aafc2e2f
BJ
817 cp += 2;
818 if (isdigit(*cp) && cp[2] == 0)
3d9f6a35 819 return;
aafc2e2f
BJ
820 }
821 break;
822
823 case 'm':
824trymem:
825 if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0)
3d9f6a35 826 return;
3bbec3da 827 if (cp[0] == 'm' && cp[1] == 't')
3d9f6a35 828 return;
aafc2e2f
BJ
829 break;
830
831 case 'n':
832 if (!strcmp(cp, "null"))
3d9f6a35 833 return;
ceb20920
MK
834 if (!strncmp(cp, "nrmt", 4))
835 return;
836 break;
837
838 case 'p':
839 if (cp[1] && cp[1] == 't' && cp[2] == 'y')
840 return;
aafc2e2f
BJ
841 break;
842
843 case 'v':
844 if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) &&
845 cp[3] == 0)
3d9f6a35 846 return;
aafc2e2f
BJ
847 break;
848 }
3d9f6a35 849 cp = dbuf->d_name + dbuf->d_namlen - 1;
aafc2e2f
BJ
850 x = 0;
851 if (cp[-1] == 'd') {
852 if (dialbase == -1) {
853 if (stat("ttyd0", &stb) == 0)
854 dialbase = stb.st_rdev & 017;
855 else
856 dialbase = -2;
857 }
858 if (dialbase == -2)
859 x = 0;
860 else
861 x = 11;
862 }
3d9f6a35 863 if (cp > dbuf->d_name && isdigit(cp[-1]) && isdigit(*cp))
aafc2e2f
BJ
864 x += 10 * (cp[-1] - ' ') + cp[0] - '0';
865 else if (*cp >= 'a' && *cp <= 'f')
866 x += 10 + *cp - 'a';
867 else if (isdigit(*cp))
868 x += *cp - '0';
869 else
870 x = -1;
871donecand:
3bc0950e
KM
872 olddp = dp;
873 dp = (struct lttys *)malloc(sizeof(struct lttys));
874 if (dp == NULL) {
875 fprintf(stderr, "ps: Can't malloc space for tty table\n");
e8807835
RC
876 exit(1);
877 }
3bc0950e
KM
878 if (lallttys == NULL)
879 lallttys = dp;
880 nttys++;
881 if (olddp)
882 olddp->next = dp;
883 dp->next = NULL;
884 (void) strcpy(dp->ttys.name, dbuf->d_name);
e8807835 885 if (Uflg) {
3bc0950e 886 if (stat(dp->ttys.name, &stb) == 0 &&
e8807835 887 (stb.st_mode&S_IFMT)==S_IFCHR)
3bc0950e 888 dp->ttys.ttyd = x = stb.st_rdev;
e8807835
RC
889 else {
890 nttys--;
3bc0950e
KM
891 if (lallttys == dp)
892 lallttys = NULL;
893 free(dp);
894 dp = olddp;
895 if (dp)
896 dp->next = NULL;
e8807835
RC
897 return;
898 }
899 } else
3bc0950e 900 dp->ttys.ttyd = -1;
aafc2e2f
BJ
901 if (x == -1)
902 return;
903 x &= 017;
3bc0950e
KM
904 dp->ttys.cand = cand[x];
905 cand[x] = nttys-1;
aafc2e2f
BJ
906}
907
908char *
909gettty()
910{
911 register char *p;
912 register struct ttys *dp;
913 struct stat stb;
914 int x;
915
916 if (u.u_ttyp == 0)
d0ba9285 917 return(" ?");
aafc2e2f 918 x = u.u_ttyd & 017;
3bc0950e
KM
919 for (dp = &allttys[cand[x]]; dp != &allttys[-1];
920 dp = &allttys[dp->cand]) {
aafc2e2f 921 if (dp->ttyd == -1) {
c67277e8
BJ
922 if (stat(dp->name, &stb) == 0 &&
923 (stb.st_mode&S_IFMT)==S_IFCHR)
aafc2e2f
BJ
924 dp->ttyd = stb.st_rdev;
925 else
926 dp->ttyd = -2;
927 }
928 if (dp->ttyd == u.u_ttyd)
929 goto found;
930 }
931 /* ick */
e8807835 932 for (dp = allttys; dp < &allttys[nttys]; dp++) {
aafc2e2f 933 if (dp->ttyd == -1) {
3bbec3da
BJ
934 if (stat(dp->name, &stb) == 0 &&
935 (stb.st_mode&S_IFMT)==S_IFCHR)
aafc2e2f
BJ
936 dp->ttyd = stb.st_rdev;
937 else
938 dp->ttyd = -2;
939 }
940 if (dp->ttyd == u.u_ttyd)
941 goto found;
942 }
943 return ("?");
944found:
945 p = dp->name;
946 if (p[0]=='t' && p[1]=='t' && p[2]=='y')
947 p += 3;
948 return (p);
949}
950
951save()
952{
953 register struct savcom *sp;
954 register struct asav *ap;
955 register char *cp;
0f0e0052 956 register struct text *xp;
aafc2e2f
BJ
957 char *ttyp, *cmdp;
958
959 if (mproc->p_stat != SZOMB && getu() == 0)
960 return;
961 ttyp = gettty();
133a0b3b 962 if (xflg == 0 && ttyp[0] == '?' || tptr && strncmp(tptr, ttyp, 2))
aafc2e2f
BJ
963 return;
964 sp = &savcom[npr];
965 cmdp = getcmd();
966 if (cmdp == 0)
967 return;
e8807835 968 sp->ap = ap = (struct asav *)calloc(1, sizeof (struct asav));
aafc2e2f
BJ
969 sp->ap->a_cmdp = cmdp;
970#define e(a,b) ap->a = mproc->b
971 e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice);
0f0e0052 972 e(a_uid, p_uid); e(a_pid, p_pid); e(a_pri, p_pri);
c67277e8 973 e(a_slptime, p_slptime); e(a_time, p_time);
aafc2e2f
BJ
974 ap->a_tty[0] = ttyp[0];
975 ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' ';
976 if (ap->a_stat == SZOMB) {
b1198826 977 ap->a_cpu = 0;
aafc2e2f
BJ
978 } else {
979 ap->a_size = mproc->p_dsize + mproc->p_ssize;
0f0e0052 980 e(a_rss, p_rssize);
aafc2e2f 981 ap->a_ttyd = u.u_ttyd;
b1198826 982 ap->a_cpu = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
1fb6a666 983 if (sumcpu)
b1198826 984 ap->a_cpu += u.u_cru.ru_utime.tv_sec + u.u_cru.ru_stime.tv_sec;
b2867a35 985 if (mproc->p_textp && text) {
bdb1f95f 986 xp = &text[mproc->p_textp - atext];
0f0e0052
BJ
987 ap->a_tsiz = xp->x_size;
988 ap->a_txtrss = xp->x_rssize;
989 ap->a_xccount = xp->x_ccount;
990 }
aafc2e2f 991 }
0f0e0052 992#undef e
79de1ed3 993 ap->a_maxrss = mproc->p_maxrss;
aafc2e2f
BJ
994 if (lflg) {
995 register struct lsav *lp;
996
e8807835
RC
997 sp->s_un.lp = lp = (struct lsav *)
998 calloc(1, sizeof (struct lsav));
aafc2e2f 999#define e(a,b) lp->a = mproc->b
c67277e8 1000 e(l_ppid, p_ppid); e(l_cpu, p_cpu);
aafc2e2f
BJ
1001 if (ap->a_stat != SZOMB)
1002 e(l_wchan, p_wchan);
1003#undef e
1004 lp->l_addr = pcbpf;
1005 } else if (vflg) {
1006 register struct vsav *vp;
aafc2e2f 1007
e8807835
RC
1008 sp->s_un.vp = vp = (struct vsav *)
1009 calloc(1, sizeof (struct vsav));
aafc2e2f 1010#define e(a,b) vp->a = mproc->b
aafc2e2f 1011 if (ap->a_stat != SZOMB) {
7f0fa372 1012 e(v_swrss, p_swrss);
b1198826 1013 vp->v_majflt = u.u_ru.ru_majflt;
0f0e0052 1014 if (mproc->p_textp)
aafc2e2f 1015 vp->v_txtswrss = xp->x_swrss;
aafc2e2f 1016 }
7f0fa372 1017 vp->v_pctcpu = pcpu();
aafc2e2f 1018#undef e
066ec2ef
SL
1019 } else if (uflg)
1020 sp->s_un.u_pctcpu = pcpu();
1021 else if (sflg) {
aafc2e2f
BJ
1022 if (ap->a_stat != SZOMB) {
1023 for (cp = (char *)u.u_stack;
bdb1f95f 1024 cp < &user.upages[UPAGES][0]; )
aafc2e2f
BJ
1025 if (*cp++)
1026 break;
066ec2ef 1027 sp->s_un.s_ssiz = (&user.upages[UPAGES][0] - cp);
aafc2e2f
BJ
1028 }
1029 }
133a0b3b 1030
aafc2e2f
BJ
1031 npr++;
1032}
1033
0f0e0052
BJ
1034double
1035pmem(ap)
1036 register struct asav *ap;
1037{
1038 double fracmem;
1039 int szptudot;
1040
1041 if ((ap->a_flag&SLOAD) == 0)
1042 fracmem = 0.0;
1043 else {
1044 szptudot = UPAGES + clrnd(ctopt(ap->a_size+ap->a_tsiz));
1045 fracmem = ((float)ap->a_rss+szptudot)/CLSIZE/ecmx;
1046 if (ap->a_xccount)
1047 fracmem += ((float)ap->a_txtrss)/CLSIZE/
1048 ap->a_xccount/ecmx;
1049 }
1050 return (100.0 * fracmem);
1051}
1052
8590462f 1053#define fxtofl(fixpt) ((double) fixpt / fscale)
7f0fa372
BJ
1054double
1055pcpu()
1056{
0f0e0052 1057 time_t time;
7f0fa372 1058
0f0e0052
BJ
1059 time = mproc->p_time;
1060 if (time == 0 || (mproc->p_flag&SLOAD) == 0)
7f0fa372 1061 return (0.0);
0f0e0052 1062 if (rawcpu)
8590462f
KM
1063 return (100.0 * fxtofl(mproc->p_pctcpu));
1064 return (100.0 * fxtofl(mproc->p_pctcpu) /
1065 (1.0 - exp(time * log(fxtofl(ccpu)))));
7f0fa372 1066}
8590462f 1067#undef fxtofl
7f0fa372 1068
aafc2e2f
BJ
1069getu()
1070{
f700a7ee 1071 struct pte *pteaddr, apte;
f700a7ee 1072 struct pte arguutl[UPAGES+CLSIZE];
aafc2e2f
BJ
1073 register int i;
1074 int ncl, size;
1075
1076 size = sflg ? ctob(UPAGES) : sizeof (struct user);
1077 if ((mproc->p_flag & SLOAD) == 0) {
25659ede
BJ
1078 if (swap < 0)
1079 return (0);
066ec2ef 1080 (void) lseek(swap, (long)dtob(mproc->p_swaddr), 0);
aafc2e2f
BJ
1081 if (read(swap, (char *)&user.user, size) != size) {
1082 fprintf(stderr, "ps: cant read u for pid %d from %s\n",
1083 mproc->p_pid, swapf);
1084 return (0);
1085 }
1086 pcbpf = 0;
1087 argaddr = 0;
1088 return (1);
1089 }
e8807835 1090 pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
3d9f6a35 1091 klseek(kmem, (long)pteaddr, 0);
aafc2e2f
BJ
1092 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
1093 printf("ps: cant read indir pte to get u for pid %d from %s\n",
e8807835 1094 mproc->p_pid, kmemf);
aafc2e2f
BJ
1095 return (0);
1096 }
e8807835 1097 lseek(mem,
3d9f6a35
KM
1098 (long)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte),
1099 0);
aafc2e2f
BJ
1100 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
1101 printf("ps: cant read page table for u of pid %d from %s\n",
e8807835 1102 mproc->p_pid, memf);
aafc2e2f
BJ
1103 return (0);
1104 }
1105 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
1106 argaddr = ctob(arguutl[0].pg_pfnum);
1107 else
1108 argaddr = 0;
1109 pcbpf = arguutl[CLSIZE].pg_pfnum;
1110 ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
1111 while (--ncl >= 0) {
1112 i = ncl * CLSIZE;
e8807835 1113 lseek(mem, (long)ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
aafc2e2f
BJ
1114 if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
1115 printf("ps: cant read page %d of u of pid %d from %s\n",
1116 arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
1117 return(0);
1118 }
1119 }
1120 return (1);
1121}
1122
1123char *
1124getcmd()
1125{
066ec2ef 1126 char cmdbuf[CLSIZE*NBPG];
aafc2e2f
BJ
1127 union {
1128 char argc[CLSIZE*NBPG];
1129 int argi[CLSIZE*NBPG/sizeof (int)];
1130 } argspac;
1131 register char *cp;
1132 register int *ip;
1133 char c;
1134 int nbad;
1135 struct dblock db;
25659ede 1136 char *file;
aafc2e2f
BJ
1137
1138 if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT))
1139 return ("");
1140 if (cflg) {
3d9f6a35 1141 (void) strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm));
aafc2e2f
BJ
1142 return (savestr(cmdbuf));
1143 }
1144 if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) {
25659ede
BJ
1145 if (swap < 0)
1146 goto retucomm;
aafc2e2f 1147 vstodb(0, CLSIZE, &u.u_smap, &db, 1);
066ec2ef 1148 (void) lseek(swap, (long)dtob(db.db_base), 0);
aafc2e2f
BJ
1149 if (read(swap, (char *)&argspac, sizeof(argspac))
1150 != sizeof(argspac))
1151 goto bad;
25659ede 1152 file = swapf;
aafc2e2f 1153 } else {
e8807835 1154 lseek(mem, (long)argaddr, 0);
aafc2e2f
BJ
1155 if (read(mem, (char *)&argspac, sizeof (argspac))
1156 != sizeof (argspac))
1157 goto bad;
25659ede 1158 file = memf;
aafc2e2f
BJ
1159 }
1160 ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)];
1161 ip -= 2; /* last arg word and .long 0 */
1162 while (*--ip)
1163 if (ip == argspac.argi)
1164 goto retucomm;
1165 *(char *)ip = ' ';
1166 ip++;
1167 nbad = 0;
1168 for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) {
1169 c = *cp & 0177;
1170 if (c == 0)
1171 *cp = ' ';
1172 else if (c < ' ' || c > 0176) {
1173 if (++nbad >= 5*(eflg+1)) {
1174 *cp++ = ' ';
1175 break;
1176 }
1177 *cp = '?';
1178 } else if (eflg == 0 && c == '=') {
1179 while (*--cp != ' ')
1180 if (cp <= (char *)ip)
1181 break;
1182 break;
1183 }
1184 }
1185 *cp = 0;
1186 while (*--cp == ' ')
1187 *cp = 0;
1188 cp = (char *)ip;
3d9f6a35 1189 (void) strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp);
aafc2e2f 1190 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
3d9f6a35
KM
1191 (void) strcat(cmdbuf, " (");
1192 (void) strncat(cmdbuf, u.u_comm, sizeof(u.u_comm));
1193 (void) strcat(cmdbuf, ")");
aafc2e2f 1194 }
aafc2e2f
BJ
1195 return (savestr(cmdbuf));
1196
1197bad:
25659ede
BJ
1198 fprintf(stderr, "ps: error locating command name for pid %d from %s\n",
1199 mproc->p_pid, file);
aafc2e2f 1200retucomm:
3d9f6a35
KM
1201 (void) strcpy(cmdbuf, " (");
1202 (void) strncat(cmdbuf, u.u_comm, sizeof (u.u_comm));
1203 (void) strcat(cmdbuf, ")");
aafc2e2f
BJ
1204 return (savestr(cmdbuf));
1205}
1206
1207char *lhdr =
f7e0c418 1208" F UID PID PPID CP PRI NI ADDR SZ RSS %*sSTAT TT TIME";
aafc2e2f
BJ
1209lpr(sp)
1210 struct savcom *sp;
1211{
1212 register struct asav *ap = sp->ap;
066ec2ef 1213 register struct lsav *lp = sp->s_un.lp;
aafc2e2f 1214
f7e0c418 1215 printf("%7x %4d %5u %5u %2d %3d %2d %4x %5d %4d",
ed325f47
MK
1216 (ap->a_flag &~ SPTECHG), /* XXX */
1217 ap->a_uid, ap->a_pid, lp->l_ppid,
1218 lp->l_cpu > 99 ? 99 : lp->l_cpu, ap->a_pri-PZERO,
1219 ap->a_nice, lp->l_addr, pgtok(ap->a_size), pgtok(ap->a_rss));
3180e1ce
KM
1220 if (lp->l_wchan == 0)
1221 printf(" %*s", wcwidth, "");
1222 else if (nflg)
1c9d8eec 1223 printf(" %*x", wcwidth, (int)lp->l_wchan&~KERNBASE);
3180e1ce
KM
1224 else
1225 printf(" %*.*s", wcwidth, abs(wcwidth), getchan(lp->l_wchan));
d0ba9285 1226 printf(" %-2.3s ", state(ap));
aafc2e2f
BJ
1227 ptty(ap->a_tty);
1228 ptime(ap);
1229}
1230
1231ptty(tp)
1232 char *tp;
1233{
1234
c67277e8 1235 printf("%-2.2s", tp);
aafc2e2f
BJ
1236}
1237
1238ptime(ap)
1239 struct asav *ap;
1240{
1241
d0ba9285 1242 printf(" %3ld:%02ld", ap->a_cpu / 60, ap->a_cpu % 60);
aafc2e2f
BJ
1243}
1244
1245char *uhdr =
1c9d8eec 1246"%s PID %%CPU %%MEM SZ RSS TT STAT TIME";
aafc2e2f
BJ
1247upr(sp)
1248 struct savcom *sp;
1249{
1250 register struct asav *ap = sp->ap;
0f0e0052
BJ
1251 int vmsize, rmsize;
1252
066ec2ef
SL
1253 vmsize = pgtok((ap->a_size + ap->a_tsiz));
1254 rmsize = pgtok(ap->a_rss);
0f0e0052 1255 if (ap->a_xccount)
066ec2ef 1256 rmsize += pgtok(ap->a_txtrss/ap->a_xccount);
3180e1ce
KM
1257 if (nflg)
1258 printf("%4d ", ap->a_uid);
1259 else
1260 printf("%-8.8s ", getname(ap->a_uid));
1c9d8eec 1261 printf("%5d %4.1f %4.1f %5d %5d",
3180e1ce 1262 ap->a_pid, sp->s_un.u_pctcpu, pmem(ap), vmsize, rmsize);
c67277e8 1263 putchar(' ');
aafc2e2f 1264 ptty(ap->a_tty);
d0ba9285 1265 printf(" %-2.3s", state(ap));
aafc2e2f
BJ
1266 ptime(ap);
1267}
1268
1269char *vhdr =
1c9d8eec 1270" SIZE PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM TSIZ TRS %CPU %MEM"+5;
aafc2e2f
BJ
1271vpr(sp)
1272 struct savcom *sp;
1273{
066ec2ef 1274 register struct vsav *vp = sp->s_un.vp;
aafc2e2f 1275 register struct asav *ap = sp->ap;
c67277e8 1276
0f0e0052 1277 printf("%5u ", ap->a_pid);
c67277e8 1278 ptty(ap->a_tty);
d0ba9285 1279 printf(" %-2.3s", state(ap));
c67277e8 1280 ptime(ap);
1c9d8eec 1281 printf(" %2d %2d %6d %5d %5d",
79de1ed3
BJ
1282 ap->a_slptime > 99 ? 99 : ap-> a_slptime,
1283 ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt,
066ec2ef
SL
1284 pgtok(ap->a_size), pgtok(ap->a_rss));
1285 if (ap->a_maxrss == (RLIM_INFINITY/NBPG))
3baf21ed 1286 printf(" xx");
79de1ed3 1287 else
1c9d8eec
MK
1288 printf(" %5d", pgtok(ap->a_maxrss));
1289 printf(" %4d %3d %4.1f %4.1f",
066ec2ef 1290 pgtok(ap->a_tsiz), pgtok(ap->a_txtrss), vp->v_pctcpu, pmem(ap));
c67277e8
BJ
1291}
1292
1293char *shdr =
0f0e0052 1294"SSIZ PID TT STAT TIME";
c67277e8
BJ
1295spr(sp)
1296 struct savcom *sp;
1297{
1298 register struct asav *ap = sp->ap;
1299
1300 if (sflg)
066ec2ef 1301 printf("%4d ", sp->s_un.s_ssiz);
c67277e8
BJ
1302 printf("%5u", ap->a_pid);
1303 putchar(' ');
1304 ptty(ap->a_tty);
d0ba9285 1305 printf(" %-2.3s", state(ap));
c67277e8
BJ
1306 ptime(ap);
1307}
1308
1309char *
1310state(ap)
1311 register struct asav *ap;
1312{
c67277e8 1313 static char res[5];
1c9d8eec 1314 char *cp = res;
aafc2e2f
BJ
1315
1316 switch (ap->a_stat) {
1317
aafc2e2f 1318 case SSTOP:
1c9d8eec 1319 *cp = 'T';
c67277e8
BJ
1320 break;
1321
1322 case SSLEEP:
1323 if (ap->a_pri >= PZERO)
1324 if (ap->a_slptime >= MAXSLP)
1c9d8eec 1325 *cp = 'I';
c67277e8 1326 else
1c9d8eec 1327 *cp = 'S';
aafc2e2f 1328 else if (ap->a_flag & SPAGE)
1c9d8eec 1329 *cp = 'P';
aafc2e2f 1330 else
1c9d8eec 1331 *cp = 'D';
aafc2e2f
BJ
1332 break;
1333
c67277e8 1334 case SWAIT:
aafc2e2f
BJ
1335 case SRUN:
1336 case SIDL:
1c9d8eec 1337 *cp = 'R';
c67277e8
BJ
1338 break;
1339
1340 case SZOMB:
1c9d8eec 1341 *cp = 'Z';
aafc2e2f 1342 break;
c67277e8
BJ
1343
1344 default:
1c9d8eec 1345 *cp = '?';
aafc2e2f 1346 }
1c9d8eec
MK
1347 cp++;
1348 if (ap->a_flag & SLOAD) {
1349 if (ap->a_rss > ap->a_maxrss)
1350 *cp++ = '>';
1351 } else
1352 *cp++ = 'W';
0f0e0052 1353 if (ap->a_nice < NZERO)
1c9d8eec 1354 *cp++ = '<';
0f0e0052 1355 else if (ap->a_nice > NZERO)
1c9d8eec
MK
1356 *cp++ = 'N';
1357 if (ap->a_flag & SUANOM)
1358 *cp++ = 'A';
1359 else if (ap->a_flag & SSEQL)
1360 *cp++ = 'S';
6d66a7a5 1361 *cp = '\0';
c67277e8 1362 return (res);
aafc2e2f
BJ
1363}
1364
1365/*
1366 * Given a base/size pair in virtual swap area,
1367 * return a physical base/size pair which is the
1368 * (largest) initial, physically contiguous block.
1369 */
1370vstodb(vsbase, vssize, dmp, dbp, rev)
1371 register int vsbase;
1372 int vssize;
1373 struct dmap *dmp;
1374 register struct dblock *dbp;
1375{
b38b1b3a 1376 register int blk = dmmin;
aafc2e2f
BJ
1377 register swblk_t *ip = dmp->dm_map;
1378
066ec2ef
SL
1379 vsbase = ctod(vsbase);
1380 vssize = ctod(vssize);
aafc2e2f
BJ
1381 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
1382 panic("vstodb");
1383 while (vsbase >= blk) {
1384 vsbase -= blk;
b38b1b3a 1385 if (blk < dmmax)
aafc2e2f
BJ
1386 blk *= 2;
1387 ip++;
1388 }
1389 if (*ip <= 0 || *ip + blk > nswap)
1390 panic("vstodb *ip");
1391 dbp->db_size = min(vssize, blk - vsbase);
1392 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
1393}
1394
1395/*ARGSUSED*/
1396panic(cp)
1397 char *cp;
1398{
1399
1400#ifdef DEBUG
1401 printf("%s\n", cp);
1402#endif
1403}
1404
1405min(a, b)
1406{
1407
1408 return (a < b ? a : b);
1409}
1410
1411pscomp(s1, s2)
1412 struct savcom *s1, *s2;
1413{
1414 register int i;
1415
066ec2ef
SL
1416 if (uflg)
1417 return (s2->s_un.u_pctcpu > s1->s_un.u_pctcpu ? 1 : -1);
aafc2e2f
BJ
1418 if (vflg)
1419 return (vsize(s2) - vsize(s1));
1420 i = s1->ap->a_ttyd - s2->ap->a_ttyd;
1421 if (i == 0)
1422 i = s1->ap->a_pid - s2->ap->a_pid;
1423 return (i);
1424}
1425
1426vsize(sp)
1427 struct savcom *sp;
1428{
1429 register struct asav *ap = sp->ap;
066ec2ef 1430 register struct vsav *vp = sp->s_un.vp;
aafc2e2f
BJ
1431
1432 if (ap->a_flag & SLOAD)
1433 return (ap->a_rss +
0f0e0052
BJ
1434 ap->a_txtrss / (ap->a_xccount ? ap->a_xccount : 1));
1435 return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss));
aafc2e2f
BJ
1436}
1437
c223880f 1438#include <utmp.h>
aafc2e2f 1439
c223880f
JB
1440struct utmp utmp;
1441#define NMAX (sizeof (utmp.ut_name))
1442#define SCPYN(a, b) strncpy(a, b, NMAX)
60b23435 1443
c223880f
JB
1444#define NUID 64
1445
1446struct ncache {
1447 int uid;
1448 char name[NMAX+1];
1449} nc[NUID];
aafc2e2f 1450
c223880f
JB
1451/*
1452 * This function assumes that the password file is hashed
1453 * (or some such) to allow fast access based on a uid key.
1454 */
aafc2e2f
BJ
1455char *
1456getname(uid)
1457{
c223880f
JB
1458 register struct passwd *pw;
1459 struct passwd *getpwent();
1460 register int cp;
a5ae2576 1461#ifdef notdef
c223880f
JB
1462 extern int _pw_stayopen;
1463
1464 _pw_stayopen = 1;
a5ae2576 1465#endif
c223880f
JB
1466
1467#if (((NUID) & ((NUID) - 1)) != 0)
1468 cp = uid % (NUID);
1469#else
1470 cp = uid & ((NUID) - 1);
1471#endif
1472 if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0])
1473 return (nc[cp].name);
1474 pw = getpwuid(uid);
1475 if (!pw)
1476 return (0);
1477 nc[cp].uid = uid;
1478 SCPYN(nc[cp].name, pw->pw_name);
1479 return (nc[cp].name);
aafc2e2f
BJ
1480}
1481
1482char *
1483savestr(cp)
1484 char *cp;
1485{
e8807835 1486 register unsigned len;
aafc2e2f
BJ
1487 register char *dp;
1488
1489 len = strlen(cp);
e8807835 1490 dp = (char *)calloc(len+1, sizeof (char));
3d9f6a35 1491 (void) strcpy(dp, cp);
aafc2e2f
BJ
1492 return (dp);
1493}
e8807835
RC
1494
1495/*
1496 * This routine was stolen from adb to simulate memory management
1497 * on the VAX.
1498 */
1499off_t
1500vtophys(loc)
1501long loc;
1502{
1503 register p;
1504 off_t newloc;
1505
f20270fc 1506 newloc = loc & ~KERNBASE;
e8807835 1507 p = btop(newloc);
f20270fc 1508 if ((loc & KERNBASE) == 0) {
e8807835
RC
1509 fprintf(stderr, "Vtophys: translating non-kernel address\n");
1510 return((off_t) -1);
1511 }
1512 if (p >= Syssize) {
1513 fprintf(stderr, "Vtophys: page out of bound (%d>=%d)\n",
1514 p, Syssize);
1515 return((off_t) -1);
1516 }
1517 if (Sysmap[p].pg_v == 0
1518 && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) {
1519 fprintf(stderr, "Vtophys: page not valid\n");
1520 return((off_t) -1);
1521 }
1522 loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET));
1523 return(loc);
1524}
3180e1ce
KM
1525
1526/*
1527 * since we can't init unions, the cleanest way to use a.out.h instead
1528 * of nlist.h (required since nlist() uses some defines) is to do a
1529 * runtime copy into the nl array -- sigh
1530 */
1531init_nlist()
1532{
1533 register struct nlist *np;
1534 register char **namep;
1535
1536 nllen = sizeof nl_names / sizeof (char *);
1537 np = nl = (struct nlist *) malloc(nllen * sizeof (struct nlist));
1538 if (np == NULL) {
1539 fprintf(stderr, "ps: out of memory allocating namelist\n");
1540 exit(1);
1541 }
1542 namep = &nl_names[0];
1543 while (nllen > 0) {
1544 np->n_un.n_name = *namep;
1545 if (**namep == '\0')
1546 break;
1547 namep++;
1548 np++;
1549 }
1550}
1551
1552/*
1553 * nlist - retreive attributes from name list (string table version)
1554 * modified to add wait channels - Charles R. LaBrec 8/85
1555 */
1556nlist(name, list)
1557 char *name;
1558 struct nlist *list;
1559{
1560 register struct nlist *p, *q;
1561 register char *s1, *s2;
1562 register n, m;
1563 int maxlen, nreq;
1564 FILE *f;
1565 FILE *sf;
1566 off_t sa; /* symbol address */
1567 off_t ss; /* start of strings */
1568 int type;
1569 struct exec buf;
1570 struct nlist space[BUFSIZ/sizeof (struct nlist)];
1571 char nambuf[BUFSIZ];
1572
1573 maxlen = 0;
1574 for (q = list, nreq = 0; q->n_un.n_name && q->n_un.n_name[0]; q++, nreq++) {
1575 q->n_type = 0;
1576 q->n_value = 0;
1577 q->n_desc = 0;
1578 q->n_other = 0;
1579 n = strlen(q->n_un.n_name);
1580 if (n > maxlen)
1581 maxlen = n;
1582 }
1583 f = fopen(name, "r");
1584 if (f == NULL)
1585 return (-1);
1586 fread((char *)&buf, sizeof buf, 1, f);
1587 if (N_BADMAG(buf)) {
1588 fclose(f);
1589 return (-1);
1590 }
1591 sf = fopen(name, "r");
1592 if (sf == NULL) {
1593 /* ??? */
1594 fclose(f);
1595 return(-1);
1596 }
1597 sa = N_SYMOFF(buf);
1598 ss = sa + buf.a_syms;
1599 n = buf.a_syms;
1600 fseek(f, sa, 0);
1601 while (n) {
1602 m = sizeof (space);
1603 if (n < m)
1604 m = n;
1605 if (fread((char *)space, m, 1, f) != 1)
1606 break;
1607 n -= m;
1608 for (q = space; (m -= sizeof(struct nlist)) >= 0; q++) {
1609 if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
1610 continue;
1611 /*
1612 * since we know what type of symbols we will get,
1613 * we can make a quick check here -- crl
1614 */
1615 type = q->n_type & (N_TYPE | N_EXT);
1616 if ((q->n_type & N_TYPE) != N_ABS
1617 && type != (N_EXT | N_DATA)
1618 && type != (N_EXT | N_BSS))
1619 continue;
1620 fseek(sf, ss+q->n_un.n_strx, 0);
1621 fread(nambuf, maxlen+1, 1, sf);
1622 /* if using wchans, add it to the list of channels */
1623 if (!nflg)
1624 addchan(&nambuf[1], (caddr_t) q->n_value);
1625 for (p = list; p->n_un.n_name && p->n_un.n_name[0]; p++) {
1626 s1 = p->n_un.n_name;
1627 s2 = nambuf;
1628 if (strcmp(p->n_un.n_name, nambuf) == 0) {
1629 p->n_value = q->n_value;
1630 p->n_type = q->n_type;
1631 p->n_desc = q->n_desc;
1632 p->n_other = q->n_other;
1633 --nreq;
1634 break;
1635 }
1636 }
1637 }
1638 }
1639alldone:
1640 fclose(f);
1641 fclose(sf);
1642 return (nreq);
1643}
1644
1645/*
1646 * add the given channel to the channel list
1647 */
1648addchan(name, caddr)
1649char *name;
1650caddr_t caddr;
1651{
1652 static int left = 0;
1653 register struct wchan *wp;
1654 register char **p;
1655
1656 for (p = wchan_stop_list; *p; p++) {
1657 if (**p != *name) /* quick check first */
1658 continue;
1659 if (strncmp(name, *p, WNAMESIZ) == 0)
1660 return; /* if found, don't add */
1661 }
1662 if (left == 0) {
1663 if (wchanhd) {
1664 left = 100;
1665 wchanhd = (struct wchan *) realloc(wchanhd,
1666 (nchans + left) * sizeof (struct wchan));
1667 } else {
1668 left = 600;
1669 wchanhd = (struct wchan *) malloc(left
1670 * sizeof (struct wchan));
1671 }
1672 if (wchanhd == NULL) {
1673 fprintf(stderr, "ps: out of memory allocating wait channels\n");
1674 nflg++;
1675 return;
1676 }
1677 }
1678 left--;
1679 wp = &wchanhd[nchans++];
1680 strncpy(wp->wc_name, name, WNAMESIZ);
1681 wp->wc_name[WNAMESIZ] = '\0';
1682 wp->wc_caddr = caddr;
1683}
1684
1685/*
1686 * returns the symbolic wait channel corresponding to chan
1687 */
1688char *
1689getchan(chan)
1690register caddr_t chan;
1691{
1692 register i, iend;
1693 register char *prevsym;
1694 register struct wchan *wp;
1695
1696 prevsym = "???"; /* nothing, to begin with */
1697 if (chan) {
1698 for (i = 0; i < NWCINDEX; i++)
1699 if ((unsigned) chan < (unsigned) wchan_index[i])
1700 break;
1701 iend = i--;
1702 if (i < 0) /* can't be found */
1703 return prevsym;
1704 iend *= nchans;
1705 iend /= NWCINDEX;
1706 i *= nchans;
1707 i /= NWCINDEX;
1708 wp = &wchanhd[i];
1709 for ( ; i < iend; i++, wp++) {
1710 if ((unsigned) wp->wc_caddr > (unsigned) chan)
1711 break;
1712 prevsym = wp->wc_name;
1713 }
1714 }
1715 return prevsym;
1716}
1717
1718/*
1719 * used in sorting the wait channel array
1720 */
1721int
1722wchancomp (w1, w2)
1723struct wchan *w1, *w2;
1724{
1725 register unsigned c1, c2;
1726
1727 c1 = (unsigned) w1->wc_caddr;
1728 c2 = (unsigned) w2->wc_caddr;
1729 if (c1 > c2)
1730 return 1;
1731 else if (c1 == c2)
1732 return 0;
1733 else
1734 return -1;
1735}