Annotation of 43BSDTahoe/etc/fstat.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1987 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that the above copyright notice and this paragraph are
                      7:  * duplicated in all such forms and that any documentation,
                      8:  * advertising materials, and other materials related to such
                      9:  * distribution and use acknowledge that the software was developed
                     10:  * by the University of California, Berkeley.  The name of the
                     11:  * University may not be used to endorse or promote products derived
                     12:  * from this software without specific prior written permission.
                     13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     16:  */
                     17: 
                     18: #ifndef lint
                     19: char copyright[] =
                     20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
                     21:  All rights reserved.\n";
                     22: #endif /* not lint */
                     23: 
                     24: #ifndef lint
                     25: static char sccsid[] = "@(#)fstat.c    5.13 (Berkeley) 6/18/88";
                     26: #endif /* not lint */
                     27: 
                     28: /*
                     29:  *  fstat 
                     30:  */
                     31: #include <machine/pte.h>
                     32: 
                     33: #include <sys/param.h>
                     34: #include <sys/dir.h>
                     35: #include <sys/user.h>
                     36: #include <sys/proc.h>
                     37: #include <sys/text.h>
                     38: #include <sys/stat.h>
                     39: #include <sys/inode.h>
                     40: #include <sys/socket.h>
                     41: #include <sys/socketvar.h>
                     42: #include <sys/domain.h>
                     43: #include <sys/protosw.h>
                     44: #include <sys/unpcb.h>
                     45: #include <sys/vmmac.h>
                     46: #define        KERNEL
                     47: #include <sys/file.h>
                     48: #undef KERNEL
                     49: #include <net/route.h>
                     50: #include <netinet/in.h>
                     51: #include <netinet/in_pcb.h>
                     52: #include <stdio.h>
                     53: #include <ctype.h>
                     54: #include <nlist.h>
                     55: #include <pwd.h>
                     56: 
                     57: #ifdef ULTRIX
                     58:                /* UFS -> GFS */
                     59: #    define    inode   gnode
                     60: #    define    x_iptr  x_gptr
                     61: #    define    i_dev   g_dev
                     62: #    define    i_number g_number
                     63: #    define    i_mode  g_mode
                     64: #    define    i_size  g_size
                     65: #endif
                     66: 
                     67: #define        N_KMEM  "/dev/kmem"
                     68: #define        N_MEM   "/dev/mem"
                     69: #define        N_SWAP  "/dev/drum"
                     70: #define        N_UNIX  "/vmunix"
                     71: 
                     72: #define        TEXT    -2
                     73: #define        WD      -1
                     74: 
                     75: typedef struct devs {
                     76:        struct devs *next;
                     77:        dev_t dev;
                     78:        int inum;
                     79:        char *name;
                     80: } DEVS;
                     81: DEVS *devs;
                     82: 
                     83: static struct nlist nl[] = {
                     84:        { "_proc" },
                     85: #define        X_PROC          0
                     86:        { "_Usrptmap" },
                     87: #define        X_USRPTMA       1
                     88:        { "_nproc" },
                     89: #define        X_NPROC         2
                     90:        { "_usrpt" },
                     91: #define        X_USRPT         3
                     92:        { "" },
                     93: };
                     94: 
                     95: struct proc *mproc;
                     96: struct pte *Usrptma, *usrpt;
                     97: 
                     98: union {
                     99:        struct user user;
                    100:        char upages[UPAGES][NBPG];
                    101: } user;
                    102: 
                    103: extern int errno;
                    104: static int fflg, vflg;
                    105: static int kmem, mem, nproc, swap;
                    106: static char *uname;
                    107: 
                    108: off_t lseek();
                    109: 
                    110: main(argc, argv)
                    111:        int argc;
                    112:        char **argv;
                    113: {
                    114:        extern char *optarg;
                    115:        extern int optind;
                    116:        register struct passwd *passwd;
                    117:        register int pflg, pid, uflg, uid;
                    118:        int ch, size;
                    119:        struct passwd *getpwnam(), *getpwuid();
                    120:        long lgetw();
                    121:        char *malloc();
                    122: 
                    123:        pflg = uflg = 0;
                    124:        while ((ch = getopt(argc, argv, "p:u:v")) != EOF)
                    125:                switch((char)ch) {
                    126:                case 'p':
                    127:                        if (pflg++)
                    128:                                usage();
                    129:                        if (!isdigit(*optarg)) {
                    130:                                fputs("fstat: -p option requires a process id.\n", stderr);
                    131:                                usage();
                    132:                        }
                    133:                        pid = atoi(optarg);
                    134:                        break;
                    135:                case 'u':
                    136:                        if (uflg++)
                    137:                                usage();
                    138:                        if (!(passwd = getpwnam(optarg))) {
                    139:                                fprintf(stderr, "%s: unknown uid\n", optarg);
                    140:                                exit(1);
                    141:                        }
                    142:                        uid = passwd->pw_uid;
                    143:                        uname = passwd->pw_name;
                    144:                        break;
                    145:                case 'v':       /* undocumented: print read error messages */
                    146:                        vflg++;
                    147:                        break;
                    148:                case '?':
                    149:                default:
                    150:                        usage();
                    151:                }
                    152: 
                    153:        if (*(argv += optind)) {
                    154:                for (; *argv; ++argv) {
                    155:                        if (getfname(*argv))
                    156:                                fflg = 1;
                    157:                }
                    158:                if (!fflg)      /* file(s) specified, but none accessable */
                    159:                        exit(1);
                    160:        }
                    161: 
                    162:        openfiles();
                    163: 
                    164:        if (nlist(N_UNIX, nl) == -1 || !nl[0].n_type) {
                    165:                fprintf(stderr, "%s: No namelist\n", N_UNIX);
                    166:                exit(1);
                    167:        }
                    168:        Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
                    169:        usrpt = (struct pte *) nl[X_USRPT].n_value;
                    170:        nproc = (int)lgetw((off_t)nl[X_NPROC].n_value);
                    171: 
                    172:        (void)lseek(kmem, lgetw((off_t)nl[X_PROC].n_value), L_SET);
                    173:        size = nproc * sizeof(struct proc);
                    174:        if ((mproc = (struct proc *)malloc((u_int)size)) == NULL) {
                    175:                fprintf(stderr, "fstat: out of space.\n");
                    176:                exit(1);
                    177:        }
                    178:        if (read(kmem, (char *)mproc, size) != size)
                    179:                rerr1("proc table", N_KMEM);
                    180: 
                    181:        printf("USER\t CMD\t      PID    FD\tDEVICE\tINODE\t  SIZE TYPE%s\n",
                    182:            fflg ? " NAME" : "");
                    183:        for (; nproc--; ++mproc) {
                    184:                if (mproc->p_stat == 0)
                    185:                        continue;
                    186:                if (pflg && mproc->p_pid != pid)
                    187:                        continue;
                    188:                if (uflg)  {
                    189:                        if (mproc->p_uid != uid)
                    190:                                continue;
                    191:                }
                    192:                else
                    193:                        uname = (passwd = getpwuid(mproc->p_uid)) ?
                    194:                            passwd->pw_name : "unknown";
                    195:                if (mproc->p_stat != SZOMB && getu() == 0)
                    196:                        continue;
                    197:                dotext();
                    198:                readf();
                    199:        }
                    200:        exit(0);
                    201: }
                    202: 
                    203: static
                    204: getu()
                    205: {
                    206:        struct pte *pteaddr, apte;
                    207:        struct pte arguutl[UPAGES+CLSIZE];
                    208:        register int i;
                    209:        int ncl;
                    210: 
                    211:        if ((mproc->p_flag & SLOAD) == 0) {
                    212:                if (swap < 0)
                    213:                        return(0);
                    214:                (void)lseek(swap, (off_t)dtob(mproc->p_swaddr), L_SET);
                    215:                if (read(swap, (char *)&user.user, sizeof(struct user))
                    216:                    != sizeof(struct user)) {
                    217:                        fprintf(stderr, "fstat: can't read u for pid %d from %s\n", mproc->p_pid, N_SWAP);
                    218:                        return(0);
                    219:                }
                    220:                return(1);
                    221:        }
                    222:        pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
                    223:        (void)lseek(kmem, (off_t)pteaddr, L_SET);
                    224:        if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
                    225:                printf("fstat: can't read indir pte to get u for pid %d from %s\n", mproc->p_pid, N_SWAP);
                    226:                return(0);
                    227:        }
                    228:        (void)lseek(mem, (off_t)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE)
                    229:            * sizeof(struct pte), L_SET);
                    230:        if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
                    231:                printf("fstat: can't read page table for u of pid %d from %s\n", mproc->p_pid, N_KMEM);
                    232:                return(0);
                    233:        }
                    234:        ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
                    235:        while (--ncl >= 0) {
                    236:                i = ncl * CLSIZE;
                    237:                (void)lseek(mem, (off_t)ctob(arguutl[CLSIZE+i].pg_pfnum), L_SET);
                    238:                if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
                    239:                        printf("fstat: can't read page %u of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, N_MEM);
                    240:                        return(0);
                    241:                }
                    242:        }
                    243:        return(1);
                    244: }
                    245: 
                    246: static
                    247: dotext()
                    248: {
                    249:        struct text text;
                    250: 
                    251:        (void)lseek(kmem, (off_t)mproc->p_textp, L_SET);
                    252:        if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) {
                    253:                rerr1("text table", N_KMEM);
                    254:                return;
                    255:        }
                    256:        if (text.x_flag)
                    257:                itrans(DTYPE_INODE, text.x_iptr, TEXT);
                    258: }
                    259: 
                    260: static
                    261: itrans(ftype, g, fno)
                    262:        int ftype, fno;
                    263:        struct inode *g;                /* if ftype is inode */
                    264: {
                    265:        struct inode inode;
                    266:        dev_t idev;
                    267:        char *comm, *itype();
                    268:        char *name = (char *)NULL;      /* set by devmatch() on a match */
                    269: 
                    270:        if (g || fflg) {
                    271:                (void)lseek(kmem, (off_t)g, L_SET);
                    272:                if (read(kmem, (char *)&inode, sizeof(inode)) != sizeof(inode)) {
                    273:                        rerr2(errno, (int)g, "inode");
                    274:                        return;
                    275:                }
                    276:                idev = inode.i_dev;
                    277:                if (fflg && !devmatch(idev, inode.i_number, &name))
                    278:                        return;
                    279:        }
                    280:        if (mproc->p_pid == 0)
                    281:                comm = "swapper";
                    282:        else if (mproc->p_pid == 2)
                    283:                comm = "pagedaemon";
                    284:        else
                    285:                comm = user.user.u_comm;
                    286:        printf("%-8.8s %-10.10s %5d  ", uname, comm, mproc->p_pid);
                    287: 
                    288:        switch(fno) {
                    289:        case WD:
                    290:                printf("  wd"); break;
                    291:        case TEXT:
                    292:                printf("text"); break;
                    293:        default:
                    294:                printf("%4d", fno);
                    295:        }
                    296: 
                    297:        if (g == 0) {
                    298:                printf("* (deallocated)\n");
                    299:                return;
                    300:        }
                    301: 
                    302:        switch(ftype) {
                    303:        case DTYPE_INODE:
                    304:                printf("\t%2d, %2d\t%5lu\t%6ld\t%3s %s\n", major(inode.i_dev),
                    305:                    minor(inode.i_dev), inode.i_number,
                    306:                    inode.i_mode == IFSOCK ? 0 : inode.i_size,
                    307:                    itype(inode.i_mode), name ? name : "");
                    308:                break;
                    309:        case DTYPE_SOCKET:
                    310:                socktrans((struct socket *)g);
                    311:                break;
                    312: #ifdef DTYPE_PORT
                    313:        case DTYPE_PORT:
                    314:                printf("* (fifo / named pipe)\n");
                    315:                break;
                    316: #endif
                    317:        default:
                    318:                printf("* (unknown file type)\n");
                    319:        }
                    320: }
                    321: 
                    322: static char *
                    323: itype(mode)
                    324:        u_short mode;
                    325: {
                    326:        switch(mode & IFMT) {
                    327:        case IFCHR:
                    328:                return("chr");
                    329:        case IFDIR:
                    330:                return("dir");
                    331:        case IFBLK:
                    332:                return("blk");
                    333:        case IFREG:
                    334:                return("reg");
                    335:        case IFLNK:
                    336:                return("lnk");
                    337:        case IFSOCK:
                    338:                return("soc");
                    339:        default:
                    340:                return("unk");
                    341:        }
                    342:        /*NOTREACHED*/
                    343: }
                    344: 
                    345: static
                    346: socktrans(sock)
                    347:        struct socket *sock;
                    348: {
                    349:        static char *stypename[] = {
                    350:                "unused",       /* 0 */
                    351:                "stream",       /* 1 */
                    352:                "dgram",        /* 2 */
                    353:                "raw",          /* 3 */
                    354:                "rdm",          /* 4 */
                    355:                "seqpak"        /* 5 */
                    356:        };
                    357: #define        STYPEMAX 5
                    358:        struct socket   so;
                    359:        struct protosw  proto;
                    360:        struct domain   dom;
                    361:        struct inpcb    inpcb;
                    362:        struct unpcb    unpcb;
                    363:        int len;
                    364:        char dname[32], *strcpy();
                    365: 
                    366:        /* fill in socket */
                    367:        (void)lseek(kmem, (off_t)sock, L_SET);
                    368:        if (read(kmem, (char *)&so, sizeof(struct socket))
                    369:            != sizeof(struct socket)) {
                    370:                rerr2(errno, (int)sock, "socket");
                    371:                return;
                    372:        }
                    373: 
                    374:        /* fill in protosw entry */
                    375:        (void)lseek(kmem, (off_t)so.so_proto, L_SET);
                    376:        if (read(kmem, (char *)&proto, sizeof(struct protosw))
                    377:            != sizeof(struct protosw)) {
                    378:                rerr2(errno, (int)so.so_proto, "protosw");
                    379:                return;
                    380:        }
                    381: 
                    382:        /* fill in domain */
                    383:        (void)lseek(kmem, (off_t)proto.pr_domain, L_SET);
                    384:        if (read(kmem, (char *)&dom, sizeof(struct domain))
                    385:            != sizeof(struct domain)) {
                    386:                rerr2(errno, (int)proto.pr_domain, "domain");
                    387:                return;
                    388:        }
                    389: 
                    390:        /*
                    391:         * grab domain name
                    392:         * kludge "internet" --> "inet" for brevity
                    393:         */
                    394:        if (dom.dom_family == AF_INET)
                    395:                (void)strcpy(dname, "inet");
                    396:        else {
                    397:                (void)lseek(kmem, (off_t)dom.dom_name, L_SET);
                    398:                if ((len = read(kmem, dname, sizeof(dname) - 1)) < 0) {
                    399:                        rerr2(errno, (int)dom.dom_name, "char");
                    400:                        dname[0] = '\0';
                    401:                }
                    402:                else
                    403:                        dname[len] = '\0';
                    404:        }
                    405: 
                    406:        if ((u_short)so.so_type > STYPEMAX)
                    407:                printf("* (%s unk%d %x", dname, so.so_type, so.so_state);
                    408:        else
                    409:                printf("* (%s %s %x", dname, stypename[so.so_type],
                    410:                    so.so_state);
                    411: 
                    412:        /* 
                    413:         * protocol specific formatting
                    414:         *
                    415:         * Try to find interesting things to print.  For tcp, the interesting
                    416:         * thing is the address of the tcpcb, for udp and others, just the
                    417:         * inpcb (socket pcb).  For unix domain, its the address of the socket
                    418:         * pcb and the address of the connected pcb (if connected).  Otherwise
                    419:         * just print the protocol number and address of the socket itself.
                    420:         * The idea is not to duplicate netstat, but to make available enough
                    421:         * information for further analysis.
                    422:         */
                    423:        switch(dom.dom_family) {
                    424:        case AF_INET:
                    425:                getinetproto(proto.pr_protocol);
                    426:                if (proto.pr_protocol == IPPROTO_TCP ) {
                    427:                        if (so.so_pcb) {
                    428:                                (void)lseek(kmem, (off_t)so.so_pcb, L_SET);
                    429:                                if (read(kmem, (char *)&inpcb, sizeof(struct inpcb))
                    430:                                    != sizeof(struct inpcb)){
                    431:                                        rerr2(errno, (int)so.so_pcb, "inpcb");
                    432:                                        return;
                    433:                                }
                    434:                                printf(" %x", (int)inpcb.inp_ppcb);
                    435:                        }
                    436:                }
                    437:                else if (so.so_pcb)
                    438:                        printf(" %x", (int)so.so_pcb);
                    439:                break;
                    440:        case AF_UNIX:
                    441:                /* print address of pcb and connected pcb */
                    442:                if (so.so_pcb) {
                    443:                        printf(" %x", (int)so.so_pcb);
                    444:                        (void)lseek(kmem, (off_t)so.so_pcb, L_SET);
                    445:                        if (read(kmem, (char *)&unpcb, sizeof(struct unpcb))
                    446:                            != sizeof(struct unpcb)){
                    447:                                rerr2(errno, (int)so.so_pcb, "unpcb");
                    448:                                return;
                    449:                        }
                    450:                        if (unpcb.unp_conn) {
                    451:                                char shoconn[4], *cp;
                    452: 
                    453:                                cp = shoconn;
                    454:                                if (!(so.so_state & SS_CANTRCVMORE))
                    455:                                        *cp++ = '<';
                    456:                                *cp++ = '-';
                    457:                                if (!(so.so_state & SS_CANTSENDMORE))
                    458:                                        *cp++ = '>';
                    459:                                *cp = '\0';
                    460:                                printf(" %s %x", shoconn, (int)unpcb.unp_conn);
                    461:                        }
                    462:                }
                    463:                break;
                    464:        default:
                    465:                /* print protocol number and socket address */
                    466:                printf(" %d %x", proto.pr_protocol, (int)sock);
                    467:        }
                    468:        printf(")\n");
                    469: }
                    470: 
                    471: /*
                    472:  * getinetproto --
                    473:  *     print name of protocol number
                    474:  */
                    475: static
                    476: getinetproto(number)
                    477:        int number;
                    478: {
                    479:        char *cp;
                    480: 
                    481:        switch(number) {
                    482:        case IPPROTO_IP:
                    483:                cp = "ip"; break;
                    484:        case IPPROTO_ICMP:
                    485:                cp ="icmp"; break;
                    486:        case IPPROTO_GGP:
                    487:                cp ="ggp"; break;
                    488:        case IPPROTO_TCP:
                    489:                cp ="tcp"; break;
                    490:        case IPPROTO_EGP:
                    491:                cp ="egp"; break;
                    492:        case IPPROTO_PUP:
                    493:                cp ="pup"; break;
                    494:        case IPPROTO_UDP:
                    495:                cp ="udp"; break;
                    496:        case IPPROTO_IDP:
                    497:                cp ="idp"; break;
                    498:        case IPPROTO_RAW:
                    499:                cp ="raw"; break;
                    500:        default:
                    501:                printf(" %d", number);
                    502:                return;
                    503:        }
                    504:        printf(" %s", cp);
                    505: }
                    506: 
                    507: static
                    508: readf()
                    509: {
                    510:        struct file lfile;
                    511:        int i;
                    512: 
                    513:        itrans(DTYPE_INODE, user.user.u_cdir, WD);
                    514:        for (i = 0; i < NOFILE; i++) {
                    515:                if (user.user.u_ofile[i] == 0)
                    516:                        continue;
                    517:                (void)lseek(kmem, (off_t)user.user.u_ofile[i], L_SET);
                    518:                if (read(kmem, (char *)&lfile, sizeof(lfile))
                    519:                    != sizeof(lfile)) {
                    520:                        rerr1("file", N_KMEM);
                    521:                        continue;
                    522:                }
                    523:                itrans(lfile.f_type, (struct inode *)lfile.f_data, i);
                    524:        }
                    525: }
                    526: 
                    527: static
                    528: devmatch(idev, inum, name)
                    529:        dev_t idev;
                    530:        ino_t inum;
                    531:        char  **name;
                    532: {
                    533:        register DEVS *d;
                    534: 
                    535:        for (d = devs; d; d = d->next)
                    536:                if (d->dev == idev && (d->inum == 0 || d->inum == inum)) {
                    537:                        *name = d->name;
                    538:                        return(1);
                    539:                }
                    540:        return(0);
                    541: }
                    542: 
                    543: static
                    544: getfname(filename)
                    545:        char *filename;
                    546: {
                    547:        struct stat statbuf;
                    548:        DEVS *cur;
                    549:        char *malloc();
                    550: 
                    551:        if (stat(filename, &statbuf)) {
                    552:                perror(filename);
                    553:                return(0);
                    554:        }
                    555:        if ((cur = (DEVS *)malloc(sizeof(DEVS))) == NULL) {
                    556:                fprintf(stderr, "fstat: out of space.\n");
                    557:                exit(1);
                    558:        }
                    559:        cur->next = devs;
                    560:        devs = cur;
                    561: 
                    562:        /* if file is block special, look for open files on it */
                    563:        if ((statbuf.st_mode & S_IFMT) != S_IFBLK) {
                    564:                cur->inum = statbuf.st_ino;
                    565:                cur->dev = statbuf.st_dev;
                    566:        }
                    567:        else {
                    568:                cur->inum = 0;
                    569:                cur->dev = statbuf.st_rdev;
                    570:        }
                    571:        cur->name = filename;
                    572:        return(1);
                    573: }
                    574: 
                    575: static
                    576: openfiles()
                    577: {
                    578:        if ((kmem = open(N_KMEM, O_RDONLY, 0)) < 0) {
                    579:                perror(N_KMEM);
                    580:                exit(1);
                    581:        }
                    582:        if ((mem = open(N_MEM, O_RDONLY, 0)) < 0) {
                    583:                perror(N_MEM);
                    584:                exit(1);
                    585:        }
                    586:        if ((swap = open(N_SWAP, O_RDONLY, 0)) < 0) {
                    587:                perror(N_SWAP);
                    588:                exit(1);
                    589:        }
                    590: }
                    591: 
                    592: static
                    593: rerr1(what, fromwhat)
                    594:        char *what, *fromwhat;
                    595: {
                    596:        if (vflg)
                    597:                printf("fstat: error reading %s from %s", what, fromwhat);
                    598: }
                    599: 
                    600: static
                    601: rerr2(err, address, what)
                    602:        int err, address;
                    603:        char *what;
                    604: {
                    605:        if (vflg)
                    606:                printf("error %d reading %s at %x from kmem\n", errno, what, address);
                    607: }
                    608: 
                    609: static long
                    610: lgetw(loc)
                    611:        off_t loc;
                    612: {
                    613:        long word;
                    614: 
                    615:        (void)lseek(kmem, (off_t)loc, L_SET);
                    616:        if (read(kmem, (char *)&word, sizeof(word)) != sizeof(word))
                    617:                rerr2(errno, (int)loc, "word");
                    618:        return(word);
                    619: }
                    620: 
                    621: static
                    622: usage()
                    623: {
                    624:        fputs("usage: fstat [-v] [-u user] [-p pid] [filename ...]\n", stderr);
                    625:        exit(1);
                    626: }

unix.superglobalmegacorp.com

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