[BACK]Return to fstat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / fstat

Annotation of src/usr.bin/fstat/fstat.c, Revision 1.1

1.1     ! deraadt     1: /*-
        !             2:  * Copyright (c) 1988, 1993
        !             3:  *     The Regents of the University of California.  All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: #ifndef lint
        !            35: static char copyright[] =
        !            36: "@(#) Copyright (c) 1988, 1993\n\
        !            37:        The Regents of the University of California.  All rights reserved.\n";
        !            38: #endif /* not lint */
        !            39:
        !            40: #ifndef lint
        !            41: /*static char sccsid[] = "from: @(#)fstat.c    8.1 (Berkeley) 6/6/93";*/
        !            42: static char *rcsid = "$Id: fstat.c,v 1.14 1995/03/28 17:24:12 jtc Exp $";
        !            43: #endif /* not lint */
        !            44:
        !            45: #include <sys/param.h>
        !            46: #include <sys/time.h>
        !            47: #include <sys/proc.h>
        !            48: #include <sys/user.h>
        !            49: #include <sys/stat.h>
        !            50: #include <sys/vnode.h>
        !            51: #include <sys/socket.h>
        !            52: #include <sys/socketvar.h>
        !            53: #include <sys/domain.h>
        !            54: #include <sys/protosw.h>
        !            55: #include <sys/unpcb.h>
        !            56: #include <sys/sysctl.h>
        !            57: #include <sys/filedesc.h>
        !            58: #define        _KERNEL
        !            59: #include <sys/file.h>
        !            60: #include <ufs/ufs/quota.h>
        !            61: #include <ufs/ufs/inode.h>
        !            62: #undef _KERNEL
        !            63: #define NFS
        !            64: #include <sys/mount.h>
        !            65: #include <nfs/nfsv2.h>
        !            66: #include <nfs/rpcv2.h>
        !            67: #include <nfs/nfs.h>
        !            68: #include <nfs/nfsnode.h>
        !            69: #undef NFS
        !            70:
        !            71: #include <net/route.h>
        !            72: #include <netinet/in.h>
        !            73: #include <netinet/in_systm.h>
        !            74: #include <netinet/ip.h>
        !            75: #include <netinet/in_pcb.h>
        !            76:
        !            77: #include <ctype.h>
        !            78: #include <errno.h>
        !            79: #include <kvm.h>
        !            80: #include <nlist.h>
        !            81: #include <paths.h>
        !            82: #include <pwd.h>
        !            83: #include <stdio.h>
        !            84: #include <stdlib.h>
        !            85: #include <string.h>
        !            86:
        !            87: #define        TEXT    -1
        !            88: #define        CDIR    -2
        !            89: #define        RDIR    -3
        !            90: #define        TRACE   -4
        !            91:
        !            92: typedef struct devs {
        !            93:        struct  devs *next;
        !            94:        long    fsid;
        !            95:        ino_t   ino;
        !            96:        char    *name;
        !            97: } DEVS;
        !            98: DEVS *devs;
        !            99:
        !           100: struct  filestat {
        !           101:        long    fsid;
        !           102:        long    fileid;
        !           103:        mode_t  mode;
        !           104:        u_long  size;
        !           105:        dev_t   rdev;
        !           106: };
        !           107:
        !           108: #ifdef notdef
        !           109: struct nlist nl[] = {
        !           110:        { "" },
        !           111: };
        !           112: #endif
        !           113:
        !           114: int    fsflg,  /* show files on same filesystem as file(s) argument */
        !           115:        pflg,   /* show files open by a particular pid */
        !           116:        uflg;   /* show files open by a particular (effective) user */
        !           117: int    checkfile; /* true if restricting to particular files or filesystems */
        !           118: int    nflg;   /* (numerical) display f.s. and rdev as dev_t */
        !           119: int    vflg;   /* display errors in locating kernel data objects etc... */
        !           120:
        !           121: #define dprintf        if (vflg) fprintf
        !           122:
        !           123: struct file **ofiles;  /* buffer of pointers to file structures */
        !           124: int maxfiles;
        !           125: #define ALLOC_OFILES(d)        \
        !           126:        if ((d) > maxfiles) { \
        !           127:                free(ofiles); \
        !           128:                ofiles = malloc((d) * sizeof(struct file *)); \
        !           129:                if (ofiles == NULL) { \
        !           130:                        fprintf(stderr, "fstat: %s\n", strerror(errno)); \
        !           131:                        exit(1); \
        !           132:                } \
        !           133:                maxfiles = (d); \
        !           134:        }
        !           135:
        !           136: /*
        !           137:  * a kvm_read that returns true if everything is read
        !           138:  */
        !           139: #define KVM_READ(kaddr, paddr, len) \
        !           140:        (kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (len))
        !           141:
        !           142: kvm_t *kd;
        !           143:
        !           144: int ufs_filestat(), nfs_filestat();
        !           145: void dofiles(), getinetproto(), socktrans();
        !           146: void usage(), vtrans();
        !           147:
        !           148: main(argc, argv)
        !           149:        int argc;
        !           150:        char **argv;
        !           151: {
        !           152:        extern char *optarg;
        !           153:        extern int optind;
        !           154:        register struct passwd *passwd;
        !           155:        struct kinfo_proc *p, *plast;
        !           156:        int arg, ch, what;
        !           157:        char *memf, *nlistf;
        !           158:        int cnt;
        !           159:
        !           160:        arg = 0;
        !           161:        what = KERN_PROC_ALL;
        !           162:        nlistf = memf = NULL;
        !           163:        while ((ch = getopt(argc, argv, "fnp:u:vNM")) != EOF)
        !           164:                switch((char)ch) {
        !           165:                case 'f':
        !           166:                        fsflg = 1;
        !           167:                        break;
        !           168:                case 'M':
        !           169:                        memf = optarg;
        !           170:                        break;
        !           171:                case 'N':
        !           172:                        nlistf = optarg;
        !           173:                        break;
        !           174:                case 'n':
        !           175:                        nflg = 1;
        !           176:                        break;
        !           177:                case 'p':
        !           178:                        if (pflg++)
        !           179:                                usage();
        !           180:                        if (!isdigit(*optarg)) {
        !           181:                                fprintf(stderr,
        !           182:                                    "fstat: -p requires a process id\n");
        !           183:                                usage();
        !           184:                        }
        !           185:                        what = KERN_PROC_PID;
        !           186:                        arg = atoi(optarg);
        !           187:                        break;
        !           188:                case 'u':
        !           189:                        if (uflg++)
        !           190:                                usage();
        !           191:                        if (!(passwd = getpwnam(optarg))) {
        !           192:                                fprintf(stderr, "%s: unknown uid\n",
        !           193:                                    optarg);
        !           194:                                exit(1);
        !           195:                        }
        !           196:                        what = KERN_PROC_UID;
        !           197:                        arg = passwd->pw_uid;
        !           198:                        break;
        !           199:                case 'v':
        !           200:                        vflg = 1;
        !           201:                        break;
        !           202:                case '?':
        !           203:                default:
        !           204:                        usage();
        !           205:                }
        !           206:
        !           207:        if (*(argv += optind)) {
        !           208:                for (; *argv; ++argv) {
        !           209:                        if (getfname(*argv))
        !           210:                                checkfile = 1;
        !           211:                }
        !           212:                if (!checkfile) /* file(s) specified, but none accessable */
        !           213:                        exit(1);
        !           214:        }
        !           215:
        !           216:        ALLOC_OFILES(256);      /* reserve space for file pointers */
        !           217:
        !           218:        if (fsflg && !checkfile) {
        !           219:                /* -f with no files means use wd */
        !           220:                if (getfname(".") == 0)
        !           221:                        exit(1);
        !           222:                checkfile = 1;
        !           223:        }
        !           224:
        !           225:        /*
        !           226:         * Discard setgid privileges if not the running kernel so that bad
        !           227:         * guys can't print interesting stuff from kernel memory.
        !           228:         */
        !           229:        if (nlistf != NULL || memf != NULL)
        !           230:                setgid(getgid());
        !           231:
        !           232:        if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, NULL)) == NULL) {
        !           233:                fprintf(stderr, "fstat: %s\n", kvm_geterr(kd));
        !           234:                exit(1);
        !           235:        }
        !           236: #ifdef notdef
        !           237:        if (kvm_nlist(kd, nl) != 0) {
        !           238:                fprintf(stderr, "fstat: no namelist: %s\n", kvm_geterr(kd));
        !           239:                exit(1);
        !           240:        }
        !           241: #endif
        !           242:        if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) {
        !           243:                fprintf(stderr, "fstat: %s\n", kvm_geterr(kd));
        !           244:                exit(1);
        !           245:        }
        !           246:        if (nflg)
        !           247:                printf("%s",
        !           248: "USER     CMD          PID   FD  DEV    INUM       MODE SZ|DV R/W");
        !           249:        else
        !           250:                printf("%s",
        !           251: "USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W");
        !           252:        if (checkfile && fsflg == 0)
        !           253:                printf(" NAME\n");
        !           254:        else
        !           255:                putchar('\n');
        !           256:
        !           257:        for (plast = &p[cnt]; p < plast; ++p) {
        !           258:                if (p->kp_proc.p_stat == SZOMB)
        !           259:                        continue;
        !           260:                dofiles(p);
        !           261:        }
        !           262:        exit(0);
        !           263: }
        !           264:
        !           265: char   *Uname, *Comm;
        !           266: int    Pid;
        !           267:
        !           268: #define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \
        !           269:        switch(i) { \
        !           270:        case TEXT: \
        !           271:                printf(" text"); \
        !           272:                break; \
        !           273:        case CDIR: \
        !           274:                printf("   wd"); \
        !           275:                break; \
        !           276:        case RDIR: \
        !           277:                printf(" root"); \
        !           278:                break; \
        !           279:        case TRACE: \
        !           280:                printf("   tr"); \
        !           281:                break; \
        !           282:        default: \
        !           283:                printf(" %4d", i); \
        !           284:                break; \
        !           285:        }
        !           286:
        !           287: /*
        !           288:  * print open files attributed to this process
        !           289:  */
        !           290: void
        !           291: dofiles(kp)
        !           292:        struct kinfo_proc *kp;
        !           293: {
        !           294:        int i, last;
        !           295:        struct file file;
        !           296:        struct filedesc0 filed0;
        !           297: #define        filed   filed0.fd_fd
        !           298:        struct proc *p = &kp->kp_proc;
        !           299:        struct eproc *ep = &kp->kp_eproc;
        !           300:
        !           301:        extern char *user_from_uid();
        !           302:
        !           303:        Uname = user_from_uid(ep->e_ucred.cr_uid, 0);
        !           304:        Pid = p->p_pid;
        !           305:        Comm = p->p_comm;
        !           306:
        !           307:        if (p->p_fd == NULL)
        !           308:                return;
        !           309:        if (!KVM_READ(p->p_fd, &filed0, sizeof (filed0))) {
        !           310:                dprintf(stderr, "can't read filedesc at %x for pid %d\n",
        !           311:                        p->p_fd, Pid);
        !           312:                return;
        !           313:        }
        !           314:        if (filed.fd_nfiles < 0 || filed.fd_lastfile >= filed.fd_nfiles ||
        !           315:            filed.fd_freefile > filed.fd_lastfile + 1) {
        !           316:                dprintf(stderr, "filedesc corrupted at %x for pid %d\n",
        !           317:                        p->p_fd, Pid);
        !           318:                return;
        !           319:        }
        !           320:        /*
        !           321:         * root directory vnode, if one
        !           322:         */
        !           323:        if (filed.fd_rdir)
        !           324:                vtrans(filed.fd_rdir, RDIR, FREAD);
        !           325:        /*
        !           326:         * current working directory vnode
        !           327:         */
        !           328:        vtrans(filed.fd_cdir, CDIR, FREAD);
        !           329:        /*
        !           330:         * ktrace vnode, if one
        !           331:         */
        !           332:        if (p->p_tracep)
        !           333:                vtrans(p->p_tracep, TRACE, FREAD|FWRITE);
        !           334:        /*
        !           335:         * open files
        !           336:         */
        !           337: #define FPSIZE (sizeof (struct file *))
        !           338:        ALLOC_OFILES(filed.fd_lastfile+1);
        !           339:        if (filed.fd_nfiles > NDFILE) {
        !           340:                if (!KVM_READ(filed.fd_ofiles, ofiles,
        !           341:                    (filed.fd_lastfile+1) * FPSIZE)) {
        !           342:                        dprintf(stderr,
        !           343:                            "can't read file structures at %x for pid %d\n",
        !           344:                            filed.fd_ofiles, Pid);
        !           345:                        return;
        !           346:                }
        !           347:        } else
        !           348:                bcopy(filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE);
        !           349:        for (i = 0; i <= filed.fd_lastfile; i++) {
        !           350:                if (ofiles[i] == NULL)
        !           351:                        continue;
        !           352:                if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) {
        !           353:                        dprintf(stderr, "can't read file %d at %x for pid %d\n",
        !           354:                                i, ofiles[i], Pid);
        !           355:                        continue;
        !           356:                }
        !           357:                if (file.f_type == DTYPE_VNODE)
        !           358:                        vtrans((struct vnode *)file.f_data, i, file.f_flag);
        !           359:                else if (file.f_type == DTYPE_SOCKET) {
        !           360:                        if (checkfile == 0)
        !           361:                                socktrans((struct socket *)file.f_data, i);
        !           362:                }
        !           363:                else {
        !           364:                        dprintf(stderr,
        !           365:                                "unknown file type %d for file %d of pid %d\n",
        !           366:                                file.f_type, i, Pid);
        !           367:                }
        !           368:        }
        !           369: }
        !           370:
        !           371: void
        !           372: vtrans(vp, i, flag)
        !           373:        struct vnode *vp;
        !           374:        int i;
        !           375:        int flag;
        !           376: {
        !           377:        struct vnode vn;
        !           378:        struct filestat fst;
        !           379:        char rw[3], mode[15];
        !           380:        char *badtype = NULL, *filename, *getmnton();
        !           381:
        !           382:        filename = badtype = NULL;
        !           383:        if (!KVM_READ(vp, &vn, sizeof (struct vnode))) {
        !           384:                dprintf(stderr, "can't read vnode at %x for pid %d\n",
        !           385:                        vp, Pid);
        !           386:                return;
        !           387:        }
        !           388:        if (vn.v_type == VNON || vn.v_tag == VT_NON)
        !           389:                badtype = "none";
        !           390:        else if (vn.v_type == VBAD)
        !           391:                badtype = "bad";
        !           392:        else
        !           393:                switch (vn.v_tag) {
        !           394:                case VT_UFS:
        !           395:                        if (!ufs_filestat(&vn, &fst))
        !           396:                                badtype = "error";
        !           397:                        break;
        !           398:                case VT_MFS:
        !           399:                        if (!ufs_filestat(&vn, &fst))
        !           400:                                badtype = "error";
        !           401:                        break;
        !           402:                case VT_NFS:
        !           403:                        if (!nfs_filestat(&vn, &fst))
        !           404:                                badtype = "error";
        !           405:                        break;
        !           406:                default: {
        !           407:                        static char unknown[10];
        !           408:                        sprintf(badtype = unknown, "?(%x)", vn.v_tag);
        !           409:                        break;;
        !           410:                }
        !           411:        }
        !           412:        if (checkfile) {
        !           413:                int fsmatch = 0;
        !           414:                register DEVS *d;
        !           415:
        !           416:                if (badtype)
        !           417:                        return;
        !           418:                for (d = devs; d != NULL; d = d->next)
        !           419:                        if (d->fsid == fst.fsid) {
        !           420:                                fsmatch = 1;
        !           421:                                if (d->ino == fst.fileid) {
        !           422:                                        filename = d->name;
        !           423:                                        break;
        !           424:                                }
        !           425:                        }
        !           426:                if (fsmatch == 0 || (filename == NULL && fsflg == 0))
        !           427:                        return;
        !           428:        }
        !           429:        PREFIX(i);
        !           430:        if (badtype) {
        !           431:                (void)printf(" -         -  %10s    -\n", badtype);
        !           432:                return;
        !           433:        }
        !           434:        if (nflg)
        !           435:                (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid));
        !           436:        else
        !           437:                (void)printf(" %-8s", getmnton(vn.v_mount));
        !           438:        if (nflg)
        !           439:                (void)sprintf(mode, "%o", fst.mode);
        !           440:        else
        !           441:                strmode(fst.mode, mode);
        !           442:        (void)printf(" %6d %10s", fst.fileid, mode);
        !           443:        switch (vn.v_type) {
        !           444:        case VBLK:
        !           445:        case VCHR: {
        !           446:                char *name;
        !           447:
        !           448:                if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ?
        !           449:                    S_IFCHR : S_IFBLK)) == NULL))
        !           450:                        printf("  %2d,%-2d", major(fst.rdev), minor(fst.rdev));
        !           451:                else
        !           452:                        printf(" %6s", name);
        !           453:                break;
        !           454:        }
        !           455:        default:
        !           456:                printf(" %6d", fst.size);
        !           457:        }
        !           458:        rw[0] = '\0';
        !           459:        if (flag & FREAD)
        !           460:                strcat(rw, "r");
        !           461:        if (flag & FWRITE)
        !           462:                strcat(rw, "w");
        !           463:        printf(" %2s", rw);
        !           464:        if (filename && !fsflg)
        !           465:                printf("  %s", filename);
        !           466:        putchar('\n');
        !           467: }
        !           468:
        !           469: int
        !           470: ufs_filestat(vp, fsp)
        !           471:        struct vnode *vp;
        !           472:        struct filestat *fsp;
        !           473: {
        !           474:        struct inode inode;
        !           475:
        !           476:        if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
        !           477:                dprintf(stderr, "can't read inode at %x for pid %d\n",
        !           478:                        VTOI(vp), Pid);
        !           479:                return 0;
        !           480:        }
        !           481:        fsp->fsid = inode.i_dev & 0xffff;
        !           482:        fsp->fileid = (long)inode.i_number;
        !           483:        fsp->mode = (mode_t)inode.i_mode;
        !           484:        fsp->size = (u_long)inode.i_size;
        !           485:        fsp->rdev = inode.i_rdev;
        !           486:
        !           487:        return 1;
        !           488: }
        !           489:
        !           490: int
        !           491: nfs_filestat(vp, fsp)
        !           492:        struct vnode *vp;
        !           493:        struct filestat *fsp;
        !           494: {
        !           495:        struct nfsnode nfsnode;
        !           496:        register mode_t mode;
        !           497:
        !           498:        if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
        !           499:                dprintf(stderr, "can't read nfsnode at %x for pid %d\n",
        !           500:                        VTONFS(vp), Pid);
        !           501:                return 0;
        !           502:        }
        !           503:        fsp->fsid = nfsnode.n_vattr.va_fsid;
        !           504:        fsp->fileid = nfsnode.n_vattr.va_fileid;
        !           505:        fsp->size = nfsnode.n_size;
        !           506:        fsp->rdev = nfsnode.n_vattr.va_rdev;
        !           507:        mode = (mode_t)nfsnode.n_vattr.va_mode;
        !           508:        switch (vp->v_type) {
        !           509:        case VREG:
        !           510:                mode |= S_IFREG;
        !           511:                break;
        !           512:        case VDIR:
        !           513:                mode |= S_IFDIR;
        !           514:                break;
        !           515:        case VBLK:
        !           516:                mode |= S_IFBLK;
        !           517:                break;
        !           518:        case VCHR:
        !           519:                mode |= S_IFCHR;
        !           520:                break;
        !           521:        case VLNK:
        !           522:                mode |= S_IFLNK;
        !           523:                break;
        !           524:        case VSOCK:
        !           525:                mode |= S_IFSOCK;
        !           526:                break;
        !           527:        case VFIFO:
        !           528:                mode |= S_IFIFO;
        !           529:                break;
        !           530:        };
        !           531:        fsp->mode = mode;
        !           532:
        !           533:        return 1;
        !           534: }
        !           535:
        !           536:
        !           537: char *
        !           538: getmnton(m)
        !           539:        struct mount *m;
        !           540: {
        !           541:        static struct mount mount;
        !           542:        static struct mtab {
        !           543:                struct mtab *next;
        !           544:                struct mount *m;
        !           545:                char mntonname[MNAMELEN];
        !           546:        } *mhead = NULL;
        !           547:        register struct mtab *mt;
        !           548:
        !           549:        for (mt = mhead; mt != NULL; mt = mt->next)
        !           550:                if (m == mt->m)
        !           551:                        return (mt->mntonname);
        !           552:        if (!KVM_READ(m, &mount, sizeof(struct mount))) {
        !           553:                fprintf(stderr, "can't read mount table at %x\n", m);
        !           554:                return (NULL);
        !           555:        }
        !           556:        if ((mt = malloc(sizeof (struct mtab))) == NULL) {
        !           557:                fprintf(stderr, "fstat: %s\n", strerror(errno));
        !           558:                exit(1);
        !           559:        }
        !           560:        mt->m = m;
        !           561:        bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
        !           562:        mt->next = mhead;
        !           563:        mhead = mt;
        !           564:        return (mt->mntonname);
        !           565: }
        !           566:
        !           567: void
        !           568: socktrans(sock, i)
        !           569:        struct socket *sock;
        !           570:        int i;
        !           571: {
        !           572:        static char *stypename[] = {
        !           573:                "unused",       /* 0 */
        !           574:                "stream",       /* 1 */
        !           575:                "dgram",        /* 2 */
        !           576:                "raw",          /* 3 */
        !           577:                "rdm",          /* 4 */
        !           578:                "seqpak"        /* 5 */
        !           579:        };
        !           580: #define        STYPEMAX 5
        !           581:        struct socket   so;
        !           582:        struct protosw  proto;
        !           583:        struct domain   dom;
        !           584:        struct inpcb    inpcb;
        !           585:        struct unpcb    unpcb;
        !           586:        int len;
        !           587:        char dname[32], *strcpy();
        !           588:
        !           589:        PREFIX(i);
        !           590:
        !           591:        /* fill in socket */
        !           592:        if (!KVM_READ(sock, &so, sizeof(struct socket))) {
        !           593:                dprintf(stderr, "can't read sock at %x\n", sock);
        !           594:                goto bad;
        !           595:        }
        !           596:
        !           597:        /* fill in protosw entry */
        !           598:        if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
        !           599:                dprintf(stderr, "can't read protosw at %x", so.so_proto);
        !           600:                goto bad;
        !           601:        }
        !           602:
        !           603:        /* fill in domain */
        !           604:        if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
        !           605:                dprintf(stderr, "can't read domain at %x\n", proto.pr_domain);
        !           606:                goto bad;
        !           607:        }
        !           608:
        !           609:        if ((len = kvm_read(kd, (u_long)dom.dom_name, dname,
        !           610:            sizeof(dname) - 1)) < 0) {
        !           611:                dprintf(stderr, "can't read domain name at %x\n",
        !           612:                        dom.dom_name);
        !           613:                dname[0] = '\0';
        !           614:        }
        !           615:        else
        !           616:                dname[len] = '\0';
        !           617:
        !           618:        if ((u_short)so.so_type > STYPEMAX)
        !           619:                printf("* %s ?%d", dname, so.so_type);
        !           620:        else
        !           621:                printf("* %s %s", dname, stypename[so.so_type]);
        !           622:
        !           623:        /*
        !           624:         * protocol specific formatting
        !           625:         *
        !           626:         * Try to find interesting things to print.  For tcp, the interesting
        !           627:         * thing is the address of the tcpcb, for udp and others, just the
        !           628:         * inpcb (socket pcb).  For unix domain, its the address of the socket
        !           629:         * pcb and the address of the connected pcb (if connected).  Otherwise
        !           630:         * just print the protocol number and address of the socket itself.
        !           631:         * The idea is not to duplicate netstat, but to make available enough
        !           632:         * information for further analysis.
        !           633:         */
        !           634:        switch(dom.dom_family) {
        !           635:        case AF_INET:
        !           636:                getinetproto(proto.pr_protocol);
        !           637:                if (proto.pr_protocol == IPPROTO_TCP ) {
        !           638:                        if (so.so_pcb) {
        !           639:                                if (kvm_read(kd, (u_long)so.so_pcb,
        !           640:                                    (char *)&inpcb, sizeof(struct inpcb))
        !           641:                                    != sizeof(struct inpcb)) {
        !           642:                                        dprintf(stderr,
        !           643:                                            "can't read inpcb at %x\n",
        !           644:                                            so.so_pcb);
        !           645:                                        goto bad;
        !           646:                                }
        !           647:                                printf(" %lx", (long)inpcb.inp_ppcb);
        !           648:                        }
        !           649:                }
        !           650:                else if (so.so_pcb)
        !           651:                        printf(" %lx", (long)so.so_pcb);
        !           652:                break;
        !           653:        case AF_UNIX:
        !           654:                /* print address of pcb and connected pcb */
        !           655:                if (so.so_pcb) {
        !           656:                        printf(" %lx", (long)so.so_pcb);
        !           657:                        if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb,
        !           658:                            sizeof(struct unpcb)) != sizeof(struct unpcb)){
        !           659:                                dprintf(stderr, "can't read unpcb at %x\n",
        !           660:                                    so.so_pcb);
        !           661:                                goto bad;
        !           662:                        }
        !           663:                        if (unpcb.unp_conn) {
        !           664:                                char shoconn[4], *cp;
        !           665:
        !           666:                                cp = shoconn;
        !           667:                                if (!(so.so_state & SS_CANTRCVMORE))
        !           668:                                        *cp++ = '<';
        !           669:                                *cp++ = '-';
        !           670:                                if (!(so.so_state & SS_CANTSENDMORE))
        !           671:                                        *cp++ = '>';
        !           672:                                *cp = '\0';
        !           673:                                printf(" %s %lx", shoconn,
        !           674:                                    (long)unpcb.unp_conn);
        !           675:                        }
        !           676:                }
        !           677:                break;
        !           678:        default:
        !           679:                /* print protocol number and socket address */
        !           680:                printf(" %d %lx", proto.pr_protocol, (long)sock);
        !           681:        }
        !           682:        printf("\n");
        !           683:        return;
        !           684: bad:
        !           685:        printf("* error\n");
        !           686: }
        !           687:
        !           688: /*
        !           689:  * getinetproto --
        !           690:  *     print name of protocol number
        !           691:  */
        !           692: void
        !           693: getinetproto(number)
        !           694:        int number;
        !           695: {
        !           696:        char *cp;
        !           697:
        !           698:        switch(number) {
        !           699:        case IPPROTO_IP:
        !           700:                cp = "ip"; break;
        !           701:        case IPPROTO_ICMP:
        !           702:                cp ="icmp"; break;
        !           703:        case IPPROTO_GGP:
        !           704:                cp ="ggp"; break;
        !           705:        case IPPROTO_TCP:
        !           706:                cp ="tcp"; break;
        !           707:        case IPPROTO_EGP:
        !           708:                cp ="egp"; break;
        !           709:        case IPPROTO_PUP:
        !           710:                cp ="pup"; break;
        !           711:        case IPPROTO_UDP:
        !           712:                cp ="udp"; break;
        !           713:        case IPPROTO_IDP:
        !           714:                cp ="idp"; break;
        !           715:        case IPPROTO_RAW:
        !           716:                cp ="raw"; break;
        !           717:        default:
        !           718:                printf(" %d", number);
        !           719:                return;
        !           720:        }
        !           721:        printf(" %s", cp);
        !           722: }
        !           723:
        !           724: getfname(filename)
        !           725:        char *filename;
        !           726: {
        !           727:        struct stat statbuf;
        !           728:        DEVS *cur;
        !           729:
        !           730:        if (stat(filename, &statbuf)) {
        !           731:                fprintf(stderr, "fstat: %s: %s\n", filename, strerror(errno));
        !           732:                return(0);
        !           733:        }
        !           734:        if ((cur = malloc(sizeof(DEVS))) == NULL) {
        !           735:                fprintf(stderr, "fstat: %s\n", strerror(errno));
        !           736:                exit(1);
        !           737:        }
        !           738:        cur->next = devs;
        !           739:        devs = cur;
        !           740:
        !           741:        cur->ino = statbuf.st_ino;
        !           742:        cur->fsid = statbuf.st_dev & 0xffff;
        !           743:        cur->name = filename;
        !           744:        return(1);
        !           745: }
        !           746:
        !           747: void
        !           748: usage()
        !           749: {
        !           750:        (void)fprintf(stderr,
        !           751:  "usage: fstat [-fnv] [-p pid] [-u user] [-N system] [-M core] [file ...]\n");
        !           752:        exit(1);
        !           753: }