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

Defined functions

addchan defined in line 571; used 1 times
cantread defined in line 878; used 2 times
err defined in line 667; used 4 times
fixup defined in line 469; used 1 times
getbyte defined in line 532; used 2 times
getchan defined in line 590; used 2 times
getcmd defined in line 884; used 2 times
getdev defined in line 308; used 2 times
getkvars defined in line 756; used 1 times
getptr defined in line 516; used 2 times
gettty defined in line 427; used 2 times
lpr defined in line 844; used 1 times
main defined in line 122; never used
nlist defined in line 607; used 3 times
openfiles defined in line 732; used 1 times
perrexit defined in line 674; used 7 times
pread defined in line 554; used 2 times
printhdr defined in line 972; used 1 times
pscomp defined in line 495; used 2 times
ptime defined in line 867; used 3 times
ptty defined in line 861; used 3 times
readpsdb defined in line 702; used 1 times
savcom defined in line 330; used 1 times
spr defined in line 834; used 1 times
ttyname defined in line 446; used 2 times
upr defined in line 821; used 1 times
wchancomp defined in line 506; used 2 times
writepsdb defined in line 681; used 1 times

Defined variables

Uflg defined in line 60; used 2 times
aflg defined in line 50; used 5 times
cflg defined in line 51; used 3 times
chkpid defined in line 49; used 3 times
cmdstart defined in line 110; used 5 times
datmap defined in line 105; used 12 times
devl defined in line 99; used 9 times
file defined in line 63; used 8 times
gflg defined in line 52; used 5 times
hz defined in line 48; used 3 times
ismem defined in line 70; used 2 times
kflg defined in line 53; used 4 times
kmem defined in line 116; used 10 times
kmemf defined in line 113; used 8 times
lflg defined in line 54; used 5 times
lhdr defined in line 842; used 1 times
mem defined in line 116; used 4 times
memf defined in line 112; used 4 times
mproc defined in line 44; used 5 times
mytty defined in line 61; used 2 times
nchans defined in line 67; used 12 times
ndev defined in line 68; used 12 times
nflg defined in line 55; used 5 times
nl defined in line 31; used 14 times
nlistf defined in line 115; used 6 times
npr defined in line 108; used 5 times
nproc defined in line 65; used 6 times
nsyms defined in line 69; used 3 times
outargs defined in line 107; used 9 times
proc defined in line 44; used 2 times
psdb defined in line 74; used 6 times
rflg defined in line 56; used 3 times
sccsid defined in line 1; never used
shdr defined in line 832; used 1 times
stbuf defined in line 46; used 3 times
swap defined in line 116; used 3 times
swapf defined in line 114; used 3 times
swplo defined in line 64; used 7 times
tell defined in line 66; used 1 times
tptr defined in line 61; used 7 times
twidth defined in line 109; used 8 times
u defined in line 45; used 6 times
uflg defined in line 57; used 5 times
uhdr defined in line 819; used 1 times
uname defined in line 62; used 2 times
wchanhd defined in line 84; used 9 times
wflg defined in line 58; used 1 times
xflg defined in line 59; used 7 times

Defined struct's

devl defined in line 96; used 4 times
map defined in line 101; used 4 times
wchan defined in line 80; used 28 times

Defined macros

ARGLIST defined in line 889; used 7 times
NNAMESIZ defined in line 42; used 4 times
NUMDEV defined in line 94; used 2 times
X_HZ defined in line 39; used 1 times
X_NPROC defined in line 37; used 2 times
X_PROC defined in line 33; used 2 times
X_SWPLO defined in line 35; used 1 times
equal defined in line 26; used 1 times
exists defined in line 27; used 2 times
round defined in line 29; used 1 times
within defined in line 28; used 2 times
Last modified: 1982-11-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2920
Valid CSS Valid XHTML 1.0 Strict