1: /*
   2:  *	1999/8/11 - Remove reference to SDETACH.  It was removed from the kernel
   3:  *		    (finally) because it was not needed.
   4:  *
   5:  *	1997/12/16 - Fix coredump when processing -U.
   6:  *
   7:  *	1996/11/16 - Move 'psdatabase' in /var/run.
   8:  *
   9:  *	12/20/94 - Missing casts caused errors in reporting on swapped
  10:  *		   processes - sms
  11:  *	1/7/93 - Heavily revised when the symbol table format changed - sms
  12:  *
  13:  *	ps - process status
  14:  *	Usage:  ps [ acgklnrtuwxU# ] [ corefile [ swapfile [ system ] ] ]
  15:  */
  16: 
  17: #include <sys/param.h>
  18: #include <stdio.h>
  19: #include <pwd.h>
  20: #include <a.out.h>
  21: #include <ctype.h>
  22: #include <string.h>
  23: #include <sys/file.h>
  24: #include <sys/ioctl.h>
  25: #include <sys/stat.h>
  26: #include <sys/user.h>
  27: #include <sys/proc.h>
  28: #include <utmp.h>
  29: #include <OLD/psout.h>
  30: 
  31: #define within(x,y,z)   (((unsigned)(x) >= (y)) && ((unsigned)(x) < (z)))
  32: #define round(x,y) ((long) ((((long) (x) + (long) (y) - 1L) / (long) (y)) * (long) (y)))
  33: 
  34:     struct  nlist nl[4];
  35: #define X_PROC      0
  36: #define X_NPROC     1
  37: #define X_HZ        2
  38: 
  39: /*
  40:  * This is no longer the size of a symbol's name, symbols can be much
  41:  * larger now.  This define says how many characters of a symbol's name
  42:  * to save in the wait channel name.  A new define has been created to
  43:  * limit the size of symbol string read from the string table.
  44: */
  45: #define NNAMESIZ    8
  46: #define MAXSYMLEN   32
  47: 
  48:     struct  proc *mproc, proc[8];
  49:     struct  user    u;
  50:     int hz;
  51:     int chkpid  = 0;
  52:     char    aflg;   /* -a: all processes, not just mine */
  53:     char    cflg;   /* -c: not complete listing of args, just comm. */
  54:     char    gflg;   /* -g: complete listing including group headers, etc */
  55:     char    kflg;   /* -k: read from core file instead of real memory */
  56:     char    lflg;   /* -l: long listing form */
  57:     char    nflg;   /* -n: numeric wchans */
  58:     char    rflg;   /* -r: raw output in style <psout.h> */
  59:     char    uflg;   /* -u: user name */
  60:     char    wflg;   /* -w[w]: wide terminal */
  61:     char    xflg;   /* -x: ALL processes, even those without ttys */
  62:     char    Uflg;   /* -U: update the private list */
  63:     char    *tptr, *mytty;
  64:     char    *uname;
  65:     int file;
  66:     int nproc;
  67:     int nchans;
  68:     int nttys;
  69:     char    *psdb   = "/var/run/psdatabase";
  70:     int npr;            /* number of processes found so far */
  71:     int twidth;         /* terminal width */
  72:     int cmdstart;       /* start position for command field */
  73:     char    *memf;          /* name of kernel memory file */
  74:     char    *kmemf = "/dev/kmem";   /* name of physical memory file */
  75:     char    *swapf;         /* name of swap file to use */
  76:     char    *nlistf;        /* name of symbol table file to use */
  77:     int kmem, mem, swap;
  78: 
  79: /*
  80:  *	Structure for the unix wchan table
  81:  */
  82: typedef struct wchan {
  83:     char    cname[NNAMESIZ];
  84:     unsigned    caddr;
  85:     } WCHAN;
  86: 
  87:     WCHAN   *wchand;
  88: 
  89: extern  char    *calloc(), *malloc(), *realloc(), *ttyname();
  90:     char    *gettty(), *getptr(), *getchan();
  91:     int pscomp(), wchancomp();
  92: extern  off_t   lseek();
  93: 
  94: /*
  95:  * 256 terminals was not only wasteful but unrealistic.  For one thing
  96:  * 2.11BSD uses bit 7 of the minor device (for almost all terminal interfaces)
  97:  * to indicate direct/modem status - this means that 128 terminals is
  98:  * a better maximum number of terminals, for another thing the system can't
  99:  * support 256 terminals - other resources (memory, files, processes) will
 100:  * have been exhausted long ago.  If 'ps' complains about too many terminals
 101:  * it is time to clean up /dev!
 102:  */
 103: #define MAXTTYS     160 /* 128 plus a few extra */
 104: 
 105: struct  ttys {
 106:     char    name[14];   /* MAXNAMLEN uses too much memory,  besides */
 107:                 /* device names tend to be very short */
 108:     dev_t   ttyd;
 109:     } allttys[MAXTTYS];
 110: 
 111: struct  map {
 112:     off_t   b1, e1; off_t   f1;
 113:     off_t   b2, e2; off_t   f2;
 114:     };
 115: 
 116:     struct  winsize ws;
 117:     struct  map datmap;
 118:     struct  psout *outargs;     /* info for first npr processes */
 119: 
 120: main (argc, argv)
 121: char    **argv;
 122: {
 123:     int uid, euid, puid, nread;
 124:     register int i, j;
 125:     char    *ap;
 126:     register struct proc    *procp;
 127: 
 128: /*
 129:  * Can't initialize unions and we need the macros from a.out.h, so the
 130:  * namelist is set up at run time.
 131: */
 132:     nl[X_PROC].n_un.n_name = "_proc";
 133:     nl[X_NPROC].n_un.n_name = "_nproc";
 134:     nl[X_HZ].n_un.n_name = "_hz";
 135: 
 136:     if  ((ioctl(fileno(stdout), TIOCGWINSZ, &ws) != -1 &&
 137:          ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
 138:          ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) ||
 139:          ws.ws_col == 0)
 140:         twidth = 80;
 141:     else
 142:         twidth = ws.ws_col;
 143: 
 144:     argc--, argv++;
 145:     if (argc > 0)   {
 146:         ap  = argv [0];
 147:         while (*ap) switch (*ap++)  {
 148:         case '-':
 149:             break;
 150: 
 151:         case 'a':
 152:             aflg++;
 153:             break;
 154: 
 155:         case 'c':
 156:             cflg++;
 157:             break;
 158: 
 159:         case 'g':
 160:             gflg++;
 161:             break;
 162: 
 163:         case 'k':
 164:             kflg++;
 165:             break;
 166: 
 167:         case 'l':
 168:             lflg    = 1;
 169:             break;
 170: 
 171:         case 'n':
 172:             nflg++;
 173:             lflg    = 1;
 174:             break;
 175: 
 176:         case 'r':
 177:             rflg++;
 178:             break;
 179: 
 180:         case 't':
 181:             if (*ap)
 182:                 tptr = ap;
 183:             else if ((tptr = ttyname(0)) != 0) {
 184:                 tptr = strcpy(mytty, tptr);
 185:                 if (strncmp(tptr, "/dev/", 5) == 0)
 186:                     tptr += 5;
 187:             }
 188:             if (strncmp(tptr, "tty", 3) == 0)
 189:                 tptr += 3;
 190:             aflg++;
 191:             gflg++;
 192:             if (tptr && *tptr == '?')
 193:                 xflg++;
 194:             while (*ap)
 195:                 ap++;
 196:             break;
 197: 
 198:         case 'u':
 199:             uflg    = 1;
 200:             break;
 201: 
 202:         case 'U':
 203:             Uflg++;
 204:             break;
 205: 
 206:         case 'w':
 207:             if (wflg)
 208:                 twidth  = BUFSIZ;
 209:             else if (twidth < 132)
 210:                 twidth  = 132;
 211:             wflg++;
 212:             break;
 213: 
 214:         case 'x':
 215:             xflg++;
 216:             break;
 217: 
 218:         default:
 219:             if (!isdigit(ap[-1]))
 220:                 break;
 221:             chkpid  = atoi(--ap);
 222:             *ap = '\0';
 223:             aflg++;
 224:             xflg++;
 225:             break;
 226:         }
 227:     }
 228: 
 229:     openfiles(argc, argv);
 230:     getkvars(argc, argv);
 231:     lseek(kmem,(off_t)nl[X_PROC].n_value,0);
 232:     uid = getuid();
 233:     euid = geteuid();
 234:     mytty = ttyname(0);
 235:     if (!strncmp(mytty,"/dev/",5)) mytty += 5;
 236:     if (!strncmp(mytty,"tty",3)) mytty += 3;
 237:     printhdr();
 238:     for (i = 0; i < nproc; i += 8)  {
 239:         j = nproc - i;
 240:         if (j > 8)
 241:             j = 8;
 242:         j *= sizeof (struct proc);
 243:         if ((nread = read(kmem, (char *) proc, j)) != j) {
 244:             cantread("proc table", kmemf);
 245:             if (nread == -1)
 246:                 break;
 247:             }
 248:         for (j = nread / sizeof (struct proc) - 1; j >= 0; j--) {
 249:             mproc   = &proc[j];
 250:             procp   = mproc;
 251:             /* skip processes that don't exist */
 252:             if (procp->p_stat == 0)
 253:                 continue;
 254:             /* skip those without a tty unless -x */
 255:             if (procp->p_pgrp == 0 && xflg == 0)
 256:                 continue;
 257:             /* skip group leaders on a tty unless -g, -x, or -t.. */
 258:             if (!tptr && !gflg && !xflg && procp->p_ppid == 1)
 259:                 continue;
 260:             /* -g also skips those where **argv is "-" - see savcom */
 261:             puid = procp->p_uid;
 262:             /* skip other peoples processes unless -a or a specific pid */
 263:             if ((uid != puid && euid != puid && aflg == 0) ||
 264:                 (chkpid != 0 && chkpid != procp->p_pid))
 265:                 continue;
 266:             if (savcom(puid))
 267:                 npr++;
 268:         }
 269:     }
 270:     fixup(npr);
 271:     for (i = 0; i < npr; i++) {
 272:         register int    cmdwidth = twidth - cmdstart - 2;
 273:         register struct psout *a = &outargs[i];
 274: 
 275:         if (rflg) {
 276:             if (write(1, (char *) a, sizeof (*a)) != sizeof (*a))
 277:                 perror("write");
 278:             continue;
 279:             }
 280:         else    if (lflg)
 281:                 lpr(a);
 282:             else    if (uflg)
 283:                     upr(a);
 284:                 else
 285:                     spr(a);
 286:         if (cmdwidth < 0)
 287:             cmdwidth = 80 - cmdstart - 2;
 288:         if (a->o_stat == SZOMB)
 289:             printf("%.*s", cmdwidth, " <defunct>");
 290:         else if (a->o_pid == 0)
 291:             printf("%.*s", cmdwidth, " swapper");
 292:         else
 293:             printf(" %.*s", twidth - cmdstart - 2, cflg ?  a->o_comm : a->o_args);
 294:         putchar('\n');
 295:         }
 296:     exit(!npr);
 297: }
 298: 
 299: getdev()
 300: {
 301:     register DIR *df;
 302:     register struct direct *dbuf;
 303: 
 304:     if (chdir("/dev") < 0) {
 305:         perror("/dev");
 306:         exit(1);
 307:     }
 308:     if ((df = opendir(".")) == NULL) {
 309:         fprintf(stderr, "Can't open . in /dev\n");
 310:         exit(1);
 311:     }
 312:     while (dbuf = readdir(df))
 313:         maybetty(dbuf->d_name);
 314:     closedir(df);
 315: }
 316: 
 317: /*
 318:  * Attempt to avoid stats by guessing minor device
 319:  * numbers from tty names.  Console is known,
 320:  * know that r(hp|up|mt) are unlikely as are different mem's,
 321:  * floppy, null, tty, etc.
 322:  */
 323: maybetty(cp)
 324:     register char *cp;
 325: {
 326:     register struct ttys *dp;
 327:     struct stat stb;
 328: 
 329:     switch (cp[0]) {
 330: 
 331:     case 'c':
 332:         if (!strcmp(cp, "console"))
 333:             break;
 334:         /* cu[la]? are possible!?! don't rule them out */
 335:         break;
 336: 
 337:     case 'd':
 338:         if (!strcmp(cp, "drum"))
 339:             return;
 340:         break;
 341: 
 342:     case 'f':
 343:         if (!strcmp(cp, "floppy"))
 344:             return;
 345:         break;
 346: 
 347:     case 'k':
 348:         if (!strcmp(cp, "kUmem") || !strcmp(cp, "kmem"))
 349:             return;
 350:         if (!strcmp(cp, "klog"))
 351:             return;
 352:         break;
 353: 
 354:     case 'r':
 355: #define is(a,b) cp[1] == 'a' && cp[2] == 'b'
 356:         if (is(h,p) || is(r,a) || is(u,p) || is(h,k) || is(x,p)
 357:             || is(r,b) || is(r,l) || is(m,t)) {
 358:             if (isdigit(cp[3]))
 359:                 return;
 360:         }
 361:         break;
 362: 
 363:     case 'm':
 364:         if (!strcmp("mem", cp))
 365:             return;
 366:         if (cp[1] == 't')
 367:             return;
 368:         break;
 369: 
 370:     case 'n':
 371:         if (!strcmp(cp, "null"))
 372:             return;
 373:         if (!strncmp(cp, "nrmt", 4))
 374:             return;
 375:         break;
 376: 
 377:     case 'p':
 378:         if (cp[1] == 't' && cp[2] == 'y')
 379:             return;
 380:         break;
 381:     }
 382:     if (nttys >= MAXTTYS) {
 383:         fprintf(stderr, "ps: tty table overflow\n");
 384:         exit(1);
 385:     }
 386:     dp = &allttys[nttys++];
 387:     (void)strcpy(dp->name, cp);
 388:     if (Uflg) {
 389:         if (stat(dp->name, &stb) == 0 &&
 390:            (stb.st_mode&S_IFMT)==S_IFCHR)
 391:             dp->ttyd = stb.st_rdev;
 392:         else {
 393:             nttys--;
 394:             return;
 395:         }
 396:     } else
 397:         dp->ttyd = -1;
 398: }
 399: 
 400: savcom(puid)
 401: {
 402:     char    *tp;
 403:     off_t   addr;
 404:     off_t   daddr, saddr;
 405:     register struct psout   *a;
 406:     register struct proc    *procp  = mproc;
 407:     register struct user    *up = &u;
 408:     long    txtsiz, datsiz, stksiz;
 409:     int septxt;
 410: 
 411:     if (procp->p_flag & SLOAD) {
 412:         addr = ctob((off_t) procp->p_addr);
 413:         daddr = ctob((off_t) procp->p_daddr);
 414:         saddr = ctob((off_t) procp->p_saddr);
 415:         file = mem;
 416:     }
 417:     else {
 418:         addr = (off_t)procp->p_addr << 9;
 419:         daddr = (off_t)procp->p_daddr << 9;
 420:         saddr = (off_t)procp->p_saddr << 9;
 421:         file = swap;
 422:     }
 423:     lseek(file, addr, 0);
 424:     if (read(file, (char *) up, sizeof (u)) != sizeof (u))
 425:         return(0);
 426: 
 427:     txtsiz = ctob(up->u_tsize); /* set up address maps for user pcs */
 428:     datsiz = ctob(up->u_dsize);
 429:     stksiz = ctob(up->u_ssize);
 430:     septxt = up->u_sep;
 431:     datmap.b1 = (septxt ?  0 : round(txtsiz, TXTRNDSIZ));
 432:     datmap.e1 = datmap.b1 + datsiz;
 433:     datmap.f1 = daddr;
 434:     datmap.f2 = saddr;
 435:     datmap.b2 = stackbas(stksiz);
 436:     datmap.e2 = stacktop(stksiz);
 437:     tp = gettty();
 438:     if ((tptr && strncmp(tptr,tp,2)) || (strncmp(mytty, tp, 2) && !aflg))
 439:         return(0);
 440:     a = &outargs[npr];      /* saving com starts here */
 441:     a->o_uid = puid;
 442:     a->o_pid = procp->p_pid;
 443:     a->o_flag = procp->p_flag;
 444:     a->o_ppid = procp->p_ppid;
 445:     a->o_cpu  = procp->p_cpu;
 446:     a->o_pri = procp->p_pri;
 447:     a->o_nice = procp->p_nice;
 448:     a->o_addr0 = procp->p_addr;
 449:     a->o_size = ctod(procp->p_dsize + procp->p_ssize + USIZE);
 450:     a->o_wchan = procp->p_wchan;
 451:     a->o_pgrp = procp->p_pgrp;
 452:     strncpy(a->o_tty, tp, sizeof (a->o_tty));
 453:     a->o_ttyd = tp[0] == '?' ?  -1 : up->u_ttyd;
 454:     a->o_stat = procp->p_stat;
 455:     a->o_flag = procp->p_flag;
 456: 
 457:     if (a->o_stat == SZOMB)
 458:         return(1);
 459:     a->o_utime = up->u_ru.ru_utime;
 460:     a->o_stime = up->u_ru.ru_stime;
 461:     a->o_cutime = up->u_cru.ru_utime;
 462:     a->o_cstime = up->u_cru.ru_stime;
 463:     a->o_sigs = (int)up->u_signal[SIGINT] + (int)up->u_signal[SIGQUIT];
 464:     a->o_uname[0] = 0;
 465:     strncpy(a->o_comm, up->u_comm, MAXCOMLEN);
 466: 
 467:     if (cflg)
 468:         return (1);
 469:     else
 470:         return(getcmd(a,saddr));
 471: }
 472: 
 473: char *
 474: gettty()
 475: {
 476:     register int tty_step;
 477:     register char *p;
 478: 
 479:     if (u.u_ttyp)
 480:         for (tty_step = 0;tty_step < nttys;++tty_step)
 481:             if (allttys[tty_step].ttyd == u.u_ttyd) {
 482:                 p = allttys[tty_step].name;
 483:                 if (!strncmp(p,"tty",3))
 484:                     p += 3;
 485:                 return(p);
 486:             }
 487:     return("?");
 488: }
 489: 
 490: /*
 491:  * fixup figures out everybodys name and sorts into a nice order.
 492:  */
 493: fixup(np)
 494: register int np;
 495: {
 496:     register int i;
 497:     register struct passwd  *pw;
 498: 
 499:     if (uflg) {
 500:         /*
 501: 		 * If we want names, traverse the password file. For each
 502: 		 * passwd entry, look for it in the processes.
 503: 		 * In case of multiple entries in the password file we believe
 504: 		 * the first one (same thing ls does).
 505: 		 */
 506:         while ((pw = getpwent()) != (struct passwd *) NULL) {
 507:             for (i = 0; i < np; i++)
 508:                 if (outargs[i].o_uid == pw->pw_uid) {
 509:                     if (outargs[i].o_uname[0] == 0)
 510:                         strcpy(outargs[i].o_uname, pw->pw_name);
 511:                     }
 512:             }
 513:         }
 514:     qsort(outargs, np, sizeof (outargs[0]), pscomp);
 515: }
 516: 
 517: pscomp(x1, x2)
 518: register struct psout   *x1, *x2;
 519: {
 520:     register int c;
 521: 
 522:     c = (x1)->o_ttyd - (x2)->o_ttyd;
 523:     if (c == 0)
 524:         c = (x1)->o_pid - (x2)->o_pid;
 525:     return(c);
 526: }
 527: 
 528: wchancomp(x1, x2)
 529: register WCHAN  *x1, *x2;
 530: {
 531:     if (x1->caddr > x2->caddr)
 532:         return(1);
 533:     else if (x1->caddr == x2->caddr)
 534:         return(0);
 535:     else
 536:         return(-1);
 537: }
 538: 
 539: char    *
 540: getptr(adr)
 541: char    **adr;
 542: {
 543:     char    *ptr = 0;
 544:     register char   *p, *pa;
 545:     register int    i;
 546: 
 547:     pa = (char *)adr;
 548:     p  = (char *)&ptr;
 549:     for (i = 0; i < sizeof (ptr); i++)
 550:         *p++ = getbyte(pa++);
 551:     return(ptr);
 552: }
 553: 
 554: getbyte(adr)
 555: register char   *adr;
 556: {
 557:     register struct map *amap = &datmap;
 558:     char    b;
 559:     off_t   saddr;
 560: 
 561:     if (!within(adr, amap->b1, amap->e1))
 562:         if (within(adr, amap->b2, amap->e2))
 563:             saddr = (unsigned) adr + amap->f2 - amap->b2;
 564:         else    return(0);
 565:     else    saddr   = (unsigned) adr + amap->f1 - amap->b1;
 566:     if (lseek(file, saddr, 0) == (off_t) -1 || read (file, &b, 1) < 1)
 567:         return(0);
 568:     return((unsigned) b);
 569: }
 570: 
 571: addchan(name, caddr)
 572:     char    *name;
 573:     unsigned caddr;
 574:     {
 575:     static  int left = 0;
 576:     register WCHAN  *wp;
 577: 
 578:     if  (left == 0)
 579:         {
 580:         if  (wchand)
 581:             {
 582:             left = 50;
 583:             wchand = (WCHAN *)realloc(wchand, (nchans + left) *
 584:                         sizeof (struct wchan));
 585:             }
 586:         else
 587:             {
 588:             left = 300;
 589:             wchand = (WCHAN *)malloc(left * sizeof (struct wchan));
 590:             }
 591:         if  (!wchand)
 592:             {
 593:             fprintf(stderr, "ps: out of wait channel memory\n");
 594:             nflg++;
 595:             return;
 596:             }
 597:         }
 598:     wp = &wchand[nchans++];
 599:     left--;
 600:     strncpy(wp->cname, name, NNAMESIZ - 1);
 601:     wp->cname[NNAMESIZ-1] = '\0';
 602:     wp->caddr = caddr;
 603:     }
 604: 
 605: char    *
 606: getchan(chan)
 607: register unsigned int chan;
 608: {
 609:     register int    i;
 610:     register char   *prevsym;
 611: 
 612:     prevsym = "";
 613:     if (chan)
 614:         for (i = 0; i < nchans; i++)    {
 615:             if (wchand[i].caddr > chan)
 616:                 return (prevsym);
 617:             prevsym = wchand[i].cname;
 618:             }
 619:     return(prevsym);
 620: }
 621: 
 622: nlist()
 623:     {
 624:     register FILE   *nlistf_fp;
 625:     FILE    *strfp;
 626:     register struct nlist *nnn;
 627:     int flag, nsyms;
 628:     struct nlist    nbuf;
 629:     struct xexec    hbuf;
 630:     char    name[MAXSYMLEN + 2];
 631:     int nllen;
 632:     off_t   sa, stroff;
 633: 
 634:     bzero(name, sizeof (name));
 635:     nllen = sizeof(nl) / sizeof(struct nlist);
 636:     if  (!(nlistf_fp = fopen(nlistf,"r")))
 637:         perrexit(nlistf);
 638:     strfp = fopen(nlistf, "r");
 639:     if  (fread(&hbuf,sizeof(hbuf),1,nlistf_fp) != 1)
 640:         {
 641:         fputs("Invalid symbol table\n",stderr);
 642:         exit(1);
 643:         }
 644:     if  (N_BADMAG(hbuf.e))
 645:         {
 646:         fprintf(stderr,"%s: bad magic number\n",nlistf);
 647:         exit(1);
 648:         }
 649:     nsyms = hbuf.e.a_syms / sizeof (struct nlist);
 650:     if  (nsyms == 0)
 651:         {
 652:         fprintf(stderr,"%s: no symbols\n",nlistf);
 653:         exit(1);
 654:         }
 655:     sa = N_SYMOFF(hbuf);
 656:     stroff = N_STROFF(hbuf);
 657:     fseek(nlistf_fp, sa, L_SET);
 658: 
 659:     addchan("u", 0140000);      /* XXX - see comment below */
 660:     while   (nsyms--)
 661:         {
 662:         fread(&nbuf,sizeof(nbuf),1,nlistf_fp);
 663:         if  ((nbuf.n_type & N_EXT) == 0)
 664:             continue;
 665:         flag = nbuf.n_type & N_TYPE;
 666: /*
 667:  * Now read the symbol string.  Can't rely on having enough memory to
 668:  * hold the entire string table, so we do a seek+read for each name.  Luckily
 669:  * this is only done for global symbols, which cuts down the work done.
 670: */
 671:         fseek(strfp, nbuf.n_un.n_strx + stroff, L_SET);
 672:         fread(name, MAXSYMLEN, 1, strfp);
 673: 
 674: /*
 675:  * Skip over anything which isn't an external data or bss symbol.
 676:  * Advantage was taken of the facts that 1) 'ps' is highly machine
 677:  * dependent and 2) _u on a pdp-11 is not likely to change _ever_.
 678:  * The reason behind this is to avoid matching on absolute symbols created
 679:  * during the unix/netnix cross binding.
 680: */
 681:         if  (!(flag == N_DATA || flag == N_BSS))
 682:             continue;
 683:         if  (!nflg)
 684:             addchan(name + 1, nbuf.n_value);
 685:         if  (nllen)
 686:             {
 687:             for (nnn = nl; nnn->n_un.n_name; nnn++)
 688:                 {
 689:                 if  (!strcmp(nnn->n_un.n_name, name))
 690:                     {
 691:                     nnn->n_value = nbuf.n_value;
 692:                     nnn->n_type = nbuf.n_type;
 693:                     nnn->n_ovly = nbuf.n_ovly;
 694:                     --nllen;
 695:                     break;
 696:                     }
 697:                 }
 698:             }
 699:         }
 700:     fclose(nlistf_fp);
 701:     fclose(strfp);
 702:     if  (!nflg)
 703:         qsort(wchand,nchans,sizeof(WCHAN),wchancomp);
 704:     }
 705: 
 706: perrexit(msg)
 707: char    *msg;
 708: {
 709:     perror(msg);
 710:     exit(1);
 711: }
 712: 
 713: writepsdb()
 714: {
 715:     register FILE   *fp;
 716:     int nllen;
 717: 
 718:     setuid(getuid());
 719:     if (!(fp = fopen (psdb, "w")))
 720:         perrexit(psdb);
 721:     else
 722:         fchmod(fileno(fp),0644);
 723:     nllen = sizeof(nl) / sizeof(struct nlist);
 724:     fwrite(nlistf,strlen(nlistf) + 1,1,fp);
 725:     fwrite((char *)&nllen,sizeof(nllen),1,fp);
 726:     fwrite((char *)&nttys,sizeof(nttys),1,fp);
 727:     fwrite((char *)&nchans,sizeof(nchans),1,fp);
 728:     fwrite((char *)nl,sizeof(struct nlist),nllen,fp);
 729:     fwrite((char *)allttys,sizeof(struct ttys),nttys,fp);
 730:     fwrite((char *)wchand,sizeof(WCHAN),nchans,fp);
 731:     fclose(fp);
 732: }
 733: 
 734: char    *
 735: readpsdb()
 736: {
 737:     register int    i;
 738:     register FILE   *fp;
 739:     register WCHAN  *ccc;
 740:     static  char    unamebuf[MAXPATHLEN + 1];
 741:     char    *p = unamebuf;
 742:     int nllen;
 743: 
 744:     if ((fp = fopen(psdb, "r")) == NULL)
 745:         perrexit(psdb);
 746: 
 747:     while ((*p= getc(fp)) != '\0')
 748:         p++;
 749:     fread(&nllen, sizeof nllen, 1, fp);
 750:     fread(&nttys, sizeof nttys, 1, fp);
 751:     fread(&nchans, sizeof nchans, 1, fp);
 752:     fread(nl, sizeof (struct nlist), nllen, fp);
 753:     fread(allttys, sizeof (struct ttys), nttys, fp);
 754:     if (!nflg)
 755:         if (!(wchand = (WCHAN *)calloc(nchans, sizeof(WCHAN)))) {
 756:             fputs("Too many symbols\n",stderr);
 757:             exit(1);
 758:         }
 759:         else for (i = 0, ccc = wchand; i < nchans; i++) {
 760:             fread((char *) ccc, sizeof(WCHAN), 1, fp);
 761:             ccc++;
 762:         }
 763:     return(unamebuf);
 764: }
 765: 
 766: openfiles(argc, argv)
 767: char    **argv;
 768: {
 769:     if (kflg)
 770:         kmemf = argc > 1 ?  argv[1] : "/usr/sys/core";
 771:     kmem = open(kmemf, 0);
 772:     if (kmem < 0)
 773:         perrexit(kmemf);
 774:     if (!kflg)
 775:         memf = "/dev/mem";
 776:     else
 777:         memf = kmemf;
 778:     mem = open(memf, 0);
 779:     if (mem < 0)
 780:         perrexit(memf);
 781:     swapf = argc > 2 ?  argv[2] : "/dev/swap";
 782:     swap = open(swapf, 0);
 783:     if (swap < 0)
 784:         perrexit(swapf);
 785: }
 786: 
 787: getkvars(argc,argv)
 788: int argc;
 789: char    **argv;
 790: {
 791:     struct  stat    st;
 792: 
 793:     nlistf = argc > 3 ?  argv[3] : "/unix";
 794:     if (Uflg) {
 795:         nlist();
 796:         getdev();
 797:         writepsdb();
 798:         exit(0);
 799:     }
 800:     else if (stat(psdb, &st) == 0) {
 801:         uname = readpsdb();
 802:         if (strcmp(uname,nlistf)) {
 803:             /*
 804: 			 * Let addchan() do the work.
 805: 			 */
 806:             nchans = 0;
 807:             free((char *)wchand);
 808:             nlist();
 809:         }
 810:     }
 811:     else {
 812:         nlist();
 813:         getdev();
 814:     }
 815: 
 816:     /* find number of procs */
 817:     if (nl[X_NPROC].n_value) {
 818:         lseek(kmem,(off_t)nl[X_NPROC].n_value,0);
 819:         if (read(kmem,(char *)&nproc,sizeof(nproc)) != sizeof(nproc)) {
 820:             perror(kmemf);
 821:             exit(1);
 822:         }
 823:     }
 824:     else {
 825:         fputs("nproc not in namelist\n",stderr);
 826:         exit(1);
 827:     }
 828:     outargs = (struct psout *)calloc(nproc, sizeof(struct psout));
 829:     if (!outargs) {
 830:         fputs("ps: not enough memory for saving info\n",stderr);
 831:         exit(1);
 832:     }
 833: 
 834:     /* find value of hz */
 835:     lseek(kmem,(off_t)nl[X_HZ].n_value,0);
 836:     read(kmem,(char *)&hz,sizeof(hz));
 837: }
 838: 
 839: 
 840: char *uhdr = "USER       PID NICE SZ TTY TIME";
 841: upr(a)
 842: register struct psout   *a;
 843: {
 844:     printf("%-8.8s%6u%4d%4d %-2.2s",a->o_uname,a->o_pid,a->o_nice,a->o_size,a->o_tty);
 845:     ptime(a);
 846: }
 847: 
 848: char *shdr = "   PID TTY TIME";
 849: spr (a)
 850: register struct psout   *a;
 851: {
 852:     printf("%6u %-2.2s",a->o_pid,a->o_tty);
 853:     ptime(a);
 854: }
 855: 
 856: char *lhdr = "  F S   UID   PID  PPID CPU PRI NICE  ADDR  SZ WCHAN    TTY TIME";
 857: lpr(a)
 858: register struct psout *a;
 859: {
 860:     static char clist[] = "0SWRIZT";
 861: 
 862:     printf("%3o %c%6u%6u%6u%4d%4d%4d%7o%4d",
 863: 0377 & a->o_flag,clist[a->o_stat],a->o_uid,a->o_pid,
 864: a->o_ppid,a->o_cpu & 0377,a->o_pri,a->o_nice,a->o_addr0,a->o_size);
 865:     if (nflg)
 866:         if (a->o_wchan)
 867:             printf("%*.*o",NNAMESIZ, NNAMESIZ, a->o_wchan);
 868:         else
 869:             fputs("       ",stdout);
 870:     else
 871:         printf(" %-*.*s",NNAMESIZ, NNAMESIZ, getchan(a->o_wchan));
 872:     printf(" %-2.2s",a->o_tty);
 873:     ptime(a);
 874: }
 875: 
 876: ptime(a)
 877: struct psout    *a;
 878: {
 879:     time_t  tm;
 880: 
 881:     tm = (a->o_utime + a->o_stime + 30) / hz;
 882:     printf("%3ld:",tm / 60);
 883:     tm %= 60;
 884:     printf(tm < 10 ? "0%ld" : "%ld",tm);
 885: }
 886: 
 887: getcmd(a,addr)
 888: off_t   addr;
 889: register struct psout   *a;
 890: {
 891:     /* amount of top of stack to examine for args */
 892: #define ARGLIST (1024/sizeof(int))
 893:     register int *ip;
 894:     register char   *cp, *cp1;
 895:     char    c, **ap;
 896:     int cc, nbad, abuf [ARGLIST];
 897: 
 898:     a->o_args[0] = 0;   /* in case of early return */
 899:     addr += ctob((off_t) mproc->p_ssize) - ARGLIST*sizeof(int);
 900: 
 901:     /* look for sh special */
 902:     lseek(file, addr + ARGLIST*sizeof(int) - sizeof (char **), 0);
 903:     if (read(file, (char *) &ap, sizeof (char *)) != sizeof (char *))
 904:         return (1);
 905:     if (ap) {
 906:         char    b[82];
 907:         char    *bp = b;
 908:         while ((cp = getptr(ap++)) && cp && (bp < b+sizeof (a->o_args)) ) {
 909:             nbad    = 0;
 910:             while ((c = getbyte(cp++)) && (bp < b+sizeof (a->o_args))) {
 911:                 if (c<' ' || c > '~') {
 912:                     if (nbad++ > 3)
 913:                         break;
 914:                     continue;
 915:                     }
 916:                 *bp++ = c;
 917:                 }
 918:             *bp++ = ' ';
 919:             }
 920:         *bp++ = 0;
 921:         (void)strcpy(a->o_args, b);
 922:         return(1);
 923:         }
 924: 
 925:     lseek(file, addr, 0);
 926:     if (read(file, (char *) abuf, sizeof (abuf)) != sizeof (abuf))
 927:         return (1);
 928:     abuf[ARGLIST-1] = 0;
 929:     for (ip = &abuf[ARGLIST-2]; ip > abuf;) {
 930:         if (*--ip == -1 || *ip == 0)    {
 931:             cp = (char *) (ip + 1);
 932:             if (*cp == '\0')
 933:                 cp++;
 934:             nbad = 0;
 935:             for (cp1 = cp; cp1 < (char *) &abuf[ARGLIST]; cp1++)    {
 936:                 cc = *cp1 & 0177;
 937:                 if (cc == 0)
 938:                     *cp1 = ' ';
 939:                 else if (cc < ' ' || cc > 0176) {
 940:                     if (++nbad >= 5)    {
 941:                         *cp1++  = ' ';
 942:                         break;
 943:                         }
 944:                     *cp1 = '?';
 945:                 } else if (cc == '=')   {
 946:                     *cp1 = '\0';
 947:                     while (cp1 > cp && *--cp1 != ' ')
 948:                         *cp1 = '\0';
 949:                     break;
 950:                     }
 951:                 }
 952:             while (*--cp1 == ' ')
 953:                 *cp1 = 0;
 954:             (void)strcpy(a->o_args, cp);
 955: garbage:
 956:             cp = a->o_args;
 957:             if (cp[0] == '-' && cp[1] <= ' ' || cp[0] == '?' || cp[0] <= ' ')   {
 958:                 strcat(cp, " (");
 959:                 strcat(cp, u.u_comm);
 960:                 strcat(cp, ")");
 961:                 }
 962:             cp[63] = 0; /* max room in psout is 64 chars */
 963:             if (xflg || gflg || tptr || cp[0] != '-')
 964:                 return(1);
 965:             return(0);
 966:             }
 967:         }
 968:     goto garbage;
 969: }
 970: 
 971: printhdr()
 972: {
 973:     register char   *hdr, *cmdstr   = " COMMAND";
 974: 
 975:     if (rflg)
 976:         return;
 977:     if (lflg && uflg) {
 978:         fputs("ps: specify only one of l and u.\n",stderr);
 979:         exit(1);
 980:     }
 981:     hdr = lflg ? lhdr : (uflg ? uhdr : shdr);
 982:     fputs(hdr,stdout);
 983:     cmdstart = strlen(hdr);
 984:     if (cmdstart + strlen(cmdstr) >= twidth)
 985:         cmdstr = " CMD";
 986:     printf("%s\n", cmdstr);
 987:     fflush(stdout);
 988: }
 989: 
 990: cantread(what, fromwhat)
 991:     char *what, *fromwhat;
 992: {
 993: 
 994:     fprintf(stderr, "ps: error reading %s from %s\n", what, fromwhat);
 995: }

Defined functions

addchan defined in line 571; used 2 times
cantread defined in line 990; used 1 times
fixup defined in line 493; used 1 times
getbyte defined in line 554; used 2 times
getchan defined in line 605; used 2 times
getcmd defined in line 887; used 1 times
getdev defined in line 299; used 2 times
getkvars defined in line 787; used 1 times
getptr defined in line 539; used 2 times
gettty defined in line 473; used 2 times
lpr defined in line 857; used 1 times
main defined in line 120; never used
maybetty defined in line 323; used 1 times
nlist defined in line 622; used 3 times
openfiles defined in line 766; used 1 times
perrexit defined in line 706; used 6 times
printhdr defined in line 971; used 1 times
pscomp defined in line 517; used 2 times
ptime defined in line 876; used 3 times
readpsdb defined in line 734; used 1 times
savcom defined in line 400; used 1 times
spr defined in line 849; used 1 times
upr defined in line 841; used 1 times
wchancomp defined in line 528; used 2 times
writepsdb defined in line 713; used 1 times

Defined variables

Uflg defined in line 62; used 3 times
aflg defined in line 52; used 5 times
allttys defined in line 109; used 5 times
cflg defined in line 53; used 3 times
chkpid defined in line 51; used 3 times
cmdstart defined in line 72; used 5 times
datmap defined in line 117; used 8 times
file defined in line 65; used 10 times
gflg defined in line 54; used 4 times
hz defined in line 50; used 3 times
kflg defined in line 55; used 3 times
kmem defined in line 77; used 8 times
kmemf defined in line 74; used 6 times
lflg defined in line 56; used 5 times
lhdr defined in line 856; used 1 times
mem defined in line 77; used 3 times
memf defined in line 73; used 4 times
mproc defined in line 48; used 4 times
mytty defined in line 63; used 7 times
nchans defined in line 67; used 12 times
nflg defined in line 57; used 6 times
nl defined in line 34; used 12 times
nlistf defined in line 76; used 9 times
npr defined in line 70; used 5 times
nproc defined in line 66; used 6 times
nttys defined in line 68; used 10 times
outargs defined in line 118; used 9 times
proc defined in line 48; used 2 times
psdb defined in line 69; used 5 times
rflg defined in line 58; used 3 times
shdr defined in line 848; used 1 times
swap defined in line 77; used 3 times
swapf defined in line 75; used 3 times
tptr defined in line 63; used 14 times
twidth defined in line 71; used 8 times
u defined in line 49; used 7 times
uflg defined in line 59; used 5 times
uhdr defined in line 840; used 1 times
uname defined in line 64; used 2 times
wchand defined in line 87; used 13 times
wflg defined in line 60; used 2 times
ws defined in line 116; used 5 times
xflg defined in line 61; used 6 times

Defined struct's

map defined in line 111; used 4 times
ttys defined in line 105; used 6 times
wchan defined in line 82; used 4 times

Defined typedef's

WCHAN defined in line 85; used 11 times

Defined macros

ARGLIST defined in line 892; used 6 times
MAXSYMLEN defined in line 46; used 2 times
MAXTTYS defined in line 103; used 2 times
NNAMESIZ defined in line 45; used 7 times
X_HZ defined in line 37; used 2 times
X_NPROC defined in line 36; used 3 times
X_PROC defined in line 35; used 2 times
is defined in line 355; used 8 times
round defined in line 32; used 1 times
within defined in line 31; used 2 times
Last modified: 1999-08-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8178
Valid CSS Valid XHTML 1.0 Strict