1: #
   2: /*
   3:  ps - show process status - iiasa version (jek)
   4: 	originally from harvard and/or CULC
   5: 
   6: 	flags are single letters
   7: 	multiple flags can occur in one argument
   8: 	dashes are optional but are needed to delimit lists of things
   9: 		multiple lists are present(???)
  10: 	flags that imply other arguments read the following arguments
  11: 		until the end of the list or until an argument starts with dash
  12: 	certain flags read exactly one argument
  13: 	initialization (i flag) should be done for:
  14: 		new users,
  15: 		new kernel
  16: 	parameters here must change to indicate:
  17: 		new tty devices, max tty lines, tty letter changes
  18: 		max users
  19: 		new things to wait for
  20: 	this program should be changed if:
  21: 		proc structure makes this obsolete
  22: 		etc
  23: 	recompilation should occur if:
  24: 		kernel structures and or paramters (nproc etc.) change
  25: 		any above changes of course
  26: 
  27: 	flags are:
  28: 		a - show all processes that have pgrps except shells
  29: 		b - show background (not detached)
  30: 		c - show child times instead of process times
  31: 		d - show detached processes inherited by init
  32: 		e - show the environment with the args
  33: 		f - show foreground jobs, connected to tty
  34: 		g - show processes in given pgrps
  35: 		h - unused
  36: 		i - perform initialization (implies 'n')
  37: 		j,k - unused
  38: 		l - print long format. includes most good stuff
  39: 		m - specify different memory file (file is next arg)
  40: 		n - show no processes
  41: 		o - unused
  42: 		p - show only processes whose id's are in list (following args)
  43: 		q - unused
  44: 		r - repeat indefinitely (number of r's = seconds or r#)
  45: 		s - show stopped processes
  46: 		t - show only processes associated with ttys in list (following)
  47: 		u - show only processes (or ancestors of) for users in list
  48: 		v - be verbose - show the most information
  49: 		w - wide format, show entire argument list (up to 512 chars)
  50: 		x - show unattached processes - no pgrp. a+x gives shells also
  51: 		y - unused
  52: 		z - show zombies
  53: 		A - show ALL information possible
  54: 		B - show busy processes
  55: 		F - go fast, avoid swap space.
  56: 		G - print pgrp
  57: 		U - use different UNIX file (next arg)
  58: 		S - show size
  59: 		T - show tty information
  60: 		W - print wait channels in hex
  61: */
  62: 
  63: #include    <signal.h>
  64: #include    <h/param.h>
  65: #include    <h/dir.h>
  66: #include    <h/user.h>
  67: #include    <h/proc.h>
  68: #include    <h/pte.h>
  69: #include    <h/vm.h>
  70: #include    <h/inode.h>
  71: #include    <h/file.h>
  72: #include    <h/buf.h>
  73: #include    <h/text.h>
  74: #include    <h/tty.h>
  75: #include    <h/conf.h>
  76: #include    <nlist.h>
  77: #include    <sys/stat.h>
  78: #include    <stdio.h>
  79: #include    <pwd.h>
  80: 
  81: 
  82: #define TRUE    1
  83: #define FALSE   0
  84: #define INTPPG  (NBPG/sizeof(int))
  85: #define MAXARGPG    5
  86: 
  87: #define Usrptmap        ((struct pte *)info.kaddr[ausrptmap])
  88: #define usrpt       ((struct pte *)info.kaddr[ausrpt])
  89: #define cswitch     ((struct cdevsw *)info.kaddr[acdevsw])
  90: struct proc *proc, *kproc;
  91: struct text *text, *ktext;
  92: struct buf *buf, *swbuf;
  93: struct inode *inode;
  94: int nproc, ntext, hz, nbuf, ninode, nfile, nswbuf;
  95: union {
  96:     struct user user;
  97:     char    upages[UPAGES][NBPG];
  98: } user;
  99: int pad1;   /* supposedly to aviod hardware problem reading /dev/mem */
 100: struct pte pagetable[UPAGES + MAXARGPG];    /* for users page table */
 101: int pad2;   /* supposedly to aviod hardware problem reading /dev/mem */
 102: 
 103: #define u   user.user
 104: #define MSPID   2       /* max system pid, not to considered BUSY */
 105: 
 106: #define MAXUSERS    256 /* total different users */
 107: #define UNAMELENGTH 8   /* length of a user name */
 108: #define NSPEC       15  /* number of specified things (proc, user, tty */
 109: #define MAXTTYS     100
 110: 
 111: /* definitions to reuse uninteresting proc table entries for linked lists */
 112: 
 113: struct  procinfo    {       /* structure to use for */
 114:     char    *pi_cmd;        /* attaching a time */
 115:     struct ttyline  *pi_tty;
 116:     long    pi_time;        /* and an arg string to a proc */
 117: };
 118: 
 119: #define p_next      p_link      /* pointer to next proc in global list */
 120: #define p_bro       p_rlink     /* next process with same parent */
 121: #define p_son       p_xlink     /* first child of this process */
 122: #define pinfo(p)    (*((struct procinfo **)&p->p_sig))
 123: #define procsize(p) ((p)->p_tsize + (p)->p_dsize + (p)->p_ssize)
 124:                     /* size of process */
 125: #define ABS(x) ((int)(x) & ~0x80000000) /* clear top bit - type int */
 126: #define K 1024
 127: #define KSHIFT  10
 128: 
 129: #define msize(x)    (x >> (KSHIFT-PGSHIFT))
 130: 
 131: #define USERPAGE    0       /* flag for pread - read user page */
 132: #define TOPMEM      1       /* flag for pread - read top of mem */
 133: 
 134: struct  proc    *plist;
 135: int     mypid;          /* pid of this process */
 136: 
 137: char    Aflag, aflag, Bflag, bflag, cflag, dflag, eflag, fflag, Fflag;
 138: char    Gflag, iflag, lflag, mflag, nflag, rflag, Sflag, sflag, Tflag;
 139: char    Uflag, uflag, vflag, wflag, xflag, nxflag, Wflag, zflag;
 140: int select;     /* flag indicating process selection */
 141: 
 142: int ntotal, nbusy, nloaded, nswapped;
 143: int ktotal, kbusy, kloaded, kswapped;
 144: 
 145: /* specified users, ttys, pids, pgrps */
 146: union numptr {
 147:     int nm_int;
 148:     char *nm_ptr;
 149: };
 150: 
 151: union ttyptr {
 152:     struct ttyline *ty_line;
 153:     char *ty_ptr;
 154: };
 155: 
 156: union numptr    pids[NSPEC], *ppids = pids; /* specified process ids */
 157: union numptr    grps[NSPEC], *pgrps = grps; /* specified groups */
 158: union numptr    uids[NSPEC], *puids = uids; /* specified user ids */
 159: union ttyptr    ttys[NSPEC], *pttys = ttys; /* specified ttys */
 160: 
 161: /* files needed by ps */
 162: 
 163: char    *memf = "/dev/mem";     /* default memory file */
 164: int mem;                /* memory file descriptor */
 165: char    *kmemf = "/dev/kmem";       /* virtual memory file */
 166: int kmem;               /* virtual memory file descriptor */
 167: char    *symf = "/vmunix";      /* default symbol file */
 168: char    *swapf = "/dev/swap";       /* default swap file */
 169: int swap;               /* swap area file descriptor */
 170: char    *infof = "/etc/spsinfo";    /* default info save file */
 171: int infofd;             /* info file descriptor */
 172: 
 173: /* variables read from the kernel */
 174: 
 175: struct  nlist   namelist[] = {
 176: #define aproc       0
 177:     {"_proc"},
 178: #define aswapdev    1
 179:     {"_swapdev"},
 180: #define aswplo      2
 181:     {"_swplo"},
 182: #define answbuf     3
 183:     {"_nswbuf"},
 184: #define atext       4
 185:     {"_text"},
 186: #define abuf        5
 187:     {"_buf"},
 188: #define abfreeli    6
 189:     {"_bfreelist"},
 190: #define akl11       7
 191:     {"_kl11"},
 192: #define adh11       8
 193:     {"_dh11"},
 194: #define alpdt       9
 195:     {"_lp_softc"},
 196: #define albolt      10
 197:     {"_lbolt"},
 198: #define atout       11
 199:     {"_tout"},
 200: #define arunin      12
 201:     {"_runin"},
 202: #define arunout     13
 203:     {"_runout"},
 204: #define aipc        14
 205:     {"_ipc"},
 206: #define afile       15
 207:     {"_file"},
 208: #define ainode      16
 209:     {"_inode"},
 210: #define amaplock    17
 211:     {"_maplock"},
 212: #define acoremap    18
 213:     {"_coremap"},
 214: #define aswapmap    19
 215:     {"_swapmap"},
 216: #define au      20
 217:     {"_u"},
 218: #define adz11       21
 219:     {"_dz_tty"},
 220: #define aetext      22
 221:     {"_etext"},
 222: #define ausrptmap   23
 223:     {"_Usrptmap"},
 224: #define ausrpt      24
 225:     {"_usrpt"},
 226: #define achtbuf     25
 227:     {"_chtbuf"},
 228: #define arhtbuf     26
 229:     {"_rhtbuf"},
 230: #define ahpbuf      27
 231:     {"_hpbuf"},
 232: #define aswbuf      28
 233:     {"_swbuf"},
 234: #define arswbuf     29
 235:     {"_rswbuf"},
 236: #define acons       30
 237:     {"_cons"},
 238: #define ark7        31
 239:     {"_rrk7buf"},
 240: #define achrfclist  32
 241:     {"_Chrfclist"},
 242: #define anproc      33
 243:     {"_nproc"},
 244: #define antext      34
 245:     {"_ntext"},
 246: #define anbuf       35
 247:     {"_nbuf"},
 248: #define ahz     36
 249:     {"_hz"},
 250: #define aninode     37
 251:     {"_ninode"},
 252: #define anfile      38
 253:     {"_nfile"},
 254: #define answap      39
 255:     {"_nswap"},
 256: #define acdevsw     40
 257:     {"_cdevsw"},
 258: #define aChconntab  41
 259:     {"_Chconntab"},
 260: #define MAXSYMBOLS  42
 261:     {"", 0, 0},
 262: };
 263: 
 264: /* this structure is read from info file or initialized (iflag) */
 265: 
 266: struct  {
 267:     caddr_t kaddr[MAXSYMBOLS];      /* useful kernel addresses */
 268:     char    unames[MAXUSERS][UNAMELENGTH];  /* user names */
 269:     struct  ttyline {
 270:         struct tty  *l_addr;        /* address of ttystruct */
 271:         unsigned    l_pgrp;     /* process group */
 272:         char        l_name[2];  /* name */
 273:         dev_t       l_dev;      /* device number */
 274:     } ttyline[MAXTTYS];
 275: 
 276: } info;
 277: int swapdev;            /* major, minor of swap device */
 278: int swplo;              /* unix swap disk offset */
 279: int nswap;              /* unix swap space size */
 280: 
 281: struct ttyline notty = {0, 0, {"- "}};
 282: 
 283: /* flags for once only activities (once per repeat) */
 284: 
 285: int heading;
 286: int coreinit, core;
 287: char *topmem;
 288: int arglength;
 289: char *getcore(), *store(), *waitingfor(), *getcmd(), *strcat(), *brk();
 290: 
 291: main(argc,argv)
 292: char *argv[];
 293: {
 294:     register char *cp, **ap;
 295:     register int i;
 296:     int myuid;
 297:     extern char _sobuf[];
 298: 
 299:     if ((myuid = getuid()) == 0)
 300:         nice(-100);
 301: 
 302:     setbuf(stdout, _sobuf);
 303:     select = 0;
 304:     for (ap = &argv[1]; --argc; ap++) {
 305:         for (cp = *ap; *cp;) {
 306:             switch (*cp++) {
 307:             case '-':
 308:                 continue;
 309:             case 'A':   /* EVERYTHING */
 310:                 Aflag++;
 311:                 continue;
 312:             case 'a':   /* all procs attached to ttys */
 313:                 bflag++;    /* include background */
 314:                 fflag++;    /* include foreground */
 315:                 dflag++;    /* include detached */
 316:                 aflag++;    /* include shells */
 317:                 select++;
 318:                 continue;
 319:             case 'b':   /* all background processes */
 320:                 bflag++;
 321:                 select++;
 322:                 continue;
 323:             case 'B':   /* all busy processes */
 324:                 Bflag++;
 325:                 select++;
 326:                 lflag++;
 327:                 continue;
 328:             case 'c':
 329:                 cflag++;
 330:                 lflag++;
 331:                 continue;
 332:             case 'd':   /* detached processes */
 333:                 dflag++;
 334:                 select++;
 335:                 continue;
 336:             case 'e':
 337:                 eflag++;
 338:                 continue;
 339:             case 'f':   /* foreground only */
 340:                 fflag++;
 341:                 select++;
 342:                 continue;
 343:             case 'F':   /* go fast, don't touch swap */
 344:                 Fflag++;
 345:                 continue;
 346:             case 'G':   /* print pgrp */
 347:                 Gflag++;
 348:                 continue;
 349:             case 'g':   /* specify process gourp */
 350:                 select++;
 351:                 while (argc > 1) {
 352:                     if (**++ap == '-') {
 353:                         ap--;
 354:                         break;
 355:                     }
 356:                     --argc;
 357:                     if (pgrps >= &grps[NSPEC])
 358:                         prexit("%a: too many groups\n");
 359:                     (pgrps++)->nm_int = atoi(*ap);
 360:                 }
 361:                 if (pgrps == grps)
 362:                     (pgrps++)->nm_int = getpgrp();
 363:                 continue;
 364:             case 'i':   /* initialize info file */
 365:                 if (myuid != 0) /* must be super user */
 366:                     goto def;
 367:                 iflag++;
 368:                 nflag++;
 369:                 Uflag++;
 370:                 continue;
 371:             case 'l':   /* long output */
 372:                 lflag++;
 373:                 continue;
 374:             case 'm':   /* use designated memory file */
 375:                 if (myuid != 0) /* must be super user */
 376:                     goto def;
 377:                 if (argc-- < 2 || **++ap == '-')
 378:                     prexit("%a: missing memory file\n");
 379:                 memf = *ap;
 380:                 mflag++;
 381:                 continue;
 382:             case 'n':
 383:                 select++;
 384:                 nflag++;
 385:                 continue;
 386:             case 'p':   /* only designated processes */
 387:                 select++;
 388:                 while (argc > 1) {
 389:                     if (**++ap == '-') {
 390:                         ap--;
 391:                         break;
 392:                     }
 393:                     --argc;
 394:                     if (ppids >= &pids[NSPEC])
 395:                         prexit("%a: too many pids\n");
 396:                     (ppids++)->nm_int = atoi(*ap);
 397:                 }
 398:                 continue;
 399:             case 'r':   /* repeat every <number> seconds */
 400:                 if (myuid != 0)
 401:                     goto def;
 402:                 rflag++;
 403:                 for (i = 0; *cp >= '0' && *cp <= '9'; cp++)
 404:                     i = i * 10 + *cp - '0';
 405:                 if (i)
 406:                     rflag = i;
 407:                 continue;
 408:             case 'U':   /* use designated symbol file */
 409:                 if (myuid != 0)
 410:                     goto def;
 411:                 if (argc-- < 2 || **++ap == '-')
 412:                     prexit("%a: missing symbol file\n");
 413:                 symf = *ap;
 414:                 Uflag++;
 415:                 continue;
 416:             case 's':
 417:                 sflag++;
 418:                 select++;
 419:                 continue;
 420:             case 'S':
 421:                 Sflag++;
 422:                 continue;
 423:             case 'T':
 424:                 Tflag++;
 425:                 continue;
 426:             case 't':   /* on designated tty(s) */
 427:                 select++;
 428:                 while (argc > 1) {
 429:                     if (**++ap == '-') {
 430:                         ap--;
 431:                         break;
 432:                     }
 433:                     --argc;
 434:                     if (pttys >= &ttys[NSPEC])
 435:                         prexit("%a: too many ttys\n");
 436:                     (pttys++)->ty_ptr = *ap;
 437:                 }
 438:                 if (pttys == ttys) {
 439:                     char *ttyname();
 440: 
 441:                     if ( (pttys->ty_ptr = ttyname(2)) == 0)
 442:                         prexit("%a: unknown tty\n");
 443:                     else if (strcmp("/dev/console", pttys->ty_ptr) == 0)
 444:                         (pttys++)->ty_ptr = "co";
 445:                     else
 446:                         (pttys++)->ty_ptr +=
 447:                             sizeof("/dev/tty") - 1;
 448:                 }
 449:                 continue;
 450:             case 'u':       /* specific user name */
 451:                 aflag++;
 452:                 select++;
 453:                 puids = &uids[0];
 454:                 while (argc > 1) {
 455:                     if (**++ap == '-') {
 456:                         ap--;
 457:                         break;
 458:                     }
 459:                     --argc;
 460:                     if (puids >= &uids[NSPEC])
 461:                         prexit("%a: too many users\n");
 462:                     (puids++)->nm_ptr = *ap;
 463:                 }
 464:                 if (puids == &uids[0])
 465:                     (puids++)->nm_int = myuid;
 466:                 continue;
 467:             case 'v':   /* most verbose output */
 468:                 vflag++;
 469:                 lflag++;
 470:                 continue;
 471:             case 'W':
 472:                 Wflag++;
 473:                 continue;
 474:             case 'w':   /* wide form (all arguments) */
 475:                 wflag++;
 476:                 continue;
 477:             case 'x':   /* include un-owned procs */
 478:                 xflag++;
 479:                 select++;
 480:                 continue;
 481:             case 'z':   /* include only zombies */
 482:                 zflag++;
 483:                 select++;
 484:                 continue;
 485:             def:
 486:             default:
 487:                 prexit("%a: unknown switch: %c\n", *--cp);
 488:             }
 489:             break;
 490:         }
 491:     }
 492: 
 493: /* these lengths are kludgely tuned to make things not exceed 79 columns */
 494:     arglength = 60;
 495:     if (lflag)
 496:         arglength -= 28;
 497:     if (vflag)
 498:         arglength -= 14;
 499:     if ((mem = open(memf, 0)) < 0)
 500:         prexit("%a: cannot read system memory: %s\n", memf);
 501:     if ((kmem = open(kmemf, 0)) < 0)
 502:         prexit("%a: cannot read system virtural memory: %s\n", kmemf);
 503:     if (!Fflag && (swap = open(swapf, 0)) <0)
 504:         prexit("%a: cannot read swap device: %s\n", swapf);
 505: 
 506:     if (!iflag)
 507:         if ((i = open(infof, 0)) < 0)
 508:             prexit("%a: cannot open info file\n");
 509:         else if (read(i, &info, sizeof info) != sizeof info)
 510:             prexit("%a: cannot read info file\n");
 511:         else
 512:             close(i);
 513:     if (Uflag) {
 514:         struct nlist *np;
 515:         if ((i = open(symf, 0)) < 0)
 516:             prexit("%a: can't read symbol file\n");
 517:         close(i);
 518:         nlist(symf, namelist);
 519:         for (np = namelist; np < &namelist[MAXSYMBOLS]; np++)
 520:             if (np->n_value == 0)
 521:                 fprintf(stderr, "%a: can't find symbol: %s\n",
 522:                     np->n_name);
 523:         if (namelist[0].n_value == -1)
 524:             prexit("%a: cannot read symbol file: %s\n", symf);
 525:         for (i = 0; i < MAXSYMBOLS; i++)
 526:             info.kaddr[i] = (caddr_t)namelist[i].n_value;
 527:         info.kaddr[aetext] = (caddr_t)( ((unsigned)info.kaddr[aetext] + 63) & ~63);
 528:     }
 529:     if (iflag) {
 530:         readusers();
 531:         ttyinit();
 532:         if ((infofd = creat(infof, 0600)) < 0)
 533:             prexit("%a: cannot create info file\n");
 534:         if ((i = write(infofd, &info, sizeof info)) != sizeof info) {
 535:             if (i == -1)
 536:                 perror(0);
 537:             prexit("%a: cannot write info file: %d\n", i);
 538:         }
 539:         close(infofd);
 540:     }
 541:     lseek(kmem, (long)info.kaddr[aswapdev], 0);
 542:     read(kmem, &swapdev, sizeof(swapdev) );
 543:     lseek(kmem, (long)info.kaddr[aswplo], 0);
 544:     read(kmem, &swplo, sizeof(swplo) );
 545:     lseek(kmem, (long)info.kaddr[answap], 0);
 546:     read(kmem, &nswap, sizeof(nswap) );
 547:     lseek(kmem, (long)info.kaddr[anproc], 0);
 548:     read(kmem, &nproc, sizeof(nproc) );
 549:     lseek(kmem, (long)info.kaddr[antext], 0);
 550:     read(kmem, &ntext, sizeof(ntext) );
 551:     lseek(kmem, (long)info.kaddr[anbuf], 0);
 552:     read(kmem, &nbuf, sizeof(nbuf) );
 553:     lseek(kmem, (long)info.kaddr[abuf], 0);
 554:     read(kmem, &buf, sizeof(buf) );
 555:     lseek(kmem, (long)info.kaddr[answbuf], 0);
 556:     read(kmem, &nswbuf, sizeof(nswbuf) );
 557:     lseek(kmem, (long)info.kaddr[aswbuf], 0);
 558:     read(kmem, &swbuf, sizeof(swbuf) );
 559:     lseek(kmem, (long)info.kaddr[aninode], 0);
 560:     read(kmem, &ninode, sizeof(ninode) );
 561:     lseek(kmem, (long)info.kaddr[ainode], 0);
 562:     read(kmem, &inode, sizeof(inode) );
 563:     lseek(kmem, (long)info.kaddr[ahz], 0);
 564:     read(kmem, &hz, sizeof(hz) );
 565:     lseek(kmem, (long)info.kaddr[aproc], 0);
 566:     read(kmem, &kproc, sizeof(kproc));
 567:     lseek(kmem, (long)info.kaddr[atext], 0);
 568:     read(kmem, &ktext, sizeof(ktext));
 569:     proc = (struct proc *)getcore(nproc * sizeof(struct proc));
 570:     text = (struct text *)getcore(ntext * sizeof(struct text));
 571:     if (puids != &uids[0] && uids[0].nm_int != myuid)
 572:         usersetup();
 573:     if (!select) {
 574:         mypid = getpid();
 575:         (puids++)->nm_int = myuid;
 576:         nxflag++;
 577:         select++;
 578:     }
 579:     ttysetup();
 580:     topmem = 0;
 581:     do {
 582:         heading = 0;            /* reset heading flag (for repeat) */
 583:         core = coreinit = 0;        /* reset core flag (for repeat) */
 584:         lseek(kmem, (long)kproc, 0);
 585:         read(kmem, proc, nproc * sizeof(struct proc));
 586:         lseek(kmem, (long)ktext, 0);
 587:         read(kmem, text, ntext * sizeof(struct text));
 588:         needed();
 589:         mktree();
 590:         action (plist, 0);
 591:         printf("%d processes (%dkb), %d busy (%dkb), %d loaded (%dkb)\n",
 592:             ntotal, (ctob(ktotal) + 1023) / 1024,
 593:             nbusy, (ctob(kbusy) + 1023) / 1024,
 594:             nloaded, (ctob(kloaded) + 1023) / 1024);
 595:         fflush(stdout);
 596:     } while (rflag && sleep(rflag) == 0);
 597:     exit(0);
 598: }
 599: 
 600: /* read the passwd file and fill in the user name arrays */
 601: readusers()
 602: {
 603:     register struct passwd *pw;
 604:     struct passwd *getpwent();
 605: 
 606:     while((pw = getpwent()) != 0) {
 607:         if(info.unames[pw->pw_uid][0] == '\0')
 608:             strcpyn(info.unames[pw->pw_uid], pw->pw_name, UNAMELENGTH);
 609:     }
 610:     endpwent();
 611: }
 612: 
 613: /* check for specified user names */
 614: 
 615: usersetup()
 616: {
 617:     register int i;
 618:     register union numptr *ip;
 619: 
 620:     for (ip = uids; ip < puids; ip++) {
 621:         for (i = 0; i < MAXUSERS; i++)
 622:             if (equalu(ip->nm_ptr, info.unames[i]))
 623:                 goto cont2;
 624:         prexit("%a: unknown user: %s\n", ip->nm_ptr);
 625:     cont2:
 626:         ip->nm_int = i;
 627:     }
 628: }
 629: 
 630: /* compare a fixed length user name */
 631: 
 632: equalu(u1, u2)
 633: register char *u1, *u2;
 634: {
 635:     register int i = 0;
 636: 
 637:     while (*u1++ == *u2)
 638:         if (!*u2++ || ++i == UNAMELENGTH)
 639:             return 1;
 640:     return 0;
 641: }
 642: 
 643: /*
 644:  * Initialize the tty part of the info structure
 645:  */
 646: ttyinit()
 647: {
 648:     struct direct dir;
 649:     struct stat sbuf;
 650:     int fd;
 651:     register struct ttyline *lp = info.ttyline;
 652: 
 653:     if ((fd = open("/dev", 0)) < 0)
 654:         prexit("%a: can't open /dev\n");
 655:     chdir("/dev");
 656:     while (read(fd, (char *)&dir, sizeof(dir)) == sizeof(dir)) {
 657:         if (dir.d_ino == 0 ||
 658:             strncmp("tty", dir.d_name, 3) != 0 &&
 659:             strcmp("console", dir.d_name) != 0)
 660:             continue;
 661:         if (dir.d_name[sizeof("tty") - 1] == 'C')
 662:             continue;
 663:         if (lp >= &info.ttyline[MAXTTYS])
 664:             prexit("%a: too many ttys in /dev\n");
 665:         if (dir.d_name[0] == 'c') {
 666:             lp->l_name[0] = 'c';
 667:             lp->l_name[1] = 'o';
 668:         } else {
 669:             lp->l_name[0] = dir.d_name[3];
 670:             lp->l_name[1] = dir.d_name[4];
 671:         }
 672:         stat(dir.d_name, &sbuf);
 673:         lp->l_dev = sbuf.st_rdev;
 674:         lseek(kmem, (long)&cswitch[major(sbuf.st_rdev)].d_ttys, 0);
 675:         read(kmem, (char *)&lp->l_addr, sizeof(lp->l_addr));
 676:         lp->l_addr += minor(sbuf.st_rdev);
 677:         lp++;
 678:     }
 679:     close(fd);
 680: }
 681: ttysetup()
 682: {
 683:     register struct ttyline *lp;
 684:     register char *cp;
 685:     union ttyptr *tp;
 686:     struct tty tty;
 687: 
 688:     for (lp = info.ttyline; lp->l_name[0]; lp++) {
 689:         lseek(kmem, (long)lp->l_addr, 0);
 690:         if (read(kmem, &tty, sizeof tty) != sizeof tty)
 691:             prexit("%a: read error in kmem\n");
 692:         lp->l_pgrp = tty.t_pgrp;
 693:         if (Tflag)
 694:             printf("tty%-.2s: dev:%2d,%2d addr:%6x, rawq:%4d, canq:%d, outq:%4d, pgrp:%5d\n",
 695:                 lp->l_name, major(lp->l_dev), minor(lp->l_dev),
 696:                 ABS(lp->l_addr), tty.t_rawq.c_cc,
 697:                 tty.t_canq.c_cc, tty.t_outq.c_cc,
 698:                 tty.t_pgrp);
 699:     }
 700: #ifdef CHAOS
 701:     mkchttys(lp);
 702: #endif
 703:     /* now fix up specified ttys */
 704: 
 705:     for (tp = &ttys[0]; tp < pttys; tp++) {
 706:         for (lp = info.ttyline; lp->l_name[0]; lp++)
 707:             if (strcmpn(tp->ty_ptr, lp->l_name, 2) == 0) {
 708:                 tp->ty_line = lp;
 709:                 goto cont2;
 710:             }
 711:         prexit("%a: unknown tty name: %c\n", tp->ty_ptr);
 712:     cont2:;
 713:     }
 714: }
 715: 
 716: /*
 717:  * Determine which procs are needed for the printout
 718:  * and add these to a list of needed processes (plist)
 719:  */
 720: needed()
 721: {
 722:     register struct proc *p, *pp;
 723:     register struct text *tp;
 724:     struct ttyline *lp;
 725:     int ok;
 726: 
 727:     plist = 0;
 728:     nswapped = ntotal = nbusy = nloaded = 0;
 729:     kswapped = ktotal = kbusy = kloaded = 0;
 730: 
 731:     for (tp = text; tp < text + ntext; tp++)
 732:         if (tp->x_count) {
 733:             ktotal += tp->x_size;
 734:             if (!(tp->x_ccount))
 735:                 kswapped += tp->x_size;
 736:         }
 737: 
 738:     for (p = proc; p < proc + nproc; p++) {
 739:         if (!p->p_stat)
 740:             continue;
 741:         if (p->p_textp)
 742:             p->p_textp = &text[p->p_textp - ktext];
 743:         if (p->p_pptr) {
 744:             p->p_pptr = &proc[p->p_pptr - kproc];
 745:             if (p->p_pptr < proc || p->p_pptr >= &proc[nproc]) {
 746:                 fprintf(stderr, "proc %d bad pptr\n", p->p_pid);
 747:                 p->p_pptr = proc;
 748:             }
 749:         } else
 750:             p->p_pptr = proc;
 751:     }
 752:     for (p = &proc[0]; p < &proc[nproc]; p++) {
 753:         if (!p->p_stat)
 754:             continue;
 755:         ntotal++;
 756:         ktotal += procsize(p);
 757:         if (p->p_flag != SZOMB)
 758:             if (p->p_flag & SLOAD) {
 759:                 nloaded++;
 760:                 kloaded += procsize(p);
 761:                 if ((tp = p->p_textp) && tp->x_count) {
 762:                     tp->x_count = 0;
 763:                     kloaded += tp->x_size;
 764:                 }
 765:             } else {
 766:                 nswapped++;
 767:                 kswapped += procsize(p);
 768:             }
 769:         ok = FALSE;
 770:         if (p->p_stat == SRUN ||
 771:             p->p_stat == SSLEEP && (p->p_pri < PZERO && p->p_pid > MSPID)) {
 772:             nbusy++;
 773:             kbusy += procsize(p);
 774:             if ((tp = p->p_textp) && tp->x_ccount) {
 775:                 tp->x_ccount = 0;
 776:                 kbusy += tp->x_size;
 777:             }
 778:             if (Bflag)
 779:                 ok = TRUE;
 780:         }
 781:         if (nflag)
 782:             continue;
 783:         if (zflag && p->p_stat == SZOMB)
 784:             ok = TRUE;
 785:         if (sflag && p->p_stat == SSTOP)
 786:             ok = TRUE;
 787:         if (select == 0 && mypid && p->p_pid == mypid)
 788:             continue;
 789:         if (p->p_pgrp == 0)
 790:             if (xflag)
 791:                 ok = TRUE;
 792:             else if (nxflag)
 793:                 continue;
 794:         if (dflag && p->p_pgrp != 0 && (p->p_flag & SDETACH) != 0)
 795:             ok = TRUE;
 796:         if (aflag && xflag && p->p_pgrp != 0 && (p->p_flag & SDETACH) == 0 &&
 797:             p->p_pptr == &proc[1])
 798:             ok = TRUE;
 799:         if (puids != uids) {
 800:             register union numptr *ip;
 801: 
 802:             for (pp = p; pp > &proc[1]; pp = pp->p_pptr)
 803:                 for (ip = uids; ip < puids; ip++)
 804:                     if ((pp->p_uid & 0377) == ip->nm_int){
 805:                         ok = TRUE;
 806:                         goto uidok;
 807:                     }
 808:         }
 809:     uidok:
 810:         if (pgrps != grps) {
 811:             register union numptr *ip;
 812: 
 813:             for (pp = p; pp > &proc[1]; pp = pp->p_pptr)
 814:                 for (ip = grps; ip < pgrps; ip++)
 815:                     if (pp->p_pgrp == ip->nm_int) {
 816:                         ok = TRUE;
 817:                         goto pgrpok;
 818:                     }
 819:         }
 820:     pgrpok:
 821:         if (ppids != pids) {
 822:             register union numptr *ip;
 823: 
 824:             for (ip = pids; ip < ppids; ip++)
 825:                 if (ip->nm_int == p->p_pid) {
 826:                     ok = TRUE;
 827:                     goto procok;
 828:                 }
 829:         }
 830:     procok:
 831:         if (select && pttys == ttys && !fflag && !bflag && !ok)
 832:             continue;
 833:         if (getu(p) == 0) {
 834:             static struct procinfo  fakep = {"--no upage--", &notty, 0};
 835: 
 836:             if (select && !ok)
 837:                 continue;
 838:             pinfo(p) = &fakep;
 839:             goto putonlist;
 840:         }
 841:         if (pttys != ttys && p->p_pgrp != 0) {
 842:             union ttyptr *ip;
 843: 
 844:             for (ip = ttys; ip < pttys; ip++)
 845:                 if (p->p_pgrp && p->p_pgrp == ip->ty_line->l_pgrp ||
 846:                     p->p_stat == SSLEEP &&
 847:                     p->p_wchan >= (char *)ip->ty_line->l_addr &&
 848:                     p->p_wchan < (char *)ip->ty_line->l_addr +
 849:                          sizeof (struct tty) ||
 850:                     u.u_ttyd == ip->ty_line->l_dev) {
 851:                     ok = TRUE;
 852:                     break;
 853:                 }
 854:         }
 855:         if (p->p_pgrp == 0)
 856:             lp = &notty;
 857:         else {
 858:             for (lp = info.ttyline; lp->l_name[0] != 0; lp++)
 859:                 if (lp->l_dev == u.u_ttyd)
 860:                     break;
 861:             if (lp->l_name[0] == 0)
 862:                 lp = &notty;
 863:             else if (p->p_pptr != &proc[1]) {
 864:                 if (fflag && p->p_pgrp == lp->l_pgrp)
 865:                     ok = TRUE;
 866:                 if (bflag && p->p_pgrp != lp->l_pgrp &&
 867:                     (p->p_flag & SDETACH) == 0 &&
 868:                     p->p_stat != SSTOP)
 869:                     ok = TRUE;
 870:             }
 871:         }
 872:         if (select && !ok)
 873:             continue;
 874:         pinfo(p) = (struct procinfo *)getcore(sizeof (struct procinfo));
 875:         pinfo(p)->pi_time = u.u_vm.vm_utime + u.u_vm.vm_stime;
 876:         pinfo(p)->pi_tty = lp;
 877:         pinfo(p)->pi_cmd = getcmd(p);
 878:     putonlist:
 879:     /* we have a needed proc! */
 880: 
 881:         p->p_next = plist;
 882:         plist = p;
 883:         p->p_son = p->p_bro = 0;
 884:     }
 885: }
 886: /*
 887:  * mktree - sort the needed processes by subtree and at the top by user
 888:  */
 889: mktree()
 890: {
 891:     register struct proc *p, *pp, *lp;
 892:     struct proc *op;
 893:     struct proc proot;
 894: 
 895:     proot.p_bro = 0;
 896: 
 897:     for (p = plist; p; p = p->p_next) { /* for all needed processes */
 898:         if (p->p_pptr > &proc[1]) {
 899:             for (pp = plist; pp; pp = pp->p_next)
 900:                 if (pp == p->p_pptr) {  /* if my parent */
 901:                     if (lp = pp->p_son) {   /* if siblings */
 902:                         for (op = 0; lp && lp->p_pid <
 903:                             p->p_pid;
 904:                             lp = (op = lp)->p_bro)
 905:                             ;
 906:                         if (op) {
 907:                             p->p_bro = lp;
 908:                             op->p_bro = p;
 909:                             break;
 910:                         }
 911:                     }
 912:                     p->p_bro = lp;  /* here if first or only */
 913:                     pp->p_son = p;
 914:                     break;
 915:                 }
 916:             if (pp)     /* if we found the parent */
 917:                 continue;
 918:         }
 919: 
 920:         /* we have a top level process, sort into top level list */
 921: 
 922:         for (pp = (lp = &proot)->p_bro; pp; pp = (lp = pp)->p_bro)
 923:             if ((p->p_uid & 0377) < (pp->p_uid & 0377) ||
 924:                 (p->p_uid & 0377) == (pp->p_uid & 0377) &&
 925:                 p->p_pid < pp->p_pid)
 926:                 break;
 927:         p->p_bro = lp->p_bro;
 928:         lp->p_bro = p;
 929:     }
 930:     plist = proot.p_bro;
 931: }
 932: 
 933: action(p, md)
 934: register struct proc *p;
 935: register int md;
 936: {
 937: 
 938:     if (p) {
 939:         printp(p, md);
 940:         if (p->p_son)
 941:             action(p->p_son, md+1);
 942:         if (p->p_bro)
 943:             action(p->p_bro, md);
 944:     }
 945: }
 946: 
 947: /*
 948:  * Pretty print the output according to the switches.
 949:  */
 950: printp(p, md)
 951: register struct proc *p;
 952: {
 953:     register char *cp, *cp1;
 954:     char    stat[10];
 955:     static int lastuid;
 956:     static char *statnames[] = {"Unk ", "Wait", "Wait", "Run ",
 957:                 "Init", "Exit", "Stop"};
 958: 
 959:     if (!heading) {
 960:         heading++;
 961:         printf("Ty User     ");
 962:         if (lflag) {
 963:             printf("Stat");
 964:             if (vflag) printf(" Flgs Nice Pri ");
 965:             else printf(" ");
 966:             printf("Memory-kb  Time Wait?  ");
 967:             }
 968:         if (Aflag)
 969:             printf("Address Proc.  Clock Alarm ");
 970:         if (Sflag)
 971:             printf("Size  ");
 972:         if (Gflag)
 973:             printf("Group ");
 974:         printf("Proc#  Command\n");
 975:     }
 976:     printf("%.2s%c", pinfo(p)->pi_tty->l_name,
 977:         p->p_pgrp == 0 ? ' ' :
 978:         p->p_flag & SDETACH ? '_' :
 979:         p->p_pgrp == pinfo(p)->pi_tty->l_pgrp ? '.' :
 980:         ' ');
 981: 
 982:     if (md == 0) {
 983:         lastuid = p->p_uid & 0377;
 984:         cp = info.unames[lastuid];
 985:         if (*cp)
 986:             printf("%-8.8s ", cp);
 987:         else
 988:             printf("user%-4.4d ", lastuid);
 989:     } else {
 990:         if (md > 8)
 991:             md = 8;
 992:         printf("%*s*", md, "");
 993:         if ((p->p_uid & 0377) != lastuid) { /* setuid process! */
 994:             lastuid = p->p_uid & 0377;
 995:             cp = info.unames[lastuid];
 996:         } else
 997:             cp = "";
 998:         md = 8 - md;
 999:         printf("%-*.*s", md, md, cp);
1000:     }
1001:     if (lflag) {
1002:         cp = statnames[p->p_stat];
1003:         if (p->p_flag&SLOAD) {
1004:             for (cp1 = stat; *cp1 = *cp; cp1++, cp++)
1005:                 if (*cp >= 'a' && *cp <= 'z')
1006:                     *cp1 -= 'a' - 'A';
1007:             cp = stat;
1008:             }
1009:         printf("%-4.4s ", cp);
1010:         if (vflag) {
1011:             cp = stat;
1012:             if (p->p_flag & SSYS) *cp++ = 'U';
1013:             if (p->p_flag&SLOCK) *cp++ = 'L';
1014:             if (p->p_flag&STRC) *cp++ = 'T';
1015:             if (p->p_flag&SWTED) *cp++ = 'W';
1016:             if (p->p_flag&SSWAP) *cp++ = 'S';
1017:             while(cp < &stat[5]) *cp++ = ' ';
1018:             *cp = 0;
1019:             printf("%-4.4s ",stat);
1020:             if (p->p_nice != NZERO)
1021:                 printf("%4d", p->p_nice - NZERO);
1022:             else
1023:                 printf("    ");
1024:             if (p->p_stat != SZOMB)
1025:                 printf("%4d ", p->p_pri);
1026:             else
1027:                 printf("     ");
1028:         }
1029:         if (p->p_stat != SZOMB) {
1030:             printf("%4d", msize(procsize(p)) );
1031:             if (p->p_textp)
1032:                 printf("+%4d ", msize(p->p_textp->x_size));
1033:             else
1034:                 printf("      ");
1035:             prcpu(pinfo(p)->pi_time);
1036:         } else
1037:             printf("                ");
1038:         if (p->p_stat != SZOMB && p->p_stat != SRUN && p->p_stat != SSTOP)
1039:             if (!Wflag && (cp = waitingfor(p)))
1040:                 printf("%-6.6s ", cp);
1041:             else printf("%6x ", ABS((int)p->p_wchan));
1042:         else printf("       ");
1043:     }
1044:     if (Aflag)
1045:         printf("%6x %6x %6d%6d ", p->p_addr,
1046:             (p - proc) * sizeof (struct proc) + info.kaddr[aproc],
1047:             p->p_time, p->p_clktim);
1048:     if (Sflag)
1049:         printf("%5x ", procsize(p) );
1050:     if (Gflag)
1051:         printf("%5D ", p->p_pgrp);
1052:     printf("%5D  ", p->p_pid);
1053:     if (wflag)
1054:         printf("%s\n", pinfo(p)->pi_cmd);
1055:     else
1056:         printf("%-.*s\n", arglength, pinfo(p)->pi_cmd);
1057: }
1058: 
1059: /* print cpu time */
1060: 
1061: prcpu(time)
1062: long time;
1063: {
1064:     register unsigned i;
1065: 
1066:     if (time < 0)
1067:         printf(" ---- ");
1068:     else if (time < (long)hz * 60 * 10)     /* less than 10 minutes */
1069:         printf("%3d.%1d ",
1070:             (int)(time / hz),
1071:             (int)(time % hz / (hz / 10)));
1072:     else if (time < (long)hz * 60 * 60 * 10)/* less than 10 hours */
1073:         printf("%3d M ",
1074:             (int)((time + (hz * 60) / 2) / (hz * 60)));
1075:     else {
1076:         i = (time + ((long)hz * 60 * 60) / 2) /
1077:                     ((long)hz * 60 * 60);
1078:         if (i < 1000)
1079:             printf("%3d H ", i);
1080:         else
1081:             printf(" ---- ");
1082:     }
1083: }
1084: /* Determine what a process is waiting for and describe it. */
1085: 
1086: char *
1087: waitingfor(p)
1088: register struct proc *p;
1089: {
1090:     register caddr_t w;
1091:     register struct ttyline *lp;
1092:     register char *cp;
1093: 
1094:     w = p->p_wchan;
1095:     if (w == (caddr_t)0)
1096:         return "null";
1097:     if (w >= (char *)kproc && w < (char *)(kproc + nproc))
1098:         return "child";
1099:     if (w >= (char *)swbuf && w < (char *)(swbuf + nswbuf))
1100:         return "swap";
1101:     if (w == info.kaddr[arswbuf])
1102:         return "rswap";
1103:     if (w >= (char *)buf && w < (char *)(buf + nbuf))
1104:         return "diskio";
1105:     if (w >= info.kaddr[afile] && w < info.kaddr[afile] + sizeof(struct file) * nfile)
1106:         return "file";
1107:     if (w >= (char *)inode && w < (char *)(inode + ninode))
1108:         switch((w - (char *)inode) % sizeof(struct inode)) {
1109:         case 1:
1110:             return "wpipe";
1111:         case 2:
1112:             return "rpipe";
1113:         case 3:
1114:             return "mutex";
1115:         case (int)&((struct inode *)0)->i_un.i_group.g_datq:
1116:             return "rmux";
1117:         default:
1118:             return "inode";
1119:         }
1120:     if (w == info.kaddr[achtbuf])
1121:         return "tapecn";
1122:     if (w == info.kaddr[ahpbuf])
1123:         return "rpdisk";
1124:     if (w == info.kaddr[ark7])
1125:         return "rkdisk";
1126:     if (w == info.kaddr[arhtbuf])
1127:         return "tapeio";
1128:     if (w == info.kaddr[alpdt])
1129:         return "printr";
1130:     if (w == info.kaddr[albolt])
1131:         return "lbolt";
1132:     if (w == info.kaddr[arunin])
1133:         return "runin";
1134:     if (w == info.kaddr[arunout])
1135:         return "runout";
1136:     if (w == info.kaddr[atout])
1137:         return "sleep";
1138:     if (w == info.kaddr[aipc])
1139:         return "ptrace";
1140:     if (w == info.kaddr[abfreeli])
1141:         return "buffer";
1142:     if (w == info.kaddr[amaplock])
1143:         return "ubmap";
1144:     if (w == info.kaddr[au])
1145:         return "pause";
1146:     if (w == info.kaddr[achrfclist])
1147:         return "chrfc";
1148:     for (lp = info.ttyline; lp->l_name[0]; lp++)
1149:         if (w >= (char *)lp->l_addr && w < (char *)lp->l_addr + sizeof (struct tty)) {
1150: #define TTY0 ((struct tty *)0)
1151:             switch(w - (char *)lp->l_addr) {
1152:             case (int)&TTY0->t_rawq:
1153:                 cp = "rtty??";
1154:                 break;
1155:             case (int)&TTY0->t_outq:
1156:                 cp = "wtty??";
1157:                 break;
1158:             case (int)&TTY0->t_state:
1159:                 cp = "otty??";
1160:                 break;
1161:             default:
1162:                 cp = "?tty??";
1163:             }
1164:             cp[4] = lp->l_name[0];
1165:             cp[5] = lp->l_name[1];
1166:             return cp;
1167:         }
1168:     return 0;
1169: }
1170: 
1171: getu(mproc)
1172: register struct proc *mproc;
1173: {
1174:     struct pte *pteaddr, apte;
1175:     register int i;
1176:     int ncl, size;
1177: 
1178:     size = Sflag ? ctob(UPAGES) : sizeof (struct user);
1179:     if ((mproc->p_flag & SLOAD) == 0) {
1180:         lseek(swap, (long)ctob(mproc->p_swaddr), 0);
1181:         if (read(swap, (char *)&user.user, size) != size) {
1182:             fprintf(stderr, "%a: cant read u for pid %d from %s\n",
1183:                 mproc->p_pid, swapf);
1184:             return (0);
1185:         }
1186:         return (1);
1187:     }
1188:     pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
1189:     lseek(kmem, (long)(mflag ? ABS(pteaddr) : (int)pteaddr), 0);
1190:     if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
1191:         printf("%a: cant read indir pte to get u for pid %d from %s\n",
1192:             mproc->p_pid, swapf);
1193:         return (0);
1194:     }
1195:     lseek(mem, (long)
1196:         (ctob(apte.pg_pfnum+1) - (UPAGES+MAXARGPG) * sizeof (struct pte)),
1197:         0);
1198:     if (read(mem, (char *)pagetable, sizeof(pagetable)) != sizeof(pagetable)) {
1199:         printf("%a: cant read page table for u of pid %d from %s\n",
1200:             mproc->p_pid, swapf);
1201:         return (0);
1202:     }
1203:     ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
1204:     while (--ncl >= 0) {
1205:         i = ncl * CLSIZE;
1206:         lseek(mem, (long)ctob(pagetable[MAXARGPG+i].pg_pfnum), 0);
1207:         if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
1208:             printf("%a: cant read page %d of u of pid %d from %s\n",
1209:                 pagetable[MAXARGPG+i].pg_pfnum, mproc->p_pid, memf);
1210:             return(0);
1211:         }
1212:     }
1213:     return (1);
1214: }
1215: char *
1216: getcmd(p)
1217: register struct proc *p;
1218: {
1219:     struct pte apte;
1220:     char argbuf[MAXARGPG * NBPG], *argptr;
1221:     register int *ip;
1222:     register char *cp, *cp1;
1223:     int cc, nbad, i;
1224: 
1225:     if (p->p_stat == SZOMB)
1226:         return "--Defunct--";
1227:     if ((p->p_flag&SLOAD) == 0 && Fflag)
1228:         return "--Swapped--";
1229:     if (p->p_flag & SSYS)
1230:         return p->p_pid == 0 ? "UNIX Swapper" :
1231:             p->p_pid == 2 ? "UNIX Pager" : "UNIX";
1232:     for (i = 0; i < MAXARGPG; i++) {
1233:         argptr = &argbuf[(MAXARGPG - 1 - i) * NBPG];
1234:         apte = pagetable[MAXARGPG - 1 - i];
1235:         if ((p->p_flag & SLOAD) && apte.pg_fod == 0 && apte.pg_pfnum ) {
1236:             lseek(mem, (long)ctob(apte.pg_pfnum), 0);
1237:             if (read(mem, argptr, NBPG) != NBPG)
1238:                 return "---Mem read error (args)---";
1239:         } else if (Fflag)
1240:             goto cheap;
1241:         else {
1242:             lseek(swap, (long)ctob(u.u_smap.dm_map[0] + DMMIN - 1 - i), 0);
1243:             if (read(swap, argptr, NBPG) != NBPG)
1244:                 return "---Swap read error (args)---";
1245:         }
1246:         /* Here block of stack is at argptr */
1247:         ip = (int *)&argptr[NBPG];
1248:         if (i == 0) {
1249:             *--ip = 0;
1250:             ip--;
1251:         }
1252:         while (ip > (int *)argptr && *--ip != 0)
1253:             ;
1254:         if (ip > (int *)argptr || *ip == 0)
1255:             break;
1256:     }
1257:     if (i >= MAXARGPG) {
1258: cheap:
1259:         argbuf[0] = '(';
1260:         strncpy(&argbuf[1], u.u_comm, sizeof(u.u_comm));
1261:         strcat(argbuf, ")");
1262:         return store(argbuf);
1263:     }
1264:     cp = (char *)(ip + 1);
1265:     if (*cp == '\0')
1266:         cp++;
1267:     nbad = 0;
1268:     for (cp1 = cp; cp1 < &argbuf[MAXARGPG*NBPG]; cp1++) {
1269:         cc = *cp1 & 0177;
1270:         if (cc == 0)
1271:             *cp1 = ' ';
1272:         else if (cc < ' ' || cc == 0177) {
1273:             if (++nbad >= 5) {
1274:                 *cp1++ = ' ';
1275:                 break;
1276:             }
1277:             *cp1 = '?';
1278:         } else if (!eflag && cc == '=') {
1279:             *cp1 = 0;
1280:             while (cp1 > cp && *--cp1 != ' ')
1281:                 *cp1 = 0;
1282:             break;
1283:         }
1284:     }
1285:     while (*--cp1 == ' ')
1286:         *cp1 = 0;
1287:     if (!wflag && &cp[arglength] < (char *)&argbuf[MAXARGPG*NBPG - 1])
1288:         cp[arglength] = 0;
1289:     return store(cp);
1290: }
1291: 
1292: /*
1293:  * Store a string in core for later use.
1294:  */
1295: char *
1296: store(cp)
1297: char *cp;
1298: {
1299:     register char *src, *dst, *svdst;
1300: 
1301:     src = cp;
1302:     while (*src++);
1303:     svdst = getcore(src - cp);
1304:     dst = svdst;
1305:     src = cp;
1306:     while (*dst++ = *src++);
1307:     return(svdst);
1308: }
1309: 
1310: /*
1311:  * Allocate and return a pointer to the asked for amount of core
1312:  */
1313: char *
1314: getcore(cnt)
1315: register int cnt;
1316: {
1317:     static char *corep;
1318:     register char *ip;
1319:     register int incr;
1320:     char *sbrk();
1321: 
1322:     if (cnt > core) {
1323:         if (coreinit == 0) {
1324:             coreinit++;
1325:             if (topmem)
1326:                 brk(topmem);    /* after repeat!! */
1327:             else
1328:                 topmem = sbrk(0);
1329:             corep = topmem;
1330:         }
1331:         incr = cnt > 4096 ? cnt : 4096;
1332:         if (sbrk(incr) == 0)
1333:             prexit("%a: out of memory!\n");
1334:         core += incr;
1335:     }
1336:     ip = corep;
1337:     core -= cnt;
1338:     corep += cnt;
1339:     return(ip);
1340: }
1341: #ifdef CHAOS
1342: #include "chunix/chsys.h"
1343: #include <chaos/chaos.h>
1344: 
1345: mkchttys(lp)
1346: register struct ttyline *lp;
1347: {
1348:     register struct connection **cnp;
1349:     register int i;
1350:     struct tty tty;
1351:     struct connection *Chconntab[CHNCONNS];
1352:     struct connection conn;
1353: 
1354:     lseek(kmem, (long)info.kaddr[aChconntab], 0);
1355:     read(kmem, (char *)Chconntab, sizeof(Chconntab));
1356:     for (i = 0, cnp = Chconntab; cnp < &Chconntab[CHNCONNS]; i++, cnp++) {
1357:         if (!*cnp)
1358:             continue;
1359:         lseek(kmem, (long)*cnp, 0);
1360:         read(kmem, (char *)&conn, sizeof(conn));
1361:         if ((conn.cn_flags & CHTTY) == 0)
1362:             continue;
1363:         lseek(kmem, (long)conn.cn_ttyp, 0);
1364:         read(kmem, (char *)&tty, sizeof(tty));
1365:         if (lp >= &info.ttyline[MAXTTYS])
1366:             prexit("%a: too many ttys\n");
1367:         lp->l_addr = conn.cn_ttyp;
1368:         lp->l_pgrp = tty.t_pgrp;
1369:         lp->l_dev = tty.t_dev;
1370:         lp->l_name[0] = 'C';
1371:         lp->l_name[1] = i < 10 ? '0' + i :
1372:             i - 10 <= 'z' - 'a' ? i - 10 + 'a' :
1373:             i - 10 - ('z' - 'a') + 'A';
1374:         if (Tflag)
1375:             printf("tty%-.2s: dev:%2d,%2d addr:%6x, rawq:%4d, canq:%d, outq:%4d, pgrp:%5d\n",
1376:                 lp->l_name, major(lp->l_dev), minor(lp->l_dev),
1377:                 ABS(lp->l_addr), tty.t_rawq.c_cc,
1378:                 tty.t_canq.c_cc, tty.t_outq.c_cc,
1379:                 tty.t_pgrp);
1380:         lp++;
1381:     }
1382: }
1383: #endif

Defined functions

action defined in line 933; used 3 times
equalu defined in line 632; used 1 times
getcmd defined in line 1215; used 2 times
getcore defined in line 1313; used 5 times
getu defined in line 1171; used 1 times
main defined in line 291; never used
mkchttys defined in line 1345; used 1 times
mktree defined in line 889; used 1 times
needed defined in line 720; used 1 times
prcpu defined in line 1061; used 1 times
printp defined in line 950; used 1 times
readusers defined in line 601; used 1 times
store defined in line 1295; used 3 times
ttyinit defined in line 646; used 1 times
ttysetup defined in line 681; used 1 times
usersetup defined in line 615; used 1 times
waitingfor defined in line 1086; used 2 times

Defined variables

Aflag defined in line 137; used 3 times
Bflag defined in line 137; used 2 times
Fflag defined in line 137; used 4 times
Gflag defined in line 138; used 3 times
Sflag defined in line 138; used 4 times
Tflag defined in line 138; used 3 times
Uflag defined in line 139; used 3 times
Wflag defined in line 139; used 2 times
aflag defined in line 137; used 3 times
arglength defined in line 288; used 6 times
bflag defined in line 137; used 4 times
buf defined in line 92; used 4 times
cflag defined in line 137; used 1 times
core defined in line 286; used 4 times
coreinit defined in line 286; used 3 times
dflag defined in line 137; used 3 times
eflag defined in line 137; used 2 times
fflag defined in line 137; used 4 times
grps defined in line 157; used 5 times
heading defined in line 285; used 3 times
hz defined in line 94; used 11 times
iflag defined in line 138; used 3 times
infof defined in line 170; used 2 times
infofd defined in line 171; used 3 times
inode defined in line 93; used 5 times
kbusy defined in line 143; used 4 times
kloaded defined in line 143; used 4 times
kmem defined in line 166; used 45 times
kmemf defined in line 165; used 2 times
kproc defined in line 90; used 6 times
kswapped defined in line 143; used 3 times
ktext defined in line 91; used 4 times
ktotal defined in line 143; used 4 times
lflag defined in line 138; used 7 times
mem defined in line 164; used 7 times
memf defined in line 163; used 4 times
mflag defined in line 138; used 2 times
mypid defined in line 135; used 3 times
namelist defined in line 175; used 5 times
nbuf defined in line 94; used 3 times
nbusy defined in line 142; used 3 times
nfile defined in line 94; used 1 times
nflag defined in line 138; used 3 times
ninode defined in line 94; used 3 times
nloaded defined in line 142; used 3 times
notty defined in line 281; used 3 times
nproc defined in line 94; used 8 times
nswap defined in line 279; used 2 times
  • in line 546(2)
nswapped defined in line 142; used 2 times
nswbuf defined in line 94; used 3 times
ntext defined in line 94; used 5 times
ntotal defined in line 142; used 3 times
nxflag defined in line 139; used 2 times
pad1 defined in line 99; never used
pad2 defined in line 101; never used
pagetable defined in line 100; used 6 times
pgrps defined in line 157; used 6 times
pids defined in line 156; used 4 times
plist defined in line 134; used 7 times
ppids defined in line 156; used 4 times
proc defined in line 90; used 17 times
pttys defined in line 159; used 11 times
puids defined in line 158; used 10 times
rflag defined in line 138; used 4 times
select defined in line 140; used 20 times
sflag defined in line 138; used 2 times
swap defined in line 169; used 5 times
swapdev defined in line 277; used 2 times
  • in line 542(2)
swapf defined in line 168; used 5 times
swbuf defined in line 92; used 4 times
swplo defined in line 278; used 2 times
  • in line 544(2)
symf defined in line 167; used 4 times
text defined in line 91; used 5 times
topmem defined in line 287; used 5 times
ttys defined in line 159; used 7 times
uflag defined in line 139; never used
uids defined in line 158; used 9 times
vflag defined in line 139; used 4 times
wflag defined in line 139; used 3 times
xflag defined in line 139; used 3 times
zflag defined in line 139; used 2 times

Defined struct's

procinfo defined in line 113; used 6 times
ttyline defined in line 269; used 14 times

Defined union's

numptr defined in line 146; used 14 times
ttyptr defined in line 151; used 6 times

Defined macros

ABS defined in line 125; used 4 times
FALSE defined in line 83; used 1 times
INTPPG defined in line 84; never used
K defined in line 126; never used
KSHIFT defined in line 127; used 1 times
MAXARGPG defined in line 85; used 11 times
MAXSYMBOLS defined in line 260; used 3 times
MAXTTYS defined in line 109; used 3 times
MAXUSERS defined in line 106; used 2 times
MSPID defined in line 104; used 1 times
NSPEC defined in line 108; used 8 times
TOPMEM defined in line 132; never used
TRUE defined in line 82; used 12 times
TTY0 defined in line 1150; used 3 times
UNAMELENGTH defined in line 107; used 3 times
USERPAGE defined in line 131; never used
Usrptmap defined in line 87; used 1 times
aChconntab defined in line 258; used 1 times
abfreeli defined in line 188; used 1 times
abuf defined in line 186; used 1 times
acdevsw defined in line 256; used 1 times
  • in line 89
achrfclist defined in line 240; used 1 times
achtbuf defined in line 226; used 1 times
acons defined in line 236; never used
acoremap defined in line 212; never used
adh11 defined in line 192; never used
adz11 defined in line 218; never used
aetext defined in line 220; used 2 times
  • in line 527(2)
afile defined in line 206; used 2 times
ahpbuf defined in line 230; used 1 times
ahz defined in line 248; used 1 times
ainode defined in line 208; used 1 times
aipc defined in line 204; used 1 times
akl11 defined in line 190; never used
albolt defined in line 196; used 1 times
alpdt defined in line 194; used 1 times
amaplock defined in line 210; used 1 times
anbuf defined in line 246; used 1 times
anfile defined in line 252; never used
aninode defined in line 250; used 1 times
anproc defined in line 242; used 1 times
answap defined in line 254; used 1 times
answbuf defined in line 182; used 1 times
antext defined in line 244; used 1 times
aproc defined in line 176; used 2 times
arhtbuf defined in line 228; used 1 times
ark7 defined in line 238; used 1 times
arswbuf defined in line 234; used 1 times
arunin defined in line 200; used 1 times
arunout defined in line 202; used 1 times
aswapdev defined in line 178; used 1 times
aswapmap defined in line 214; never used
aswbuf defined in line 232; used 1 times
aswplo defined in line 180; used 1 times
atext defined in line 184; used 1 times
atout defined in line 198; used 1 times
au defined in line 216; used 1 times
ausrpt defined in line 224; used 1 times
  • in line 88
ausrptmap defined in line 222; used 1 times
  • in line 87
cswitch defined in line 89; used 1 times
msize defined in line 129; used 2 times
p_bro defined in line 120; used 14 times
p_next defined in line 119; used 3 times
p_son defined in line 121; used 5 times
pinfo defined in line 122; used 10 times
procsize defined in line 123; used 6 times
u defined in line 103; used 7 times
usrpt defined in line 88; never used
Last modified: 1982-06-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3627
Valid CSS Valid XHTML 1.0 Strict