Annotation of 43BSD/bin/ps.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.