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

1.1       root        1: /*-
                      2:  * Copyright (c) 1990 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted provided
                      6:  * that: (1) source distributions retain this entire copyright notice and
                      7:  * comment, and (2) distributions including binaries display the following
                      8:  * acknowledgement:  ``This product includes software developed by the
                      9:  * University of California, Berkeley and its contributors'' in the
                     10:  * documentation or other materials provided with the distribution and in
                     11:  * all advertising materials mentioning features or use of this software.
                     12:  * Neither the name of the University nor the names of its contributors may
                     13:  * be used to endorse or promote products derived from this software without
                     14:  * specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: char copyright[] =
                     22: "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
                     23:  All rights reserved.\n";
                     24: #endif /* not lint */
                     25: 
                     26: #ifndef lint
                     27: static char sccsid[] = "@(#)ps.c       5.28 (Berkeley) 6/26/90";
                     28: #endif /* not lint */
                     29: 
                     30: #include <machine/pte.h>
                     31: 
                     32: #include <sys/param.h>
                     33: #include <sys/ioctl.h>
                     34: #include <sys/tty.h>
                     35: #include <sys/user.h>
                     36: #include <sys/proc.h>
                     37: #include <sys/vm.h>
                     38: #include <sys/text.h>
                     39: #include <sys/stat.h>
                     40: #include <sys/mbuf.h>
                     41: #include <nlist.h>
                     42: #include <pwd.h>
                     43: #include <math.h>
                     44: #include <errno.h>
                     45: #include <stdio.h>
                     46: #include <ctype.h>
                     47: #include <kvm.h>
                     48: 
                     49: struct usave {
                     50:        struct  proc *u_procp;
                     51:        struct  timeval u_start;
                     52:        struct  rusage u_ru;
                     53:        struct  rusage u_cru;
                     54:        short   u_cmask;
                     55:        char    u_acflag;
                     56: };
                     57: 
                     58: /*
                     59:  * to compute offset in common structures
                     60:  */
                     61: #define        POFF(x)         ((int)&((struct proc *)0)->x)
                     62: #define        EOFF(x)         ((int)&((struct eproc *)0)->x)
                     63: #define        UOFF(x)         ((int)&((struct usave *)0)->x)
                     64: #define        ROFF(x)         ((int)&((struct rusage *)0)->x)
                     65: 
                     66: enum type      { CHAR, UCHAR, SHORT, USHORT, LONG, ULONG, KPTR };
                     67: 
                     68: #define        UIDFMT  "u"
                     69: #define UIDLEN 5
                     70: #define PIDFMT "d"
                     71: #define PIDLEN 5
                     72: #define        USERLEN 8
                     73: 
                     74: int needuser, needcomm, neednlist;
                     75: 
                     76: int    command(), ucomm(), logname(), pvar(), evar(), uvar(), rvar(), uname(), 
                     77:        runame(), state(), pri(), tdev(), tname(), longtname(), started(),
                     78:        lstarted(), wchan(), vsize(), rssize(), p_rssize(), cputime(), 
                     79:        pmem(), pcpu(), pagein(), maxrss(), tsize(), trss();
                     80:        /**
                     81:        utime(), stime(), ixrss(), idrss(), isrss();
                     82:        **/
                     83: 
                     84: struct usave *saveuser();
                     85: char   *saveargs();
                     86: 
                     87: struct var {
                     88:        char    *name[8];       /* name(s) of variable */
                     89:        char    *header;        /* default header */
                     90:        int     flag;
                     91: #define        USER    0x01    /* requires user structure */
                     92: #define        LJUST   0x02    /* right adjust on output */
                     93: #define        COMM    0x04    /* requires exec arguments and environment (XXX) */
                     94: #define        NLIST   0x08    /* requires nlist to get extra variables */
                     95:        int     (*oproc)();     /* output routine */
                     96:        short   width;          /* printing width */
                     97:        /*
                     98:         * The following (optional) elements are hooks for passing information
                     99:         * to the generic output routines: pvar, evar, uvar (those which print
                    100:         * simple elements from well known structures: proc, eproc, usave)
                    101:         */
                    102:        int     off;            /* offset in structure */
                    103:        enum    type type;      /* type of element */
                    104:        char    *fmt;           /* printf format */
                    105:        /*
                    106:         * glue to link selected fields together
                    107:         */
                    108:        struct  var *next;
                    109: }  var[] = {
                    110:        {{"command", "comm", "args"}, "COMMAND", USER|LJUST|COMM, 
                    111:                command, 16}, 
                    112:        {{"ucomm"}, "COMMAND",  LJUST, ucomm, MAXCOMLEN},
                    113:        {{"logname"}, "LOGNAME", LJUST, logname, MAXLOGNAME},
                    114:        {{"flag", "f"}, "F", 0, pvar, 7, POFF(p_flag), LONG, "x"},
                    115:        {{"uid"}, "UID", 0, pvar, UIDLEN, POFF(p_uid),USHORT, UIDFMT},
                    116:        {{"ruid"}, "RUID", 0, pvar, UIDLEN, POFF(p_ruid), USHORT, UIDFMT},
                    117:        {{"svuid"}, "SVUID", 0, pvar, UIDLEN, POFF(p_svuid), USHORT, UIDFMT},
                    118:        {{"rgid"}, "RGID", 0, pvar, UIDLEN, POFF(p_rgid), USHORT, UIDFMT},
                    119:        {{"svgid"}, "SVGID", 0, pvar, UIDLEN, POFF(p_svgid), USHORT, UIDFMT},
                    120:        {{"pid"}, "PID", 0, pvar, PIDLEN, POFF(p_pid),SHORT, PIDFMT},
                    121:        {{"ppid"}, "PPID", 0, pvar, PIDLEN, POFF(p_ppid), SHORT, PIDFMT},
                    122:        {{"cp", "cpu"}, "CP", 0, pvar, 3, POFF(p_cpu), UCHAR, "d"},
                    123:        {{"xstat"}, "XSTAT", 0, pvar, 4, POFF(p_xstat), USHORT, "x"},
                    124:        {{"poip"}, "POIP", 0, pvar, 4, POFF(p_poip), SHORT, "d"},
                    125:        {{"nwchan"}, "WCHAN", 0, pvar, 6, POFF(p_wchan), KPTR, "x"},
                    126:        {{"wchan"}, "WCHAN", LJUST, wchan, 6},
                    127:        {{"rlink"}, "RLINK", 0, pvar, 8, POFF(p_rlink), KPTR, "x"},
                    128:        {{"ktrace", "traceflag"}, "KTRACE",
                    129:                0, pvar, 8, POFF(p_traceflag), LONG, "x"},
                    130:        {{"ktracep", "tracep"}, "KTRACEP",
                    131:                0, pvar, 8, POFF(p_tracep), LONG, "x"},
                    132:        {{"sig", "pending"}, "PENDING",
                    133:                0, pvar, 8, POFF(p_sig), LONG, "x"},
                    134:        {{"sigmask", "blocked"}, "BLOCKED",
                    135:                0, pvar, 8, POFF(p_sigmask), LONG, "x"},
                    136:        {{"sigignore", "ignored"}, "IGNORED",
                    137:                0, pvar, 8, POFF(p_sigignore), LONG, "x"},
                    138:        {{"sigcatch", "caught"}, "CAUGHT",
                    139:                0, pvar, 8, POFF(p_sigcatch), LONG, "x"},
                    140:        {{"user", "uname"}, "USER", LJUST, uname, USERLEN},
                    141:        {{"ruser", "runame"}, "RUSER", LJUST, runame, USERLEN},
                    142:        {{"pgid"}, "PGID", 0, evar, PIDLEN, EOFF(e_pgid), USHORT, PIDFMT},
                    143:        {{"jobc"}, "JOBC", 0, evar, 4, EOFF(e_jobc), SHORT, "d"},
                    144:        {{"sess", "session"}, "SESS", 0, evar, 6, EOFF(e_sess), KPTR, "x"},
                    145:        {{"tdev", "dev"}, "TDEV", 0, tdev, 4},
                    146:        {{"tname", "tty", "tt"}, "TT", LJUST, tname, 3},
                    147:        {{"longtname", "longtty"}, "TT", LJUST, longtname, 8},
                    148:        {{"tpgid"}, "TPGID", 0, evar, 4, EOFF(e_tpgid), USHORT, PIDFMT},
                    149:        {{"tsession", "tsess"}, "TSESS", 
                    150:                0, evar, 6, EOFF(e_tsess), KPTR, "x"},
                    151:        {{"paddr", "procaddr"}, "PADDR",
                    152:                0, evar, 6, EOFF(e_paddr), KPTR, "x"},
                    153:        {{"state", "stat"}, "STAT", 0, state, 4},
                    154:        {{"pri"}, "PRI", 0, pri, 3},
                    155:        {{"usrpri"}, "UPR", 0, pvar, 3, POFF(p_usrpri), CHAR, "d"},
                    156:        {{"nice", "ni"}, "NI", 0, pvar, 2, POFF(p_nice), CHAR, "d"}, 
                    157:        {{"vsize", "vsz"}, "VSZ", 0, vsize, 5},
                    158:        {{"rssize", "rsz"}, "RSZ", 0, rssize, 4},
                    159:        {{"rss", "p_rss"}, "RSS", 0, p_rssize, 4},
                    160:        {{"u_procp", "uprocp"}, "UPROCP",
                    161:                USER, uvar, 6, UOFF(u_procp), KPTR, "x"},
                    162:        {{"umask", "u_cmask"}, "UMASK",
                    163:                USER, uvar, 3, UOFF(u_cmask), CHAR, "#o"},
                    164:        {{"acflag", "acflg"}, "ACFLG",
                    165:                USER, uvar, 3, UOFF(u_acflag), SHORT, "x"},
                    166:        {{"start"}, "STARTED", USER|LJUST, started, 8},
                    167:        {{"lstart"}, "STARTED", USER|LJUST, lstarted, 28},
                    168:        {{"cputime", "time"}, "TIME", USER, cputime, 9},
                    169:        {{"p_ru"}, "P_RU", 0, pvar, 6, POFF(p_ru), KPTR, "x"},
                    170:        {{"pcpu", "%cpu"}, "%CPU", NLIST, pcpu, 4},
                    171:        {{"pmem", "%mem"}, "%MEM", NLIST, pmem, 4},
                    172:        {{"sl", "slp", "slptime"}, "SL",
                    173:                0, pvar, 3, POFF(p_slptime), CHAR, "d"},
                    174:        {{"re", "resident"}, "RE",
                    175:                0, pvar, 3, POFF(p_time), CHAR, "d"},
                    176:        {{"pagein", "majflt"}, "PAGEIN", USER, pagein, 6},
                    177:        {{"lim", "maxrss"}, "LIM", 0, maxrss, 5},
                    178:        {{"tsiz"}, "TSIZ", 0, tsize, 4},
                    179:        {{"trs"}, "TRS", 0, trss, 3},
                    180:        /***
                    181:        {{"utime"}, "UTIME", USER, utime, 4},
                    182:        {{"stime"}, "STIME", USER, stime, 4},
                    183:        {{"ixrss"}, "IXRSS", USER, ixrss, 4},
                    184:        {{"idrss"}, "IDRSS", USER, idrss, 4},
                    185:        {{"isrss"}, "ISRSS", USER, isrss, 4},
                    186:        ***/
                    187:        {{"minflt"}, "MINFLT", 
                    188:                USER, rvar, 4, ROFF(ru_minflt), LONG, "d"},
                    189:        {{"majflt"}, "MAJFLT", 
                    190:                USER, rvar, 4, ROFF(ru_majflt), LONG, "d"},
                    191:        {{"nswap"}, "NSWAP",    
                    192:                USER, rvar, 4, ROFF(ru_nswap), LONG, "d"},
                    193:        {{"inblock", "inblk"}, "INBLK",         
                    194:                USER, rvar, 4, ROFF(ru_inblock), LONG, "d"},
                    195:        {{"oublock", "oublk"}, "OUBLK", 
                    196:                USER, rvar, 4, ROFF(ru_oublock), LONG, "d"},
                    197:        {{"msgsnd"}, "MSGSND", 
                    198:                USER, rvar, 4, ROFF(ru_msgsnd), LONG, "d"},
                    199:        {{"msgrcv"}, "MSGRCV", 
                    200:                USER, rvar, 4, ROFF(ru_msgrcv), LONG, "d"},
                    201:        {{"nsignals", "nsigs"}, "NSIGS", 
                    202:                USER, rvar, 4, ROFF(ru_nsignals), LONG, "d"},
                    203:        {{"nvcsw", "vcsw"}, "VCSW", 
                    204:                USER, rvar, 5, ROFF(ru_nvcsw), LONG, "d"},
                    205:        {{"nivcsw", "ivcsw"}, "IVCSW", 
                    206:                USER, rvar, 5, ROFF(ru_nivcsw), LONG, "d"},
                    207:        NULL
                    208: };
                    209: 
                    210: /* 
                    211:  * combination variables 
                    212:  */
                    213: struct combovar {
                    214:        char *name;
                    215:        char *replace;
                    216: } combovar[] = {
                    217:        "RUSAGE", "minflt majflt nswap inblock oublock \
                    218:                msgsnd msgrcv nsigs nvcsw nivcsw",
                    219:        0, 0
                    220: };
                    221: #define DFMT   "pid tname state cputime comm"
                    222: #define LFMT \
                    223:        "uid pid ppid cp pri nice vsz rss wchan state tname cputime comm"
                    224: #define        JFMT    "user pid ppid pgid sess jobc state tname cputime comm"
                    225: #define        SFMT    "uid pid sig sigmask sigignore sigcatch stat tname comm"
                    226: #define        VFMT \
                    227:        "pid tt state time sl re pagein vsz rss lim tsiz trs %cpu %mem comm"
                    228: #define UFMT \
                    229:        "uname pid %cpu %mem vsz rss tt state start time comm"
                    230: 
                    231: struct kinfo {
                    232:        struct proc *ki_p;      /* proc structure */
                    233:        struct eproc *ki_e;     /* extra stuff */
                    234:        struct usave *ki_u;     /* interesting parts of user */
                    235:        char *ki_args;          /* exec args (should be char **) */
                    236:        char *ki_env;           /* environment (should be char **) */
                    237: } *kinfo;
                    238: 
                    239: struct var *vhead, *vtail;
                    240: int    termwidth;      /* width of screen (0 == infinity) */
                    241: #define UNLIMITED      0
                    242: int    totwidth;       /* calculated width of requested variables */
                    243: int    sumrusage;
                    244: int    rawcpu;
                    245: int    sortby;
                    246: #define        SORTMEM 1
                    247: #define        SORTCPU 2
                    248: 
                    249: int    uid = -1;
                    250: dev_t  ttydev = NODEV;
                    251: int    pid = -1;
                    252: int    all;
                    253: int    xflg;
                    254: int    prtheader;
                    255: int    lineno;
                    256: 
                    257: /*
                    258:  * variables retrieved via nlist
                    259:  */
                    260: struct nlist psnl[] = {
                    261:        {"_ecmx"},
                    262: #define        X_ECMX          0
                    263:        {"_fscale"},
                    264: #define        X_FSCALE        1
                    265:        {"_ccpu"},
                    266: #define        X_CCPU          2
                    267:        {NULL}
                    268: };
                    269: int    fscale;
                    270: int    ecmx;
                    271: fixpt_t        ccpu;
                    272: 
                    273: #define USAGE  "ps [ -(o|O) fmt ] [ -wlvujnsaxSCLmcr ] [ -p pid ] [ -t tty ]"
                    274: 
                    275: main (argc, argv) 
                    276:        char *argv[];
                    277: {
                    278:        extern char *optarg;
                    279:        extern int optind;
                    280:        int ch; 
                    281:        register i;
                    282:        register struct var *v;
                    283:        register struct proc *p;
                    284:        struct winsize ws;
                    285:        struct kinfo_proc *kprocs;
                    286:        int nentries;
                    287:        int fmt = 0;
                    288:        int pscomp();
                    289:        int what, flag;
                    290:        char *kludge_oldps_options();
                    291: 
                    292:        if ((ioctl(1, TIOCGWINSZ, &ws) == -1 && 
                    293:             ioctl(2, TIOCGWINSZ, &ws) == -1 &&
                    294:             ioctl(0, TIOCGWINSZ, &ws) == -1) ||
                    295:             ws.ws_col == 0)
                    296:                termwidth = 79;
                    297:        else
                    298:                termwidth = ws.ws_col - 1;
                    299:        if (argc > 1)
                    300:                argv[1] = kludge_oldps_options(argv[1]);
                    301: 
                    302:        while ((ch = getopt(argc, argv, "o:O:wlvujnsaxt:p:SCLmrhTg")) != EOF)
                    303:                switch((char)ch) {
                    304:                case 'o':
                    305:                        parsefmt(optarg);
                    306:                        fmt++;
                    307:                        break;
                    308:                case 'O':
                    309:                        parsefmt("pid");
                    310:                        parsefmt(optarg);
                    311:                        parsefmt("state tt time command");
                    312:                        fmt++;
                    313:                        break;
                    314:                case 'w':
                    315:                        if (termwidth < 131)
                    316:                                termwidth = 131;
                    317:                        else
                    318:                                termwidth = UNLIMITED;
                    319:                        break;
                    320:                case 'l':
                    321:                        parsefmt(LFMT);
                    322:                        fmt++;
                    323:                        break;
                    324:                case 'v':
                    325:                        parsefmt(VFMT);
                    326:                        sortby = SORTMEM;
                    327:                        fmt++;
                    328:                        break;
                    329:                case 'u':
                    330:                        parsefmt(UFMT);
                    331:                        sortby = SORTCPU;
                    332:                        fmt++;
                    333:                        break;
                    334:                case 'j':
                    335:                        parsefmt(JFMT);
                    336:                        fmt++;
                    337:                        break;
                    338:                case 's':
                    339:                        parsefmt(SFMT);
                    340:                        fmt++;
                    341:                        break;
                    342:                case 'T':
                    343:                case 't': {
                    344:                        struct stat stbuf;
                    345:                        char *tname, *ttyname();
                    346:                        char termname[MAXPATHLEN+1];
                    347: 
                    348:                        if (ch == 'T') {
                    349:                                if ((tname = ttyname(0)) == NULL)
                    350:                                        error("<stdin>: not a terminal");
                    351:                        } else 
                    352:                                tname = optarg;
                    353:                        if (strlen(tname) == 2) {
                    354:                                if (strcmp(tname, "co") == 0)
                    355:                                        strcpy(termname, "/dev/console");
                    356:                                else {
                    357:                                        strcpy(termname, "/dev/tty");
                    358:                                        strcat(termname, tname);
                    359:                                }
                    360:                        } else if (*tname != '/') {
                    361:                                strcpy(termname, "/dev/");
                    362:                                strcat(termname, tname);
                    363:                        } else
                    364:                                strcpy(termname, tname);
                    365:                        if (stat(termname, &stbuf) == -1)
                    366:                                syserror(termname);
                    367:                        if ((stbuf.st_mode & S_IFMT) != S_IFCHR)
                    368:                                error("%s: not a terminal", termname);
                    369:                        ttydev = stbuf.st_rdev;
                    370:                        break;
                    371:                }
                    372:                case 'p':
                    373:                        pid = atoi(optarg);
                    374:                        xflg++;
                    375:                        break;
                    376:                case 'S':
                    377:                        sumrusage++;
                    378:                        break;
                    379:                case 'C':
                    380:                        rawcpu++;
                    381:                        break;
                    382:                case 'L': {
                    383:                        int i = 0;
                    384:                        struct combovar *cb = &combovar[0];
                    385:                        char *cp;
                    386: 
                    387:                        v = &var[0];
                    388:                        for (;;) {
                    389:                                if (v->name[0] != NULL) {
                    390:                                        cp = v->name[0];
                    391:                                        v++;
                    392:                                } else if (cb->name != NULL) {
                    393:                                        cp = cb->name;
                    394:                                        cb++;
                    395:                                } else
                    396:                                        break;
                    397:                                if (termwidth && 
                    398:                                   (i += strlen(cp)+1) > termwidth)
                    399:                                        i = strlen(cp), printf("\n");
                    400:                                printf("%s ", cp);
                    401:                        }
                    402:                        printf("\n");
                    403:                        exit(0);
                    404:                }
                    405:                case 'a':
                    406:                        all++;
                    407:                        break;
                    408:                case 'x':
                    409:                        xflg++;
                    410:                        break;
                    411:                case 'm':
                    412:                        sortby = SORTMEM;
                    413:                        break;
                    414:                case 'r':
                    415:                        sortby = SORTCPU;
                    416:                        break;
                    417:                case 'h':
                    418:                        prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
                    419:                        break;
                    420:                case 'g':
                    421:                        break;  /* no-op */
                    422:                case '?':
                    423:                default:
                    424:                        fprintf(stderr, "usage: %s\n", USAGE);
                    425:                        exit(1);
                    426:                }
                    427:        argc -= optind;
                    428:        argv += optind;
                    429:        
                    430:        if (*argv) {
                    431:                char *nlistf, *memf = NULL, *swapf = NULL;
                    432: 
                    433:                nlistf = *argv++;
                    434:                if (*argv) {
                    435:                        memf = *argv++;
                    436:                        if (*argv)
                    437:                                swapf = *argv++;
                    438:                }
                    439:                if (kvm_openfiles(nlistf, memf, swapf) == -1)
                    440:                        error("kvm_openfiles: %s", kvm_geterr());
                    441:        }
                    442: 
                    443:        if (!fmt)
                    444:                parsefmt(DFMT);
                    445: 
                    446:        if (!all && ttydev == NODEV && pid == -1)  /* XXX - should be cleaner */
                    447:                uid = getuid();
                    448: 
                    449:        /*
                    450:         * scan requested variables, noting what structures are needed,
                    451:         * and adjusting header widths as appropiate.
                    452:         */
                    453:        scanvars();
                    454: #ifdef notdef
                    455:        if (sortby == SORTCPU)
                    456:                neednlist = 1;
                    457: #endif
                    458:        if (neednlist)
                    459:                donlist();
                    460:        /*
                    461:         * get proc list
                    462:         */
                    463:        if (uid != -1) {
                    464:                what = KINFO_PROC_UID;
                    465:                flag = uid;
                    466:        } else if (ttydev != NODEV) {
                    467:                what = KINFO_PROC_TTY;
                    468:                flag = ttydev;
                    469:        } else if (pid != -1) {
                    470:                what = KINFO_PROC_PID;
                    471:                flag = pid;
                    472:        } else
                    473:                what = KINFO_PROC_ALL;
                    474:        /*
                    475:         * select procs
                    476:         */
                    477:        if ((nentries = kvm_getprocs(what, flag)) == -1) {
                    478:                fprintf(stderr, "ps: %s\n", kvm_geterr());
                    479:                exit(1);
                    480:        }
                    481:        kinfo = (struct kinfo *)malloc(nentries * sizeof (struct kinfo));
                    482:        if (kinfo == NULL)
                    483:                error("out of memory");
                    484:        i = 0;
                    485:        while ((p = kvm_nextproc()) != NULL) {
                    486:                kinfo[i].ki_p = p;
                    487:                kinfo[i].ki_e = kvm_geteproc(p);
                    488:                if (needuser)
                    489:                        saveuser(&kinfo[i]);
                    490:                i++;
                    491:        }
                    492:        nentries = i;
                    493:        /*
                    494:         * print header
                    495:         */
                    496:        printheader();
                    497:        if (nentries == 0)
                    498:                exit(0);
                    499:        /*
                    500:         * sort proc list
                    501:         */
                    502:        qsort(kinfo, nentries, sizeof (struct kinfo), pscomp);
                    503:        /*
                    504:         * for each proc, call each variable output function.
                    505:         */
                    506:        for (i = 0; i < nentries; i++) {
                    507:                if (xflg == 0 && (kinfo[i].ki_e->e_tdev == NODEV ||
                    508:                    (kinfo[i].ki_p->p_flag & SCTTY ) == 0))
                    509:                        continue;
                    510:                for (v = vhead; v != NULL; v = v->next) {
                    511:                        (*v->oproc)(&kinfo[i], v);
                    512:                        if (v->next != NULL)
                    513:                                putchar(' ');
                    514:                }
                    515:                putchar('\n');
                    516:                if (prtheader && lineno++ == prtheader-4) {
                    517:                        putchar('\n');
                    518:                        printheader();
                    519:                        lineno = 0;
                    520:                }
                    521:        }
                    522: 
                    523:        exit(0);
                    524: }
                    525: 
                    526: #define FMTSEP " \t,\n"
                    527: 
                    528: parsefmt(fmt)
                    529:        char *fmt;
                    530: {
                    531:        register char *f = fmt, *cp, *hp;
                    532:        struct var *v;
                    533:        char *strtok(), *index();
                    534:        char newbuf[1024], *nb = newbuf; /* XXX */
                    535:        char *lookupcombo();
                    536:        struct var *lookupvar();
                    537:        
                    538:        /*
                    539:         * strtok is not &^%^& re-entrant, so we have
                    540:         * only one level of expansion, looking for combo
                    541:         * variables once here, and expanding the string
                    542:         * before really parsing it.  With strtok_r,
                    543:         * you would move the expansion to before the
                    544:         * lookupvar inside the 2nd while loop with a
                    545:         * recursive call to parsefmt.
                    546:         */
                    547:        while ((cp = strtok(f, FMTSEP)) != NULL) {
                    548:                if ((hp = lookupcombo(cp)) == NULL);
                    549:                        hp = cp;
                    550:                if (((nb + strlen(hp)) - newbuf) >= 1024)
                    551:                        error("format too large");
                    552:                strcpy(nb, hp);
                    553:                while (*nb)
                    554:                        nb++;
                    555:                *nb++ = ' ';
                    556:                *nb =  '\0';
                    557:                f = NULL;
                    558:        }
                    559:        f = newbuf;
                    560:        while ((cp = strtok(f, FMTSEP)) != NULL) {
                    561:                if (hp = index(cp, '='))
                    562:                        *hp++ = '\0';
                    563:                v = lookupvar(cp);
                    564:                if (v == NULL)
                    565:                        error("unknown variable in format: %s", cp);
                    566:                if (v->next != NULL || vtail == v)
                    567:                        error("can't specify a variable twice: %s", cp);
                    568:                if (hp)
                    569:                        v->header = hp;
                    570:                if (vhead == NULL)
                    571:                        vhead = vtail = v;
                    572:                else {
                    573:                        vtail->next = v;
                    574:                        vtail = v;
                    575:                }
                    576:                f = NULL;       /* for strtok */
                    577:        }
                    578: 
                    579: }
                    580: 
                    581: scanvars()
                    582: {
                    583:        register i;
                    584:        register struct var *v;
                    585: 
                    586:        for (v = vhead; v != NULL; v = v->next) {
                    587:                i = strlen(v->header);
                    588:                if (v->width < i)
                    589:                        v->width = i;
                    590:                totwidth += v->width + 1;       /* +1 for space */
                    591:                if (v->flag & USER)
                    592:                        needuser = 1;
                    593:                if (v->flag & COMM)
                    594:                        needcomm = 1;
                    595:                if (v->flag & NLIST)
                    596:                        neednlist = 1;
                    597:        }
                    598:        totwidth--;
                    599: }
                    600: printheader()
                    601: {
                    602:        register struct var *v;
                    603: 
                    604:        for (v = vhead; v != NULL; v = v->next) {
                    605:                if (v->flag & LJUST) {
                    606:                        if (v->next == NULL)    /* last one */
                    607:                                printf("%s", v->header);
                    608:                        else
                    609:                                printf("%-*s",v->width, v->header);
                    610:                } else
                    611:                        printf("%*s",v->width, v->header);
                    612:                if (v->next != NULL)
                    613:                        putchar(' ');
                    614:        }
                    615:        putchar('\n');
                    616: }
                    617: 
                    618: command(k, v) 
                    619:        struct kinfo *k;
                    620:        struct var *v;
                    621: {
                    622: 
                    623:        if (v->next == NULL) {          
                    624:                /* last field */
                    625:                if (termwidth == UNLIMITED)
                    626:                        printf("%s", k->ki_args);
                    627:                else {
                    628:                        register left = termwidth - (totwidth - v->width);
                    629:                        register char *cp = k->ki_args;
                    630: 
                    631:                        if (left < 1)   /* already wrapped, just use std width */
                    632:                                left = v->width;
                    633:                        while (left-- && *cp)
                    634:                                putchar(*cp++);
                    635:                }
                    636:        } else
                    637:                printf("%-*.*s", v->width, v->width, k->ki_args);
                    638:                
                    639: }
                    640: 
                    641: ucomm(k, v) 
                    642:        struct kinfo *k;
                    643:        struct var *v;
                    644: {
                    645: 
                    646:        printf("%-*s", v->width, k->ki_p->p_comm);
                    647: }
                    648: 
                    649: logname(k, v) 
                    650:        struct kinfo *k;
                    651:        struct var *v;
                    652: {
                    653: 
                    654:        printf("%-*s", v->width, k->ki_p->p_logname);
                    655: }
                    656: 
                    657: state(k, v)
                    658:        struct kinfo *k;
                    659:        struct var *v;
                    660: {
                    661:        char buf[16];
                    662:        register char *cp = buf;
                    663:        register struct proc *p = k->ki_p;
                    664:        register flag = p->p_flag;
                    665: 
                    666:        switch (p->p_stat) {
                    667: 
                    668:        case SSTOP:
                    669:                *cp = 'T';
                    670:                break;
                    671: 
                    672:        case SSLEEP:
                    673:                if (flag & SSINTR)      /* interuptable (long) */
                    674:                        *cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
                    675:                else 
                    676:                        *cp = (flag & SPAGE) ? 'P' : 'D';
                    677:                break;
                    678: 
                    679:        case SRUN:
                    680:        case SIDL:
                    681:                *cp = 'R';
                    682:                break;
                    683: 
                    684:        case SZOMB:
                    685:                *cp = 'Z';
                    686:                break;
                    687: 
                    688:        default:
                    689:                *cp = '?';
                    690:        }
                    691:        cp++;
                    692:        if (flag & SLOAD) {
                    693:                if (p->p_rssize > p->p_maxrss)
                    694:                        *cp++ = '>';
                    695:        } else
                    696:                *cp++ = 'W';
                    697:        if (p->p_nice < NZERO)
                    698:                *cp++ = '<';
                    699:        else if (p->p_nice > NZERO)
                    700:                *cp++ = 'N';
                    701:        if (flag & SUANOM)
                    702:                *cp++ = 'A';
                    703:        else if (flag & SSEQL)
                    704:                *cp++ = 'S';
                    705:        if (flag & STRC)
                    706:                *cp++ = 'X';
                    707:        if (flag & SWEXIT)
                    708:                *cp++ = 'E';
                    709:        if (flag & SVFORK)
                    710:                *cp++ = 'V';
                    711:        if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO))
                    712:                *cp++ = 'L';
                    713:        if (k->ki_e->e_flag & EPROC_SLEADER)
                    714:                *cp++ = 's';
                    715:        if ((flag & SCTTY) && k->ki_e->e_pgid == k->ki_e->e_tpgid)
                    716:                *cp++ = '+';
                    717:        *cp = '\0';
                    718:        printf("%-*s", v->width, buf);
                    719: }
                    720: 
                    721: pri(k, v)
                    722:        struct kinfo *k;
                    723:        struct var *v;
                    724: {
                    725: 
                    726:        printf("%*d", v->width, k->ki_p->p_pri - PZERO);
                    727: }
                    728: 
                    729: uname(k, v)
                    730:        struct kinfo *k;
                    731:        struct var *v;
                    732: {
                    733: 
                    734:        printf("%-*s", v->width, user_from_uid(k->ki_p->p_uid, 0));
                    735: }
                    736: 
                    737: runame(k, v)
                    738:        struct kinfo *k;
                    739:        struct var *v;
                    740: {
                    741: 
                    742:        printf("%-*s", v->width, user_from_uid(k->ki_p->p_ruid, 0));
                    743: }
                    744: 
                    745: tdev(k, v)
                    746:        struct kinfo *k;
                    747:        struct var *v;
                    748: {
                    749:        dev_t dev = k->ki_e->e_tdev;
                    750: 
                    751:        if (dev == NODEV)
                    752:                printf("%*s", v->width, "??");
                    753:        else {
                    754:                char buff[16];
                    755: 
                    756:                sprintf(buff, "%d/%d", major(dev), minor(dev));
                    757:                printf("%*s", v->width, buff);
                    758:        }
                    759: }
                    760: 
                    761: extern char *devname();
                    762: 
                    763: tname(k, v)
                    764:        struct kinfo *k;
                    765:        struct var *v;
                    766: {
                    767:        dev_t dev = k->ki_e->e_tdev;
                    768:        char *tname;
                    769: 
                    770:        if (dev == NODEV || (tname = devname(dev, S_IFCHR)) == NULL)
                    771:                printf("%-*s", v->width, "??");
                    772:        else {
                    773:                if (strncmp(tname, "tty", 3) == 0)
                    774:                        tname += 3;
                    775:                printf("%*.*s%c", v->width-1, v->width-1, tname,
                    776:                        k->ki_e->e_flag & EPROC_CTTY ? ' ' : '-');
                    777:        }
                    778: }
                    779: 
                    780: longtname(k, v)
                    781:        struct kinfo *k;
                    782:        struct var *v;
                    783: {
                    784:        dev_t dev = k->ki_e->e_tdev;
                    785:        char *tname;
                    786: 
                    787:        if (dev == NODEV || (tname = devname(dev, S_IFCHR)) == NULL)
                    788:                printf("%-*s", v->width, "??");
                    789:        else
                    790:                printf("%-*s", v->width, tname);
                    791: }
                    792: 
                    793: #include <sys/time.h>
                    794: 
                    795: started(k, v)
                    796:        struct kinfo *k;
                    797:        struct var *v;
                    798: {
                    799:        extern char *attime();
                    800: 
                    801:        printf("%-*s", v->width, k->ki_u ? 
                    802:                attime(&k->ki_u->u_start.tv_sec) : "-");
                    803:                
                    804: }
                    805: 
                    806: lstarted(k, v)
                    807:        struct kinfo *k;
                    808:        struct var *v;
                    809: {
                    810:        extern char *ctime();
                    811:        char *tp; 
                    812: 
                    813:        if (k->ki_u)
                    814:                (tp = ctime(&k->ki_u->u_start.tv_sec))[24] = '\0';
                    815:        else
                    816:                tp = "-";
                    817:        printf("%-*s", v->width, tp);
                    818: }
                    819: 
                    820: wchan(k, v)
                    821:        struct kinfo *k;
                    822:        struct var *v;
                    823: {
                    824: 
                    825:        if (k->ki_p->p_wchan) {
                    826:                if (k->ki_p->p_pri > PZERO)
                    827:                        printf("%-*.*s", v->width, v->width, k->ki_e->e_wmesg);
                    828:                else
                    829:                        printf("%*x", v->width, 
                    830:                                (int)k->ki_p->p_wchan &~ KERNBASE);
                    831:        } else
                    832:                printf("%-*s", v->width, "-");
                    833: }
                    834: 
                    835: #define pgtok(a)        (((a)*NBPG)/1024)
                    836: #define pgtok(a)        (((a)*NBPG)/1024)
                    837: 
                    838: vsize(k, v)
                    839:        struct kinfo *k;
                    840:        struct var *v;
                    841: {
                    842: 
                    843:        printf("%*d", v->width, 
                    844:                pgtok(k->ki_p->p_dsize + k->ki_p->p_ssize + k->ki_e->e_xsize));
                    845: }
                    846: 
                    847: rssize(k, v)
                    848:        struct kinfo *k;
                    849:        struct var *v;
                    850: {
                    851: 
                    852:        printf("%*d", v->width, 
                    853:                pgtok(k->ki_p->p_rssize + (k->ki_e->e_xccount ? 
                    854:                      (k->ki_e->e_xrssize / k->ki_e->e_xccount) : 0)));
                    855: }
                    856: 
                    857: p_rssize(k, v)         /* doesn't account for text */
                    858:        struct kinfo *k;
                    859:        struct var *v;
                    860: {
                    861: 
                    862:        printf("%*d", v->width, pgtok(k->ki_p->p_rssize));
                    863: }
                    864: 
                    865: cputime(k, v)
                    866:        struct kinfo *k;
                    867:        struct var *v;
                    868: {
                    869:        long secs;
                    870:        long psecs;     /* "parts" of a second. first micro, then centi */
                    871:        char obuff[128];
                    872: 
                    873:        if (k->ki_p->p_stat == SZOMB || k->ki_u == NULL) {
                    874:                secs = 0;
                    875:                psecs = 0;
                    876:        } else {
                    877:                secs = k->ki_p->p_utime.tv_sec + 
                    878:                        k->ki_p->p_stime.tv_sec;
                    879:                psecs = k->ki_p->p_utime.tv_usec + 
                    880:                        k->ki_p->p_stime.tv_usec;
                    881:                if (sumrusage) {
                    882:                        secs += k->ki_u->u_cru.ru_utime.tv_sec + 
                    883:                                k->ki_u->u_cru.ru_stime.tv_sec;
                    884:                        psecs += k->ki_u->u_cru.ru_utime.tv_usec + 
                    885:                                k->ki_u->u_cru.ru_stime.tv_usec;
                    886:                }
                    887:                /*
                    888:                 * round and scale to 100's
                    889:                 */
                    890:                psecs = (psecs + 5000) / 10000;
                    891:                if (psecs >= 100) {
                    892:                        psecs -= 100;
                    893:                        secs++;
                    894:                }
                    895:        }
                    896:        sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
                    897:        printf("%*s", v->width, obuff);
                    898: }
                    899: 
                    900: double
                    901: getpcpu(k)
                    902:        struct kinfo *k;
                    903: {
                    904:        /*
                    905:         * note: this routine requires ccpu and fscale
                    906:         * be initialized.  If you call this routine from
                    907:         * somewhere new, insure that the "neednlist" flag
                    908:         * gets set.
                    909:         */
                    910:        struct proc *p = k->ki_p;
                    911: #define        fxtofl(fixpt)   ((double)(fixpt) / fscale)
                    912: 
                    913:        if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) /* XXX - I don't like this */
                    914:                return (0.0);
                    915:        if (rawcpu)
                    916:                return (100.0 * fxtofl(p->p_pctcpu));
                    917:        return (100.0 * fxtofl(p->p_pctcpu) /
                    918:                (1.0 - exp(p->p_time * log(fxtofl(ccpu)))));
                    919: }
                    920: 
                    921: pcpu(k, v)
                    922:        struct kinfo *k;
                    923:        struct var *v;
                    924: {
                    925: 
                    926:        printf("%*.1f", v->width, getpcpu(k));
                    927: }
                    928: 
                    929: double
                    930: getpmem(k, v)
                    931:        struct kinfo *k;
                    932:        struct var *v;
                    933: {
                    934:        struct proc *p = k->ki_p;
                    935:        struct eproc *e = k->ki_e;
                    936:        double fracmem;
                    937:        int szptudot;
                    938:        /*
                    939:         * note: this routine requires that ecmx
                    940:         * be initialized.  If you call this routine from
                    941:         * somewhere new, insure that the "neednlist" flag
                    942:         * gets set.
                    943:         */
                    944: 
                    945:        if (p->p_flag & SLOAD == 0)
                    946:                return (0.0);
                    947:        szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
                    948:        fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/ecmx;
                    949:        if (p->p_textp && e->e_xccount)
                    950:                fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/ecmx;
                    951:        return (100.0 * fracmem);
                    952: }
                    953: 
                    954: pmem(k, v)
                    955:        struct kinfo *k;
                    956:        struct var *v;
                    957: {
                    958: 
                    959:        printf("%*.1f", v->width, getpmem(k));
                    960: }
                    961: 
                    962: pagein(k, v)
                    963:        struct kinfo *k;
                    964:        struct var *v;
                    965: {
                    966: 
                    967:        printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0);
                    968: }
                    969: 
                    970: maxrss(k, v)
                    971:        struct kinfo *k;
                    972:        struct var *v;
                    973: {
                    974: 
                    975:        if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG))
                    976:                printf("%*d", v->width, pgtok(k->ki_p->p_maxrss));
                    977:        else
                    978:                printf("%*s", v->width, "-");
                    979: }
                    980: 
                    981: tsize(k, v)
                    982:        struct kinfo *k;
                    983:        struct var *v;
                    984: {
                    985:        
                    986:        printf("%*d", v->width, pgtok(k->ki_e->e_xsize));
                    987: }
                    988: 
                    989: trss(k, v)
                    990:        struct kinfo *k;
                    991:        struct var *v;
                    992: {
                    993: 
                    994:        printf("%*d", v->width, pgtok(k->ki_e->e_xrssize));
                    995: }
                    996: 
                    997: /*
                    998:  * Generic output routines.  Print fields from various prototype
                    999:  * structures.
                   1000:  */
                   1001: pvar(k, v) 
                   1002:        struct kinfo *k;
                   1003:        struct var *v;
                   1004: {
                   1005:  
                   1006:        printval((char *)((char *)k->ki_p + v->off), v);
                   1007: }
                   1008: 
                   1009: evar(k, v) 
                   1010:        struct kinfo *k;
                   1011:        struct var *v;
                   1012: {
                   1013:  
                   1014:        printval((char *)((char *)k->ki_e + v->off), v);
                   1015: }
                   1016: 
                   1017: uvar(k, v) 
                   1018:        struct kinfo *k;
                   1019:        struct var *v;
                   1020: {
                   1021:  
                   1022:        if (k->ki_u)
                   1023:                printval((char *)((char *)k->ki_u + v->off), v);
                   1024:        else
                   1025:                printf("%*s", v->width, "-");
                   1026: }
                   1027: 
                   1028: rvar(k, v)
                   1029:        struct kinfo *k;
                   1030:        struct var *v;
                   1031: {
                   1032:        
                   1033:        if (k->ki_u)
                   1034:                printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v);
                   1035:        else
                   1036:                printf("%*s", v->width, "-");
                   1037: }
                   1038: 
                   1039: char *
                   1040: lookupcombo(cp)
                   1041:        char *cp;
                   1042: {
                   1043:        register struct combovar *cv = &combovar[0];
                   1044: 
                   1045:        for (; cv->name; cv++)
                   1046:                if (strcmp(cp, cv->name) == 0)
                   1047:                        return (cv->replace);
                   1048:        return (NULL);
                   1049: }
                   1050: 
                   1051: struct var *
                   1052: lookupvar(cp)
                   1053:        char *cp;
                   1054: {
                   1055:        register int i, j;
                   1056: 
                   1057:        for (i=0; var[i].name[0] != NULL; i++)
                   1058:                for (j=0; var[i].name[j] != NULL; j++)
                   1059:                        if (strcmp(cp, var[i].name[j]) == 0)
                   1060:                                return (&var[i]);
                   1061:        return (NULL);
                   1062: }
                   1063: 
                   1064: printval(bp, v)
                   1065:        char *bp;
                   1066:        struct var *v;
                   1067: {
                   1068:        static char ofmt[32] = "%";
                   1069:        register char *cp = ofmt+1, *fcp = v->fmt;
                   1070: 
                   1071:        if (v->flag & LJUST)
                   1072:                *cp++ = '-';
                   1073:        *cp++ = '*';
                   1074:        while (*cp++ = *fcp++)
                   1075:                ;
                   1076: 
                   1077:        switch (v->type) {
                   1078:        case CHAR:
                   1079:                printf(ofmt, v->width, *(char *)bp);
                   1080:                break;
                   1081: 
                   1082:        case UCHAR:
                   1083:                printf(ofmt, v->width, *(u_char *)bp);
                   1084:                break;
                   1085: 
                   1086:        case SHORT:
                   1087:                printf(ofmt, v->width, *(short *)bp);
                   1088:                break;
                   1089: 
                   1090:        case USHORT:
                   1091:                printf(ofmt, v->width, *(u_short *)bp);
                   1092:                break;
                   1093: 
                   1094:        case LONG:
                   1095:                printf(ofmt, v->width, *(long *)bp);
                   1096:                break;
                   1097: 
                   1098:        case ULONG:
                   1099:                printf(ofmt, v->width, *(u_long *)bp);
                   1100:                break;
                   1101: 
                   1102:        case KPTR:
                   1103:                printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
                   1104:                break;
                   1105: 
                   1106:        default:
                   1107:                error("unknown type %d", v->type);
                   1108:        }
                   1109: }
                   1110: 
                   1111: /* XXX - redo */
                   1112: struct usave *
                   1113: saveuser(ki) 
                   1114:        struct kinfo *ki;
                   1115: {
                   1116:        register struct usave *usp;
                   1117:        register struct user *up;
                   1118:        
                   1119:        if ((usp = (struct usave *)calloc(1, sizeof (struct usave))) == NULL) {
                   1120:                fprintf(stderr, "ps: out of memory\n");
                   1121:                exit(1);
                   1122:        }
                   1123:        ki->ki_u = usp;
                   1124:        up = kvm_getu(ki->ki_p);
                   1125:        /*
                   1126:         * save arguments if needed
                   1127:         */
                   1128:        if (needcomm)
                   1129:                ki->ki_args = saveargs(ki->ki_p, up);
                   1130:        else
                   1131:                ki->ki_args = NULL;
                   1132:        if (up != NULL) { 
                   1133:                /*
                   1134:                 * save important fields
                   1135:                 */
                   1136:                usp->u_procp = up->u_procp;
                   1137:                usp->u_start = up->u_start;
                   1138:                usp->u_ru = up->u_ru;
                   1139:                usp->u_cru = up->u_cru;
                   1140:                usp->u_cmask = up->u_cmask;
                   1141:                usp->u_acflag = up->u_acflag;
                   1142:        }
                   1143:        return;
                   1144: }
                   1145: 
                   1146: char *
                   1147: saveargs(p, up)
                   1148:        struct proc *p;
                   1149:        struct user *up;
                   1150: {
                   1151:        char *savestr();
                   1152: 
                   1153:        return(savestr(kvm_getargs(p, up)));
                   1154: }
                   1155:        
                   1156: 
                   1157: pscomp(k1, k2)
                   1158:        struct kinfo *k1, *k2;
                   1159: {
                   1160:        int i;
                   1161: #define VSIZE(k) ((k)->ki_p->p_dsize + (k)->ki_p->p_ssize + (k)->ki_e->e_xsize)
                   1162: 
                   1163:        if (sortby == SORTCPU)
                   1164:                return (getpcpu(k2) - getpcpu(k1));
                   1165: #ifdef notyet
                   1166:        if (sortby == SORTRUN)
                   1167:                return (proc_compare(k1->ki_p, k2->ki_p));
                   1168: #endif
                   1169:        if (sortby == SORTMEM)
                   1170:                return (VSIZE(k2) - VSIZE(k1));
                   1171:        i =  k1->ki_e->e_tdev - k2->ki_e->e_tdev;
                   1172:        if (i == 0)
                   1173:                i = k1->ki_p->p_pid - k2->ki_p->p_pid;
                   1174:        return (i);
                   1175: }
                   1176: 
                   1177: donlist()
                   1178: {
                   1179:        if (kvm_nlist(psnl) != 0)
                   1180:                error("can't get namelist");
                   1181:        if (kvm_read(psnl[X_FSCALE].n_value, &fscale, sizeof(int)) !=
                   1182:            sizeof (int))
                   1183:                error("error reading fscale: %s", kvm_geterr());
                   1184:        if (kvm_read(psnl[X_ECMX].n_value, &ecmx, sizeof(int)) !=
                   1185:            sizeof (int))
                   1186:                error("error reading ecmx: %s", kvm_geterr());
                   1187:        if (kvm_read(psnl[X_CCPU].n_value, &ccpu, sizeof(fixpt_t)) !=
                   1188:            sizeof (fixpt_t))
                   1189:                error("error reading ccpu: %s", kvm_geterr());
                   1190: }
                   1191: 
                   1192: char *
                   1193: savestr(cp)
                   1194:        char *cp;
                   1195: {
                   1196:        register unsigned len;
                   1197:        register char *dp;
                   1198: 
                   1199:        len = strlen(cp);
                   1200:        dp = (char *)calloc(len+1, sizeof (char));
                   1201:        (void) strcpy(dp, cp);
                   1202:        return (dp);
                   1203: }
                   1204: 
                   1205: error(a, b, c, d, e)
                   1206:        char *a, *b, *c, *d, *e;
                   1207: {
                   1208:        fprintf(stderr, "ps: ");
                   1209:        fprintf(stderr, a, b, c, d, e);
                   1210:        fprintf(stderr, "\n");
                   1211:        exit(1);
                   1212: }
                   1213: 
                   1214: syserror(a)
                   1215:        char *a;
                   1216: {
                   1217:        extern errno;
                   1218: 
                   1219:        error("%s: %s", a, strerror(errno));
                   1220: }
                   1221: 
                   1222: /*
                   1223:  * ICK (all for getopt), would rather hide the ugliness
                   1224:  * here than taint the main code.
                   1225:  *
                   1226:  *  ps foo -> ps -foo
                   1227:  *  ps 34 -> ps -p34
                   1228:  *
                   1229:  * The old convention that 't' with no trailing tty arg means the users
                   1230:  * tty, is only supported if argv[1] doesn't begin with a '-'.  This same
                   1231:  * feature is available with the option 'T', which takes no argument.
                   1232:  */
                   1233: char *
                   1234: kludge_oldps_options(s)
                   1235:        char *s;
                   1236: {
                   1237:        int len = strlen(s), numlen = 0;
                   1238:        char *newopts, *ns, *cp;
                   1239: 
                   1240:        if ((newopts = ns = (char *)malloc(len+2)) == NULL)
                   1241:                error("out of memory");
                   1242:        /*
                   1243:         * options begin with '-'
                   1244:         */
                   1245:        if (*s != '-')
                   1246:                *ns++ = '-';    /* add option flag */
                   1247:        /*
                   1248:         * gaze to end of argv[1]
                   1249:         */
                   1250:        cp = s + len - 1;
                   1251:        /*
                   1252:         * if last letter is a 't' flag with no argument (in the context
                   1253:         * of the oldps options -- option string NOT starting with a '-' --
                   1254:         * then convert to 'T' (meaning *this* terminal, i.e. ttyname(0).
                   1255:         */
                   1256:        if (*cp == 't' && *s != '-')
                   1257:                *cp = 'T';
                   1258:        else {
                   1259:                /*
                   1260:                 * otherwise check for trailing number, which *may* be a
                   1261:                 * pid.
                   1262:                 */
                   1263:                while (isdigit(*cp)) {
                   1264:                        --cp;
                   1265:                        numlen++;
                   1266:                }
                   1267:        }
                   1268:        cp++;
                   1269:        bcopy(s, ns, cp - s);   /* copy everything up to trailing number */
                   1270:        while (*ns)
                   1271:                ns++;
                   1272:        /*
                   1273:         * if there's a trailing number, and not a preceding 'p' (pid) or
                   1274:         * 't' (tty) flag, then assume it's a pid and insert a 'p' flag.
                   1275:         */
                   1276:        if (isdigit(*cp) && (cp == s || *(cp-1) != 't' && *(cp-1) != 'p' &&
                   1277:           ((cp-1) == s || *(cp-2) != 't')))
                   1278:                *ns++ = 'p';
                   1279:        strcat(ns, cp);         /* and append the number */
                   1280: 
                   1281:        return (newopts);
                   1282: }

unix.superglobalmegacorp.com

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