# 2.11BSD#431 - /usr/src/bin/ps.c

##### Functions

    addchan           X
    cantread          X
    fixup             X
    getbyte           X
    getchan           X
    getcmd            X
    getdev            X
    getkvars          X
    getptr            X
    gettty            X
    lpr               X
    main              X
    maybetty          X
    nlist             X
    openfiles         X
    perrexit          X
    printhdr          X
    pscomp            X
    ptime             X
    readpsdb          X
    savcom            X
    spr               X
    upr               X
    wchancomp         X
    writepsdb         X

##### Variables

    Uflg              X
    aflg              X
    allttys           X
    cflg              X
    chkpid            X
    cmdstart          X
    datmap            X
    file              X
    gflg              X
    hz                X
    kflg              X
    kmem              X
    kmemf             X
    lflg              X
    lhdr              X
    mem               X
    memf              X
    mproc             X
    mytty             X
    nchans            X
    nflg              X
    nl                X
    nlistf            X
    npr               X
    nproc             X
    nttys             X
    outargs           X
    proc              X
    psdb              X
    rflg              X
    shdr              X
    swap              X
    swapf             X
    tptr              X
    twidth            X
    u                 X
    uflg              X
    uhdr              X
    uname             X
    wchand            X
    wflg              X
    ws                X
    xflg              X

##### Macros

    ARGLIST           X
    MAXSYMLEN         X
    MAXTTYS           X
    NNAMESIZ          X
    X_HZ              X
    X_NPROC           X
    X_PROC            X
    is                X
    round             X
    within            X

##### struct's

    map               X
    ttys              X
    wchan             X

##### typedef's

    WCHAN             X

       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

- in line 659, 684

cantread defined in line 990; used 1 times

- in line 244

fixup defined in line 493; used 1 times

- in line 270

getbyte defined in line 554; used 2 times

- in line 550, 910

getchan defined in line 605; used 2 times

- in line 90, 871

getcmd defined in line 887; used 1 times

- in line 470

getdev defined in line 299; used 2 times

- in line 796, 813

getkvars defined in line 787; used 1 times

- in line 230

getptr defined in line 539; used 2 times

- in line 90, 908

gettty defined in line 473; used 2 times

- in line 90, 437

lpr defined in line 857; used 1 times

- in line 281

main defined in line 120; never used
maybetty defined in line 323; used 1 times

- in line 313

nlist defined in line 622; used 3 times

- in line 795, 808-812(2)

openfiles defined in line 766; used 1 times

- in line 229

perrexit defined in line 706; used 6 times

- in line 637, 720, 745, 773, 780-784(2)

printhdr defined in line 971; used 1 times

- in line 237

pscomp defined in line 517; used 2 times

- in line 91, 514

ptime defined in line 876; used 3 times

- in line 845, 853, 873

readpsdb defined in line 734; used 1 times

- in line 801

savcom defined in line 400; used 1 times

- in line 266

spr defined in line 849; used 1 times

- in line 285

upr defined in line 841; used 1 times

- in line 283

wchancomp defined in line 528; used 2 times

- in line 91, 703

writepsdb defined in line 713; used 1 times

- in line 797

#### Defined variables

Uflg defined in line 62; used 3 times

- in line 203, 388, 794

aflg defined in line 52; used 5 times

- in line 152, 190, 223, 263, 438

allttys defined in line 109; used 5 times

- in line 386, 481-482(2), 729, 753

cflg defined in line 53; used 3 times

- in line 156, 293, 467

chkpid defined in line 51; used 3 times

- in line 221, 264(2)

cmdstart defined in line 72; used 5 times

- in line 272, 287, 293, 983-984(2)

datmap defined in line 117; used 8 times

- in line 431-436(7), 557

file defined in line 65; used 10 times

- in line 415, 421-424(3), 566(2), 902-903(2), 925-926(2)

gflg defined in line 54; used 4 times

- in line 160, 191, 258, 963

hz defined in line 50; used 3 times

- in line 836(2), 881

kflg defined in line 55; used 3 times

- in line 164, 769-774(2)

kmem defined in line 77; used 8 times

- in line 231, 243, 771-772(2), 818-819(2), 835-836(2)

kmemf defined in line 74; used 6 times

- in line 244, 770-777(4), 820

lflg defined in line 56; used 5 times

- in line 168-173(2), 280, 977-981(2)

lhdr defined in line 856; used 1 times

- in line 981

mem defined in line 77; used 3 times

- in line 415, 778-779(2)

memf defined in line 73; used 4 times

- in line 775-780(4)

mproc defined in line 48; used 4 times

- in line 249-250(2), 406, 899

mytty defined in line 63; used 7 times

- in line 184, 234-236(5), 438

nchans defined in line 67; used 12 times

- in line 583, 598, 614, 703, 727-730(3), 751-759(4), 806

nflg defined in line 57; used 6 times

- in line 172, 594, 683, 702, 754, 865

nl defined in line 34; used 12 times

- in line 132-134(3), 231, 635, 687, 723-728(2), 752, 817-818(2), 835

nlistf defined in line 76; used 9 times

- in line 636-638(3), 646, 652, 724(2), 793, 802

npr defined in line 70; used 5 times

- in line 267-271(3), 296, 440

nproc defined in line 66; used 6 times

- in line 238-239(2), 819(3), 828

nttys defined in line 68; used 10 times

- in line 382-386(2), 393, 480, 726-729(3), 750-753(3)

outargs defined in line 118; used 9 times

- in line 273, 440, 508-514(5), 828-829(2)

proc defined in line 48; used 2 times

- in line 243, 249

psdb defined in line 69; used 5 times

- in line 719-720(2), 744-745(2), 800

rflg defined in line 58; used 3 times

- in line 177, 275, 975

shdr defined in line 848; used 1 times

- in line 981

swap defined in line 77; used 3 times

- in line 421, 782-783(2)

swapf defined in line 75; used 3 times

- in line 781-784(3)

tptr defined in line 63; used 14 times

- in line 182-192(10), 258, 438(2), 963

twidth defined in line 71; used 8 times

- in line 140-142(2), 208-210(3), 272, 293, 984

u defined in line 49; used 7 times

- in line 356, 407, 424(2), 479-481(2), 959

uflg defined in line 59; used 5 times

- in line 199, 282, 499, 977-981(2)

uhdr defined in line 840; used 1 times

- in line 981

uname defined in line 64; used 2 times

- in line 801-802(2)

wchand defined in line 87; used 13 times

- in line 580-583(3), 589-591(2), 598, 615-617(2), 703, 730, 755-759(2), 807

wflg defined in line 60; used 2 times

- in line 207-211(2)

ws defined in line 116; used 5 times

- in line 136-142(5)

xflg defined in line 61; used 6 times

- in line 193, 215, 224, 255-258(2), 963

#### Defined struct's

map defined in line 111; used 4 times

- in line 117(2), 557(2)

ttys defined in line 105; used 6 times

- in line 326(2), 729(2), 753(2)

wchan defined in line 82; used 4 times

- in line 584-589(4)

#### Defined typedef's

WCHAN defined in line 85; used 11 times

- in line 87, 529, 576, 583, 589, 703, 730, 739, 755-760(3)

#### Defined macros

ARGLIST defined in line 892; used 6 times

- in line 896-902(3), 928-929(2), 935

MAXSYMLEN defined in line 46; used 2 times

- in line 630, 672

MAXTTYS defined in line 103; used 2 times

- in line 109, 382

NNAMESIZ defined in line 45; used 7 times

- in line 83, 600-601(2), 867-871(4)

X_HZ defined in line 37; used 2 times

- in line 134, 835

X_NPROC defined in line 36; used 3 times

- in line 133, 817-818(2)

X_PROC defined in line 35; used 2 times

- in line 132, 231

is defined in line 355; used 8 times

- in line 356-357(8)

round defined in line 32; used 1 times

- in line 431

within defined in line 31; used 2 times

- in line 561-562(2)

Last modified: 1999-08-12 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4072 |