386BSD 0.1 development
[unix-history] / usr / src / usr.bin / fstat / fstat.c
index bf14241..264851d 100644 (file)
@@ -1,52 +1,74 @@
-/*
- * Copyright (c) 1987 Regents of the University of California.
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
  * All rights reserved.
  *
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
 char copyright[] =
  */
 
 #ifndef lint
 char copyright[] =
-"@(#) Copyright (c) 1987 Regents of the University of California.\n\
+"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
-char sccsid[] = "@(#)fstat.c   5.22 (Berkeley) %G%";
+static char sccsid[] = "@(#)fstat.c    5.32 (Berkeley) 6/17/91";
 #endif /* not lint */
 
 /*
  *  fstat 
  */
 #endif /* not lint */
 
 /*
  *  fstat 
  */
-#include <machine/pte.h>
-
 #include <sys/param.h>
 #include <sys/param.h>
-#include <sys/user.h>
+#include <sys/time.h>
 #include <sys/proc.h>
 #include <sys/proc.h>
-#include <sys/text.h>
+#include <sys/user.h>
+#ifdef SPPWAIT
+#define NEWVM
+#endif
+#ifndef NEWVM
+#include <machine/pte.h>
+#include <sys/vmmac.h>
+#endif
 #include <sys/stat.h>
 #include <sys/stat.h>
-#include <sys/time.h>
 #include <sys/vnode.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/domain.h>
 #include <sys/protosw.h>
 #include <sys/unpcb.h>
 #include <sys/vnode.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/domain.h>
 #include <sys/protosw.h>
 #include <sys/unpcb.h>
-#include <sys/vmmac.h>
+#include <sys/kinfo.h>
+#include <sys/filedesc.h>
 #define        KERNEL
 #define NFS
 #include <sys/file.h>
 #include <sys/mount.h>
 #define        KERNEL
 #define NFS
 #include <sys/file.h>
 #include <sys/mount.h>
+#include <ufs/quota.h>
 #include <ufs/inode.h>
 #include <nfs/nfsv2.h>
 #include <nfs/nfs.h>
 #include <ufs/inode.h>
 #include <nfs/nfsv2.h>
 #include <nfs/nfs.h>
@@ -59,13 +81,15 @@ char sccsid[] = "@(#)fstat.c        5.22 (Berkeley) %G%";
 #include <netinet/ip.h>
 #include <netinet/in_pcb.h>
 
 #include <netinet/ip.h>
 #include <netinet/in_pcb.h>
 
-#include <kvm.h>
-#include <paths.h>
-#include <ctype.h>
+#include <errno.h>
 #include <nlist.h>
 #include <nlist.h>
+#include <kvm.h>
 #include <pwd.h>
 #include <pwd.h>
-#include <strings.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <paths.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
 
 #define        TEXT    -1
 #define        CDIR    -2
 
 #define        TEXT    -1
 #define        CDIR    -2
@@ -74,7 +98,7 @@ char sccsid[] = "@(#)fstat.c  5.22 (Berkeley) %G%";
 
 typedef struct devs {
        struct  devs *next;
 
 typedef struct devs {
        struct  devs *next;
-       dev_t   dev;
+       long    fsid;
        ino_t   ino;
        char    *name;
 } DEVS;
        ino_t   ino;
        char    *name;
 } DEVS;
@@ -83,13 +107,16 @@ DEVS *devs;
 struct  filestat {
        long    fsid;
        long    fileid;
 struct  filestat {
        long    fsid;
        long    fileid;
+       mode_t  mode;
        u_long  size;
        dev_t   rdev;
 };
 
        u_long  size;
        dev_t   rdev;
 };
 
+#ifdef notdef
 struct nlist nl[] = {
        { "" },
 };
 struct nlist nl[] = {
        { "" },
 };
+#endif
 
 int    fsflg,  /* show files on same filesystem as file(s) argument */
        pflg,   /* show files open by a particular pid */
 
 int    fsflg,  /* show files on same filesystem as file(s) argument */
        pflg,   /* show files open by a particular pid */
@@ -100,30 +127,54 @@ int       vflg;   /* display errors in locating kernel data objects etc... */
 
 #define dprintf        if (vflg) fprintf
 
 
 #define dprintf        if (vflg) fprintf
 
-extern int errno;
-off_t lseek();
+struct file **ofiles;  /* buffer of pointers to file structures */
+int maxfiles;
+#define ALLOC_OFILES(d)        \
+       if ((d) > maxfiles) { \
+               free(ofiles); \
+               ofiles = malloc((d) * sizeof(struct file *)); \
+               if (ofiles == NULL) { \
+                       fprintf(stderr, "fstat: %s\n", strerror(errno)); \
+                       exit(1); \
+               } \
+               maxfiles = (d); \
+       }
+
+/*
+ * a kvm_read that returns true if everything is read 
+ */
+#define KVM_READ(kaddr, paddr, len) (kvm_read((kaddr), (paddr), (len)) == (len))
+
+void dofiles(), getinetproto(), socktrans(), nfs_filestat(), ufs_filestat();
+void usage(), vtrans();
 
 main(argc, argv)
        int argc;
        char **argv;
 {
 
 main(argc, argv)
        int argc;
        char **argv;
 {
-       register struct passwd *passwd;
-       int what = KINFO_PROC_ALL, arg = 0;
-       struct passwd *getpwnam(), *getpwuid();
-       struct proc *p;
        extern char *optarg;
        extern int optind;
        extern char *optarg;
        extern int optind;
-       int ch, size;
-       char *malloc();
-
+       register struct passwd *passwd;
+       struct proc *p;
+       int arg, ch, what;
+       char *namelist = NULL, *memfile = NULL;
 
 
-       while ((ch = getopt(argc, argv, "p:u:fnv")) != EOF)
+       arg = 0;
+       what = KINFO_PROC_ALL;
+       while ((ch = getopt(argc, argv, "fnp:u:vNM")) != EOF)
                switch((char)ch) {
                switch((char)ch) {
+               case 'f':
+                       fsflg = 1;
+                       break;
+               case 'n':
+                       nflg = 1;
+                       break;
                case 'p':
                        if (pflg++)
                                usage();
                        if (!isdigit(*optarg)) {
                case 'p':
                        if (pflg++)
                                usage();
                        if (!isdigit(*optarg)) {
-                               fputs("fstat: -p option requires a process id.\n", stderr);
+                               fprintf(stderr,
+                                   "fstat: -p requires a process id\n");
                                usage();
                        }
                        what = KINFO_PROC_PID;
                                usage();
                        }
                        what = KINFO_PROC_PID;
@@ -133,21 +184,21 @@ main(argc, argv)
                        if (uflg++)
                                usage();
                        if (!(passwd = getpwnam(optarg))) {
                        if (uflg++)
                                usage();
                        if (!(passwd = getpwnam(optarg))) {
-                               (void)fprintf(stderr, "%s: unknown uid\n",
+                               fprintf(stderr, "%s: unknown uid\n",
                                    optarg);
                                exit(1);
                        }
                        what = KINFO_PROC_UID;
                        arg = passwd->pw_uid;
                        break;
                                    optarg);
                                exit(1);
                        }
                        what = KINFO_PROC_UID;
                        arg = passwd->pw_uid;
                        break;
-               case 'f':
-                       fsflg++;
+               case 'v':
+                       vflg = 1;
                        break;
                        break;
-               case 'n':
-                       nflg++;
+               case 'N':
+                       namelist = optarg;
                        break;
                        break;
-               case 'v':
-                       vflg++;
+               case 'M':
+                       memfile = optarg;
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
@@ -162,6 +213,9 @@ main(argc, argv)
                if (!checkfile) /* file(s) specified, but none accessable */
                        exit(1);
        }
                if (!checkfile) /* file(s) specified, but none accessable */
                        exit(1);
        }
+
+       ALLOC_OFILES(256);      /* reserve space for file pointers */
+
        if (fsflg && !checkfile) {      
                /* -f with no files means use wd */
                if (getfname(".") == 0)
        if (fsflg && !checkfile) {      
                /* -f with no files means use wd */
                if (getfname(".") == 0)
@@ -169,24 +223,28 @@ main(argc, argv)
                checkfile = 1;
        }
 
                checkfile = 1;
        }
 
-       if (kvm_openfiles(NULL, NULL, NULL) == -1) {
+       if (kvm_openfiles(namelist, memfile, NULL) == -1) {
                fprintf(stderr, "fstat: %s\n", kvm_geterr());
                exit(1);
        }
                fprintf(stderr, "fstat: %s\n", kvm_geterr());
                exit(1);
        }
+#ifdef notdef
        if (kvm_nlist(nl) != 0) {
        if (kvm_nlist(nl) != 0) {
-               (void)fprintf(stderr, "%s: no namelist: %s\n", kvm_geterr());
+               fprintf(stderr, "fstat: no namelist: %s\n", kvm_geterr());
                exit(1);
        }
                exit(1);
        }
+#endif
        if (kvm_getprocs(what, arg) == -1) {
                fprintf(stderr, "fstat: %s\n", kvm_geterr());
                exit(1);
        }
        if (nflg)
        if (kvm_getprocs(what, arg) == -1) {
                fprintf(stderr, "fstat: %s\n", kvm_geterr());
                exit(1);
        }
        if (nflg)
-fputs("USER     CMD        PID   FD FST  DEV    INUM TYPE SZ|DV", stdout);
+               printf("%s",
+"USER     CMD          PID   FD  DEV    INUM       MODE SZ|DV");
        else
        else
-fputs("USER     CMD        PID   FD FST MNT        INUM TYPE SZ|DV", stdout);
+               printf("%s",
+"USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV");
        if (checkfile && fsflg == 0)
        if (checkfile && fsflg == 0)
-               fputs(" NAME\n", stdout);       
+               printf(" NAME\n");
        else
                putchar('\n');
 
        else
                putchar('\n');
 
@@ -201,19 +259,19 @@ fputs("USER     CMD        PID   FD FST MNT        INUM TYPE SZ|DV", stdout);
 char   *Uname, *Comm;
 int    Pid;
 
 char   *Uname, *Comm;
 int    Pid;
 
-#define PREFIX(i) printf("%-8.8s %-8.8s %5d", Uname, Comm, Pid); \
+#define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \
        switch(i) { \
        case TEXT: \
        switch(i) { \
        case TEXT: \
-               fputs(" text", stdout); \
+               printf(" text"); \
                break; \
        case CDIR: \
                break; \
        case CDIR: \
-               fputs("   wd", stdout); \
+               printf("   wd"); \
                break; \
        case RDIR: \
                break; \
        case RDIR: \
-               fputs(" root", stdout); \
+               printf(" root"); \
                break; \
        case TRACE: \
                break; \
        case TRACE: \
-               fputs("   tr", stdout); \
+               printf("   tr"); \
                break; \
        default: \
                printf(" %4d", i); \
                break; \
        default: \
                printf(" %4d", i); \
@@ -223,40 +281,67 @@ int       Pid;
 /*
  * print open files attributed to this process
  */
 /*
  * print open files attributed to this process
  */
+void
 dofiles(p)
        struct proc *p;
 {
 dofiles(p)
        struct proc *p;
 {
-       int i;
-       char *user_from_uid();
+       int i, last;
        struct file file;
        struct file file;
-       struct user *up = kvm_getu(p);
+#ifdef NEWVM
+       struct filedesc0 filed0;
+#define        filed   filed0.fd_fd
+       struct eproc *ep;
+#else
+       struct filedesc filed;
+#endif
+
+       extern char *user_from_uid();
+#ifndef NEWVM
        struct vnode *xvptr;
        struct vnode *xvptr;
+#endif
 
 
+#ifdef NEWVM
+       ep = kvm_geteproc(p);
+       Uname = user_from_uid(ep->e_ucred.cr_uid, 0);
+#else
        Uname = user_from_uid(p->p_uid, 0);
        Uname = user_from_uid(p->p_uid, 0);
+#endif
        Pid = p->p_pid;
        Comm = p->p_comm;
 
        Pid = p->p_pid;
        Comm = p->p_comm;
 
-       if (up == NULL) {
-               dprintf(stderr, "can't read u for pid %d\n", Pid);
+       if (p->p_fd == NULL)
+               return;
+#ifdef NEWVM
+       if (!KVM_READ(p->p_fd, &filed0, sizeof (filed0))) {
+               dprintf(stderr, "can't read filedesc at %x for pid %d\n",
+                       p->p_fd, Pid);
+               return;
+       }
+#else
+       if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) {
+               dprintf(stderr, "can't read filedesc at %x for pid %d\n",
+                       p->p_fd, Pid);
                return;
        }
                return;
        }
+#endif
        /*
         * root directory vnode, if one
         */
        /*
         * root directory vnode, if one
         */
-       if (up->u_rdir)
-               vtrans(up->u_rdir, RDIR);
+       if (filed.fd_rdir)
+               vtrans(filed.fd_rdir, RDIR);
+#ifndef NEWVM
        /*
         * text vnode
         */
        if (p->p_textp && 
        /*
         * text vnode
         */
        if (p->p_textp && 
-           kvm_read((int)p->p_textp+(int)&((struct text *)0)->x_vptr, &xvptr,
-           sizeof (struct vnode *)) == sizeof (struct vnode *) &&
+           KVM_READ(&(p->p_textp->x_vptr), &xvptr, sizeof (struct vnode *)) &&
            xvptr != NULL)
                vtrans(xvptr, TEXT);
            xvptr != NULL)
                vtrans(xvptr, TEXT);
+#endif
        /*
         * current working directory vnode
         */
        /*
         * current working directory vnode
         */
-       vtrans(up->u_cdir, CDIR);
+       vtrans(filed.fd_cdir, CDIR);
        /*
         * ktrace vnode, if one
         */
        /*
         * ktrace vnode, if one
         */
@@ -265,13 +350,35 @@ dofiles(p)
        /*
         * open files
         */
        /*
         * open files
         */
-       for (i = 0; i <= up->u_lastfile; i++) {
-               if (up->u_ofile[i] == 0)
+#define FPSIZE (sizeof (struct file *))
+       ALLOC_OFILES(filed.fd_lastfile);
+#ifdef NEWVM
+       if (filed.fd_nfiles > NDFILE) {
+               if (!KVM_READ(filed.fd_ofiles, ofiles,
+                   filed.fd_lastfile * FPSIZE)) {
+                       dprintf(stderr,
+                           "can't read file structures at %x for pid %d\n",
+                           filed.fd_ofiles, Pid);
+                       return;
+               }
+       } else
+               bcopy(filed0.fd_dfiles, ofiles, filed.fd_lastfile * FPSIZE);
+#else
+       bcopy(filed.fd_ofile, ofiles, MIN(filed.fd_lastfile, NDFILE) * FPSIZE);
+       last = filed.fd_lastfile;
+       if ((last > NDFILE) && !KVM_READ(filed.fd_moreofiles, &ofiles[NDFILE],
+           (last - NDFILE) * FPSIZE)) {
+               dprintf(stderr, "can't read rest of files at %x for pid %d\n",
+                       filed.fd_moreofiles, Pid);
+               return;
+       }
+#endif
+       for (i = 0; i <= filed.fd_lastfile; i++) {
+               if (ofiles[i] == NULL)
                        continue;
                        continue;
-               if (kvm_read(up->u_ofile[i], &file, sizeof (struct file)) !=
-                   sizeof (struct file)) {
-                       dprintf(stderr, "can't read file %d for pid %d\n",
-                               i, Pid);
+               if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) {
+                       dprintf(stderr, "can't read file %d at %x for pid %d\n",
+                               i, ofiles[i], Pid);
                        continue;
                }
                if (file.f_type == DTYPE_VNODE)
                        continue;
                }
                if (file.f_type == DTYPE_VNODE)
@@ -286,54 +393,52 @@ dofiles(p)
        }
 }
 
        }
 }
 
+void
 vtrans(vp, i)
        struct vnode *vp;
 vtrans(vp, i)
        struct vnode *vp;
+       int i;
 {
 {
+       extern char *devname();
        struct vnode vn;
        struct filestat fst;
        struct vnode vn;
        struct filestat fst;
-       char *filename = NULL;
-       char *fstype;
-       char *getmnton(), *vtype();
-       int nodata = 0;
+       char mode[15];
+       char *badtype, *filename, *getmnton();
 
 
-       if (kvm_read((off_t)vp, &vn, sizeof (struct vnode)) != 
-           sizeof (struct vnode)) {
+       filename = badtype = NULL;
+       if (!KVM_READ(vp, &vn, sizeof (struct vnode))) {
                dprintf(stderr, "can't read vnode at %x for pid %d\n",
                        vp, Pid);
                return;
        }
                dprintf(stderr, "can't read vnode at %x for pid %d\n",
                        vp, Pid);
                return;
        }
-       switch (vn.v_tag) {
-       case VT_NON:
-               fstype = " non";
-               nodata = 1;
-               break;
-       case VT_UFS:
-               fstype = " ufs";
-               ufs_filestat(&vn, &fst);
-               break;
-       case VT_MFS:
-               fstype = " mfs";
-               ufs_filestat(&vn, &fst);
-               break;
-       case VT_NFS:
-               fstype = " nfs";
-               nfs_filestat(&vn, &fst);
-               break;
-       default: {
-               static char unknown[10];
-               sprintf(fstype = unknown, " ?%d", vn.v_tag);
-               nodata = 1;
-               break;;
-       }
+       if (vn.v_type == VNON || vn.v_tag == VT_NON)
+               badtype = "none";
+       else if (vn.v_type == VBAD)
+               badtype = "bad";
+       else
+               switch (vn.v_tag) {
+               case VT_UFS:
+                       ufs_filestat(&vn, &fst);
+                       break;
+               case VT_MFS:
+                       ufs_filestat(&vn, &fst);
+                       break;
+               case VT_NFS:
+                       nfs_filestat(&vn, &fst);
+                       break;
+               default: {
+                       static char unknown[10];
+                       sprintf(badtype = unknown, "?(%x)", vn.v_tag);
+                       break;;
+               }
        }
        if (checkfile) {
                int fsmatch = 0;
                register DEVS *d;
 
        }
        if (checkfile) {
                int fsmatch = 0;
                register DEVS *d;
 
-               if (nodata)
+               if (badtype)
                        return;
                for (d = devs; d != NULL; d = d->next)
                        return;
                for (d = devs; d != NULL; d = d->next)
-                       if (d->dev == fst.fsid) {
+                       if (d->fsid == fst.fsid) {
                                fsmatch = 1;
                                if (d->ino == fst.fileid) {
                                        filename = d->name;
                                fsmatch = 1;
                                if (d->ino == fst.fileid) {
                                        filename = d->name;
@@ -344,29 +449,31 @@ vtrans(vp, i)
                        return;
        }
        PREFIX(i);
                        return;
        }
        PREFIX(i);
-       fputs(fstype, stdout);
-       if (nodata) {
-               printf(" -       -    -    -\n");
+       if (badtype) {
+               (void)printf(" -         -  %10s    -\n", badtype);
                return;
        }
        if (nflg)
                return;
        }
        if (nflg)
-               printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid));
+               (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid));
        else
        else
-               printf(" %-8s", getmnton(vn.v_mount));
-       printf(" %6d %3s", fst.fileid, vtype(vn.v_type));
+               (void)printf(" %-8s", getmnton(vn.v_mount));
+       if (nflg)
+               (void)sprintf(mode, "%o", fst.mode);
+       else
+               strmode(fst.mode, mode);
+       (void)printf(" %6d %10s", fst.fileid, mode);
        switch (vn.v_type) {
        case VBLK:
        switch (vn.v_type) {
        case VBLK:
-               if (nflg)
+       case VCHR: {
+               char *name;
+
+               if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ? 
+                   S_IFCHR : S_IFBLK)) == NULL))
                        printf("  %2d,%-2d", major(fst.rdev), minor(fst.rdev));
                else
                        printf("  %2d,%-2d", major(fst.rdev), minor(fst.rdev));
                else
-                       printf(" %-6s", devname(fst.rdev, 0));
-               break;
-       case VCHR:
-               if (nflg)
-                       printf("  %2d/%-2d", major(fst.rdev), minor(fst.rdev));
-               else
-                       printf(" %-6s", devname(fst.rdev, 1));
+                       printf(" %6s", name);
                break;
                break;
+       }
        default:
                printf(" %6d", fst.size);
        }
        default:
                printf(" %6d", fst.size);
        }
@@ -376,28 +483,57 @@ vtrans(vp, i)
        putchar('\n');
 }
 
        putchar('\n');
 }
 
+void
 ufs_filestat(vp, fsp)
        struct vnode *vp;
        struct filestat *fsp;
 {
        struct inode *ip = VTOI(vp);
 
 ufs_filestat(vp, fsp)
        struct vnode *vp;
        struct filestat *fsp;
 {
        struct inode *ip = VTOI(vp);
 
-       fsp->fsid = (long)ip->i_dev;
+       fsp->fsid = ip->i_dev & 0xffff;
        fsp->fileid = (long)ip->i_number;
        fsp->fileid = (long)ip->i_number;
+       fsp->mode = (mode_t)ip->i_mode;
        fsp->size = (u_long)ip->i_size;
        fsp->rdev = ip->i_rdev;
 }
 
        fsp->size = (u_long)ip->i_size;
        fsp->rdev = ip->i_rdev;
 }
 
+void
 nfs_filestat(vp, fsp)
        struct vnode *vp;
        struct filestat *fsp;
 {
 nfs_filestat(vp, fsp)
        struct vnode *vp;
        struct filestat *fsp;
 {
-       struct nfsnode *np = VTONFS(vp);
+       register struct nfsnode *np = VTONFS(vp);
+       register mode_t mode;
 
        fsp->fsid = np->n_vattr.va_fsid;
        fsp->fileid = np->n_vattr.va_fileid;
 
        fsp->fsid = np->n_vattr.va_fsid;
        fsp->fileid = np->n_vattr.va_fileid;
-       fsp->size = np->n_vattr.va_size;
+       fsp->size = np->n_size;
        fsp->rdev = np->n_vattr.va_rdev;
        fsp->rdev = np->n_vattr.va_rdev;
+       mode = (mode_t)np->n_vattr.va_mode;
+       switch (vp->v_type) {
+       case VREG:
+               mode |= S_IFREG;
+               break;
+       case VDIR:
+               mode |= S_IFDIR;
+               break;
+       case VBLK:
+               mode |= S_IFBLK;
+               break;
+       case VCHR:
+               mode |= S_IFCHR;
+               break;
+       case VLNK:
+               mode |= S_IFLNK;
+               break;
+       case VSOCK:
+               mode |= S_IFSOCK;
+               break;
+       case VFIFO:
+               mode |= S_IFIFO;
+               break;
+       };
+       fsp->mode = mode;
 }
 
 
 }
 
 
@@ -416,57 +552,25 @@ getmnton(m)
        for (mt = mhead; mt != NULL; mt = mt->next)
                if (m == mt->m)
                        return (mt->mntonname);
        for (mt = mhead; mt != NULL; mt = mt->next)
                if (m == mt->m)
                        return (mt->mntonname);
-       if (kvm_read((off_t)m, &mount, sizeof(struct mount)) != 
-           sizeof(struct mount)) {
+       if (!KVM_READ(m, &mount, sizeof(struct mount))) {
                fprintf(stderr, "can't read mount table at %x\n", m);
                return (NULL);
        }
                fprintf(stderr, "can't read mount table at %x\n", m);
                return (NULL);
        }
-       if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) {
-               fprintf(stderr, "out of memory\n");
+       if ((mt = malloc(sizeof (struct mtab))) == NULL) {
+               fprintf(stderr, "fstat: %s\n", strerror(errno));
                exit(1);
        }
        mt->m = m;
                exit(1);
        }
        mt->m = m;
-       bcopy(&mount.m_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
+       bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
        mt->next = mhead;
        mhead = mt;
        return (mt->mntonname);
 }
 
        mt->next = mhead;
        mhead = mt;
        return (mt->mntonname);
 }
 
-char *
-vtype(type)
-       enum vtype type;
-{
-
-       switch(type) {
-       case VNON:
-               return("non");
-       case VREG:
-               return("reg");
-       case VDIR:
-               return("dir");
-       case VBLK:
-               return("blk");
-       case VCHR:
-               return("chr");
-       case VLNK:
-               return("lnk");
-       case VSOCK:
-               return("soc");
-       case VFIFO:
-               return("fif");
-       case VBAD:
-               return("bad");
-       default: {
-               static char unknown[10];
-               sprintf(unknown, "?%d", type);
-               return(unknown);
-       }
-       }
-       /*NOTREACHED*/
-}
-
+void
 socktrans(sock, i)
        struct socket *sock;
 socktrans(sock, i)
        struct socket *sock;
+       int i;
 {
        static char *stypename[] = {
                "unused",       /* 0 */
 {
        static char *stypename[] = {
                "unused",       /* 0 */
@@ -488,46 +592,36 @@ socktrans(sock, i)
        PREFIX(i);
 
        /* fill in socket */
        PREFIX(i);
 
        /* fill in socket */
-       if (kvm_read((off_t)sock, (char *)&so, sizeof(struct socket))
-           != sizeof(struct socket)) {
+       if (!KVM_READ(sock, &so, sizeof(struct socket))) {
                dprintf(stderr, "can't read sock at %x\n", sock);
                dprintf(stderr, "can't read sock at %x\n", sock);
-               return;
+               goto bad;
        }
 
        /* fill in protosw entry */
        }
 
        /* fill in protosw entry */
-       if (kvm_read((off_t)so.so_proto, (char *)&proto, sizeof(struct protosw))
-           != sizeof(struct protosw)) {
+       if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
                dprintf(stderr, "can't read protosw at %x", so.so_proto);
                dprintf(stderr, "can't read protosw at %x", so.so_proto);
-               return;
+               goto bad;
        }
 
        /* fill in domain */
        }
 
        /* fill in domain */
-       if (kvm_read((off_t)proto.pr_domain, (char *)&dom, sizeof(struct domain))
-           != sizeof(struct domain)) {
+       if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
                dprintf(stderr, "can't read domain at %x\n", proto.pr_domain);
                dprintf(stderr, "can't read domain at %x\n", proto.pr_domain);
-               return;
+               goto bad;
        }
 
        }
 
-       /*
-        * grab domain name
-        * kludge "internet" --> "inet" for brevity
-        */
-       if (dom.dom_family == AF_INET)
-               (void)strcpy(dname, "inet");
-       else {
-               if ((len = kvm_read((off_t)dom.dom_name, dname, sizeof(dname) - 1)) < 0) {
-                       dprintf(stderr, "can't read domain name at %x\n",
-                               dom.dom_name);
-                       dname[0] = '\0';
-               }
-               else
-                       dname[len] = '\0';
+       if ((len =
+           kvm_read(dom.dom_name, dname, sizeof(dname) - 1)) < 0) {
+               dprintf(stderr, "can't read domain name at %x\n",
+                       dom.dom_name);
+               dname[0] = '\0';
        }
        }
+       else
+               dname[len] = '\0';
 
        if ((u_short)so.so_type > STYPEMAX)
 
        if ((u_short)so.so_type > STYPEMAX)
-               (void)printf("* %s ?%d", dname, so.so_type);
+               printf("* %s ?%d", dname, so.so_type);
        else
        else
-               (void)printf("* %s %s", dname, stypename[so.so_type]);
+               printf("* %s %s", dname, stypename[so.so_type]);
 
        /* 
         * protocol specific formatting
 
        /* 
         * protocol specific formatting
@@ -545,27 +639,29 @@ socktrans(sock, i)
                getinetproto(proto.pr_protocol);
                if (proto.pr_protocol == IPPROTO_TCP ) {
                        if (so.so_pcb) {
                getinetproto(proto.pr_protocol);
                if (proto.pr_protocol == IPPROTO_TCP ) {
                        if (so.so_pcb) {
-                               if (kvm_read((off_t)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb))
-                                   != sizeof(struct inpcb)){
+                               if (kvm_read(so.so_pcb, &inpcb,
+                                   sizeof(struct inpcb))
+                                   != sizeof(struct inpcb)) {
                                        dprintf(stderr, 
                                        dprintf(stderr, 
-                                            "can't read inpcb at %x\n", so.so_pcb);
-                                       return;
+                                           "can't read inpcb at %x\n",
+                                           so.so_pcb);
+                                       goto bad;
                                }
                                }
-                               (void)printf(" %x", (int)inpcb.inp_ppcb);
+                               printf(" %x", (int)inpcb.inp_ppcb);
                        }
                }
                else if (so.so_pcb)
                        }
                }
                else if (so.so_pcb)
-                       (void)printf(" %x", (int)so.so_pcb);
+                       printf(" %x", (int)so.so_pcb);
                break;
        case AF_UNIX:
                /* print address of pcb and connected pcb */
                if (so.so_pcb) {
                break;
        case AF_UNIX:
                /* print address of pcb and connected pcb */
                if (so.so_pcb) {
-                       (void)printf(" %x", (int)so.so_pcb);
-                       if (kvm_read((off_t)so.so_pcb, (char *)&unpcb, sizeof(struct unpcb))
-                           != sizeof(struct unpcb)){
+                       printf(" %x", (int)so.so_pcb);
+                       if (kvm_read(so.so_pcb, &unpcb,
+                           sizeof(struct unpcb)) != sizeof(struct unpcb)){
                                dprintf(stderr, "can't read unpcb at %x\n",
                                dprintf(stderr, "can't read unpcb at %x\n",
-                                       so.so_pcb);
-                               return;
+                                   so.so_pcb);
+                               goto bad;
                        }
                        if (unpcb.unp_conn) {
                                char shoconn[4], *cp;
                        }
                        if (unpcb.unp_conn) {
                                char shoconn[4], *cp;
@@ -577,22 +673,26 @@ socktrans(sock, i)
                                if (!(so.so_state & SS_CANTSENDMORE))
                                        *cp++ = '>';
                                *cp = '\0';
                                if (!(so.so_state & SS_CANTSENDMORE))
                                        *cp++ = '>';
                                *cp = '\0';
-                               (void)printf(" %s %x", shoconn,
+                               printf(" %s %x", shoconn,
                                    (int)unpcb.unp_conn);
                        }
                }
                break;
        default:
                /* print protocol number and socket address */
                                    (int)unpcb.unp_conn);
                        }
                }
                break;
        default:
                /* print protocol number and socket address */
-               (void)printf(" %d %x", proto.pr_protocol, (int)sock);
+               printf(" %d %x", proto.pr_protocol, (int)sock);
        }
        }
-       (void)printf("\n");
+       printf("\n");
+       return;
+bad:
+       printf("* error\n");
 }
 
 /*
  * getinetproto --
  *     print name of protocol number
  */
 }
 
 /*
  * getinetproto --
  *     print name of protocol number
  */
+void
 getinetproto(number)
        int number;
 {
 getinetproto(number)
        int number;
 {
@@ -618,10 +718,10 @@ getinetproto(number)
        case IPPROTO_RAW:
                cp ="raw"; break;
        default:
        case IPPROTO_RAW:
                cp ="raw"; break;
        default:
-               (void)printf(" %d", number);
+               printf(" %d", number);
                return;
        }
                return;
        }
-       (void)printf(" %s", cp);
+       printf(" %s", cp);
 }
 
 getfname(filename)
 }
 
 getfname(filename)
@@ -629,29 +729,29 @@ getfname(filename)
 {
        struct stat statbuf;
        DEVS *cur;
 {
        struct stat statbuf;
        DEVS *cur;
-       char *malloc();
 
        if (stat(filename, &statbuf)) {
 
        if (stat(filename, &statbuf)) {
-               (void)fprintf(stderr, "fstat: %s: %s\n", strerror(errno),
+               fprintf(stderr, "fstat: %s: %s\n", strerror(errno),
                    filename);
                return(0);
        }
                    filename);
                return(0);
        }
-       if ((cur = (DEVS *)malloc(sizeof(DEVS))) == NULL) {
-               (void)fprintf(stderr, "fstat: out of space.\n");
+       if ((cur = malloc(sizeof(DEVS))) == NULL) {
+               fprintf(stderr, "fstat: %s\n", strerror(errno));
                exit(1);
        }
        cur->next = devs;
        devs = cur;
 
        cur->ino = statbuf.st_ino;
                exit(1);
        }
        cur->next = devs;
        devs = cur;
 
        cur->ino = statbuf.st_ino;
-       cur->dev = statbuf.st_dev;
+       cur->fsid = statbuf.st_dev & 0xffff;
        cur->name = filename;
        return(1);
 }
 
        cur->name = filename;
        return(1);
 }
 
+void
 usage()
 {
        (void)fprintf(stderr,
 usage()
 {
        (void)fprintf(stderr,
          "usage: fstat [-u user] [-p pid] [filename ...]\n");
"usage: fstat [-fnv] [-p pid] [-u user] [-N system] [-M core] [file ...]\n");
        exit(1);
 }
        exit(1);
 }