add pathnames.h, make errors more consistent
[unix-history] / usr / src / usr.bin / fstat / fstat.c
index 53291c4..decfab2 100644 (file)
 /*
  * Copyright (c) 1987 Regents of the University of California.
 /*
  * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * 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.
  */
 
 #ifndef lint
 char copyright[] =
 "@(#) Copyright (c) 1987 Regents of the University of California.\n\
  All rights reserved.\n";
  */
 
 #ifndef lint
 char copyright[] =
 "@(#) Copyright (c) 1987 Regents of the University of California.\n\
  All rights reserved.\n";
-#endif not lint
+#endif /* not lint */
 
 #ifndef lint
 
 #ifndef lint
-static char sccsid[] = "@(#)fstat.c    5.4 (Berkeley) %G%";
-#endif not lint
+static char sccsid[] = "@(#)fstat.c    5.16 (Berkeley) %G%";
+#endif /* not lint */
 
 /*
  *  fstat 
  */
 
 /*
  *  fstat 
  */
-#include <stdio.h>
-#include <ctype.h>
-#include <nlist.h>
-#include <pwd.h>
+#include <machine/pte.h>
+
 #include <sys/param.h>
 #include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
 #include <sys/dir.h>
 #include <sys/user.h>
 #include <sys/proc.h>
 #include <sys/dir.h>
 #include <sys/user.h>
 #include <sys/proc.h>
-#include <machine/pte.h> 
-#include <sys/vm.h>
 #include <sys/text.h>
 #include <sys/stat.h>
 #include <sys/text.h>
 #include <sys/stat.h>
-#include <math.h>
-#include <sys/vlimit.h>
 #include <sys/inode.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/domain.h>
 #include <sys/protosw.h>
 #include <sys/inode.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>
+#define        KERNEL
+#include <sys/file.h>
+#undef KERNEL
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
-#include <sys/unpcb.h>
-#define KERNEL
-#include <sys/file.h>
-#undef KERNEL
+#include <stdio.h>
+#include <ctype.h>
+#include <nlist.h>
+#include <pwd.h>
+#include "pathnames.h"
 
 
-#ifdef ULTRIX  
-               /* UFS -> GFS */
+#ifdef ULTRIX
+               /* UFS -> GFS */
 #    define    inode   gnode
 #    define    x_iptr  x_gptr
 #    define    i_dev   g_dev
 #    define    i_number g_number
 #    define    i_mode  g_mode
 #    define    i_size  g_size
 #    define    inode   gnode
 #    define    x_iptr  x_gptr
 #    define    i_dev   g_dev
 #    define    i_number g_number
 #    define    i_mode  g_mode
 #    define    i_size  g_size
-#endif ULTRIX
+#endif
 
 
-char *emalloc();
-char *getinetproto();
+#define        TEXT    -2
+#define        WD      -1
 
 
-#define vprintf        if (vflg) printf
-#define WD     -1
-#define TEXT   -2
-
-int    pcbpf, nswap, kmem, mem, swap, uid, pid;
-int    uflg, fflg, vflg, nproc, pflg;
-int sflg, kflg; /*4.2*/
-int argaddr; /*4.2*/
-
-struct devs {
+typedef struct devs {
        struct devs *next;
        dev_t dev;
        int inum;
        struct devs *next;
        dev_t dev;
        int inum;
-} devs;
-
-#define clear(x)       ((int)x & 0x7fffffff)
+       char *name;
+} DEVS;
+DEVS *devs;
 
 
-struct pte *Sysmap = 0;
-
-struct nlist nl[] = {
+static struct nlist nl[] = {
        { "_proc" },
 #define        X_PROC          0
        { "_Usrptmap" },
 #define        X_USRPTMA       1
        { "_proc" },
 #define        X_PROC          0
        { "_Usrptmap" },
 #define        X_USRPTMA       1
-       { "_usrpt" },
-#define        X_USRPT         2
-       { "_nswap" },
-#define        X_NSWAP         3
        { "_nproc" },
        { "_nproc" },
-#define        X_NPROC         4
-       { "_Sysmap" },
-#define SSYSMAP                5
-       { "_Syssize" },
-#define SSYSSIZE       6
+#define        X_NPROC         2
+       { "_usrpt" },
+#define        X_USRPT         3
        { "" },
 };
 
        { "" },
 };
 
-char   *stypename[] = {
-       "unused",       /* 0 */
-       "stream",       /* 1 */
-       "dgram",        /* 2 */
-       "raw",          /* 3 */
-       "rdm",          /* 4 */
-       "seqpak"        /* 5 */
-};
-#define STYPEMAX 5
-
-char   *uname;
-
+struct proc *mproc;
+struct pte *Usrptma, *usrpt;
 
 
-struct proc proc[8], *mproc;           /* 8 = a few, for less syscalls */
-struct pte *Usrptma, *usrpt;
-
-int    paduser1;               /* avoid hardware mem clobbering botch */
 union {
 union {
-       struct  user user;
-       char    upages[UPAGES][NBPG];
+       struct user user;
+       char upages[UPAGES][NBPG];
 } user;
 } user;
-int    paduser2;               /* avoid hardware mem clobbering botch */
-#define u      user.user
 
 
-char   *kmemf, *memf, *swapf, *nlistf;
+extern int errno;
+static int fflg, vflg;
+static int kmem, mem, nproc, swap;
+static char *uname;
 
 
-extern int     errno;
-char   stdoutBuf[BUFSIZ];
+off_t lseek();
 
 main(argc, argv)
 
 main(argc, argv)
-char **argv;
+       int argc;
+       char **argv;
 {
 {
-       register int i, j;
-       off_t procp;
-       dev_t   dev;
-
-       argv++;
-       while (*argv) {
-               if (strcmp(*argv, "-v") == 0) {
-                       vflg++;
-                       argv++;
-                       continue;
-               } 
-               if (strcmp(*argv, "-u") == 0) {
-                       if (uflg++)
+       extern char *optarg;
+       extern int optind;
+       register struct passwd *passwd;
+       register int pflg, pid, uflg, uid;
+       int ch, size;
+       struct passwd *getpwnam(), *getpwuid();
+       long lgetw();
+       char *malloc();
+
+       pflg = uflg = 0;
+       while ((ch = getopt(argc, argv, "p:u:v")) != EOF)
+               switch((char)ch) {
+               case 'p':
+                       if (pflg++)
+                               usage();
+                       if (!isdigit(*optarg)) {
+                               fputs("fstat: -p option requires a process id.\n", stderr);
                                usage();
                                usage();
-                       if ((uid = getuname(*(++argv))) < 0) {
-                               fprintf(stderr, "%s: unknown user\n", *argv);
-                               exit(1);
                        }
                        }
-                       argv++;
-                       continue;
-               } 
-               if (strcmp(*argv, "-f") == 0) {
-                       fflg++;
-                       if (getfname(*(++argv)) < 0) {
-                               perror(*argv);
+                       pid = atoi(optarg);
+                       break;
+               case 'u':
+                       if (uflg++)
+                               usage();
+                       if (!(passwd = getpwnam(optarg))) {
+                               fprintf(stderr, "%s: unknown uid\n", optarg);
                                exit(1);
                        }
                                exit(1);
                        }
-                       argv++;
-                       continue;
+                       uid = passwd->pw_uid;
+                       uname = passwd->pw_name;
+                       break;
+               case 'v':       /* undocumented: print read error messages */
+                       vflg++;
+                       break;
+               case '?':
+               default:
+                       usage();
                }
 
                }
 
-               if (strcmp(*argv, "-p") == 0) {
-                       if (pflg++ || ((pid = Atoi(*(++argv))) <= 0)) {
-                               usage();
-                               perror(*argv);
-                               exit(1);
-                       }
-                       argv++;
-                       continue;
+       if (*(argv += optind)) {
+               for (; *argv; ++argv) {
+                       if (getfname(*argv))
+                               fflg = 1;
                }
                }
-               /* otherwise its a file argument */
-               fflg++;
-               if (getfname(*argv) < 0) {
-                       perror(*argv);
+               if (!fflg)      /* file(s) specified, but none accessable */
                        exit(1);
                        exit(1);
-               }
-               argv++;
-               continue;
-       }
-
-       if (chdir("/dev") < 0) {
-               perror("/dev");
-               exit(1);
        }
 
        }
 
-       printf("USER\t CMD\t      PID    FD\tDEVICE\tINODE\t  SIZE\tTYPE\n");
        openfiles();
        openfiles();
-       getkvars();
-       procp = getw((off_t) nl[X_PROC].n_value);
-       nproc = getw((off_t) nl[X_NPROC].n_value);
-       for (i=0; i<nproc; i += 8) {
-               lseek(kmem, (long) procp, 0);
-               j = nproc - i;
-               if (j > 8)
-                       j = 8;
-               j *= sizeof (struct proc);
-               if (read(kmem, (char *) proc, j) != j)
-                       cantread("proc table", kmemf);
-               procp += j;
-               for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
-                       mproc = &proc[j];
-                       if (mproc->p_stat == 0)
-                               continue;
-                       doproc();
-               }
-       }
-       exit(0);
-}
 
 
-long
-getw(loc)
-       off_t loc;
-{
-       long word;
-
-       lseek(kmem, (long) loc, 0);
-       if (read(kmem, (char *) &word, sizeof (word)) != sizeof (word))
-               vprintf("error reading kmem at %x\n", loc);
-       return (word);
-}
-
-openfiles()
-{
-
-       kmemf = "kmem";
-       kmem = open(kmemf, 0);
-       if (kmem < 0) {
-               perror(kmemf);
-               exit(1);
-       }
-       memf = "mem";
-       mem = open(memf, 0);
-       if (mem < 0) {
-               perror(memf);
-               exit(1);
-       }
-       swapf = "drum";
-       swap = open(swapf, 0);
-       if (swap < 0) {
-               perror(swapf);
+       if (nlist(_PATH_UNIX, nl) == -1 || !nl[0].n_type) {
+               fprintf(stderr, "%s: No namelist\n", _PATH_UNIX);
                exit(1);
        }
                exit(1);
        }
-}
-
-getkvars()
-{
-       nlistf = "/vmunix";
-       nlist(nlistf, nl);
-       if (nl[0].n_type == 0) {
-               fprintf(stderr, "%s: No namelist\n", nlistf);
-               exit(1);
-       }
-       Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
+       Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
        usrpt = (struct pte *) nl[X_USRPT].n_value;
        usrpt = (struct pte *) nl[X_USRPT].n_value;
-       lseek(kmem, (long) nl[X_NSWAP].n_value, 0);
-       if (read(kmem, (char *) &nswap, sizeof (nswap)) != sizeof (nswap)) {
-               cantread("nswap", kmemf);
+       nproc = (int)lgetw((off_t)nl[X_NPROC].n_value);
+
+       (void)lseek(kmem, lgetw((off_t)nl[X_PROC].n_value), L_SET);
+       size = nproc * sizeof(struct proc);
+       if ((mproc = (struct proc *)malloc((u_int)size)) == NULL) {
+               fprintf(stderr, "fstat: out of space.\n");
                exit(1);
        }
                exit(1);
        }
-}
-
-cantread(what, fromwhat)
-       char *what, *fromwhat;
-{
-
-       vprintf("fstat: error reading %s from %s", what, fromwhat);
-}
+       if (read(kmem, (char *)mproc, size) != size)
+               rerr1("proc table", _PATH_KMEM);
 
 
-doproc()
-{
-       struct passwd   *getpwuid();
-
-
-       if (uflg && mproc->p_uid != uid)
-               return;
-       if (pflg && mproc->p_pid != pid)
-               return;
-       if (mproc->p_stat != SZOMB && getu() == 0)
-               return;
-       uname = getpwuid(mproc->p_uid)->pw_name;
-       dotext();
-       getf();
+       printf("USER\t CMD\t      PID    FD\tDEVICE\tINODE\t  SIZE TYPE%s\n",
+           fflg ? " NAME" : "");
+       for (; nproc--; ++mproc) {
+               if (mproc->p_stat == 0)
+                       continue;
+               if (pflg && mproc->p_pid != pid)
+                       continue;
+               if (uflg)  {
+                       if (mproc->p_uid != uid)
+                               continue;
+               }
+               else
+                       uname = (passwd = getpwuid(mproc->p_uid)) ?
+                           passwd->pw_name : "unknown";
+               if (mproc->p_stat != SZOMB && getu() == 0)
+                       continue;
+               dotext();
+               readf();
+       }
+       exit(0);
 }
 
 }
 
+static
 getu()
 {
        struct pte *pteaddr, apte;
        struct pte arguutl[UPAGES+CLSIZE];
        register int i;
 getu()
 {
        struct pte *pteaddr, apte;
        struct pte arguutl[UPAGES+CLSIZE];
        register int i;
-       int ncl, size;
+       int ncl;
 
 
-       size = sizeof (struct user);
        if ((mproc->p_flag & SLOAD) == 0) {
                if (swap < 0)
        if ((mproc->p_flag & SLOAD) == 0) {
                if (swap < 0)
-                       return (0);
-               (void) lseek(swap, (long)dtob(mproc->p_swaddr), 0);
-               if (read(swap, (char *)&user.user, size) != size) {
-                       fprintf(stderr, "ps: cant read u for pid %d from %s\n",
-                           mproc->p_pid, swapf);
-                       return (0);
+                       return(0);
+               (void)lseek(swap, (off_t)dtob(mproc->p_swaddr), L_SET);
+               if (read(swap, (char *)&user.user, sizeof(struct user))
+                   != sizeof(struct user)) {
+                       fprintf(stderr, "fstat: can't read u for pid %d from %s\n", mproc->p_pid, _PATH_SWAP);
+                       return(0);
                }
                }
-               pcbpf = 0;
-               argaddr = 0;
-               return (1);
+               return(1);
        }
        pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
        }
        pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
-       klseek(kmem, (long)pteaddr, 0);
+       (void)lseek(kmem, (off_t)pteaddr, L_SET);
        if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
        if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
-               printf("fstat: cant read indir pte to get u for pid %d from %s\n",
-                   mproc->p_pid, swapf);
-               return (0);
+               printf("fstat: can't read indir pte to get u for pid %d from %s\n", mproc->p_pid, _PATH_SWAP);
+               return(0);
        }
        }
-       klseek(mem,
-           (long)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte),
-               0);
+       (void)lseek(mem, (off_t)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE)
+           * sizeof(struct pte), L_SET);
        if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
        if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
-               printf("fstat: cant read page table for u of pid %d from %s\n",
-                   mproc->p_pid, kmemf);
-               return (0);
+               printf("fstat: can't read page table for u of pid %d from %s\n", mproc->p_pid, _PATH_KMEM);
+               return(0);
        }
        }
-       if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
-               argaddr = ctob(arguutl[0].pg_pfnum);
-       else
-               argaddr = 0;
-       pcbpf = arguutl[CLSIZE].pg_pfnum;
-       ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
+       ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
        while (--ncl >= 0) {
                i = ncl * CLSIZE;
        while (--ncl >= 0) {
                i = ncl * CLSIZE;
-               klseek(mem, (long)ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
+               (void)lseek(mem, (off_t)ctob(arguutl[CLSIZE+i].pg_pfnum), L_SET);
                if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
                if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
-                       printf("fstat: cant read page %d of u of pid %d from %s\n",
-                           arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
+                       printf("fstat: can't read page %u of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, _PATH_MEM);
                        return(0);
                }
        }
                        return(0);
                }
        }
-       return (1);
+       return(1);
 }
 
 }
 
-#define        NMAX    8
-#define        NUID    2048
-
+static
 dotext()
 {
 dotext()
 {
-       struct text     text;
+       struct text text;
 
 
-       lseek(kmem, (long) mproc->p_textp, 0);
+       (void)lseek(kmem, (off_t)mproc->p_textp, L_SET);
        if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) {
        if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) {
-               cantread("text table", kmemf);
-               return;
-       }
-       if (text.x_flag == 0)
+               rerr1("text table", _PATH_KMEM);
                return;
                return;
-       itrans(DTYPE_INODE, text.x_iptr, TEXT);
-}
-
-char   *itypename[] = {
-       "unk",
-#define UNK 0  /* unknown */
-       "chr",
-#define CHR 1  
-       "dir",
-#define DIR 2
-       "blk",
-#define BLK 3
-       "reg",
-#define REG 4
-       "lnk",
-#define LNK 5
-       "soc"
-#define SOC 6
-};
-
-itype(mode)
-{
-       switch(mode&IFMT) {
-       case IFCHR:
-               return(CHR);
-       case IFDIR:
-               return(DIR);
-       case IFBLK:
-               return(BLK);
-       case IFREG:
-               return(REG);
-       case IFLNK:
-               return(LNK);
-       case IFSOCK:
-               return(SOC);
-       default:
-               return(0);
        }
        }
+       if (text.x_flag)
+               itrans(DTYPE_INODE, text.x_iptr, TEXT);
 }
 
 }
 
+static
 itrans(ftype, g, fno)
 itrans(ftype, g, fno)
-struct inode   *g;  /* if ftype is inode */
+       int ftype, fno;
+       struct inode *g;                /* if ftype is inode */
 {
 {
-       struct inode    inode;
-       dev_t   idev;
-       int     type;
-       char    *comm;
-
-       if (g == 0 && ! fflg) {
-               goto skip;
-       }
-       lseek(kmem, (long) g, 0);
-       if (read(kmem, (char *) &inode, sizeof(inode))
-                                       != sizeof(inode)) {
-               vprintf("error %d reading inode at %x from kmem\n", errno, g);
-               return;
+       struct inode inode;
+       dev_t idev;
+       char *comm, *itype();
+       char *name = (char *)NULL;      /* set by devmatch() on a match */
+
+       if (g || fflg) {
+               (void)lseek(kmem, (off_t)g, L_SET);
+               if (read(kmem, (char *)&inode, sizeof(inode)) != sizeof(inode)) {
+                       rerr2(errno, (int)g, "inode");
+                       return;
+               }
+               idev = inode.i_dev;
+               if (fflg && !devmatch(idev, inode.i_number, &name))
+                       return;
        }
        }
-       idev = inode.i_dev;
-       if (fflg && !devmatch(idev, inode.i_number))
-               return;
-skip:
        if (mproc->p_pid == 0)
                comm = "swapper";
        else if (mproc->p_pid == 2)
                comm = "pagedaemon";
        else
        if (mproc->p_pid == 0)
                comm = "swapper";
        else if (mproc->p_pid == 2)
                comm = "pagedaemon";
        else
-               comm = u.u_comm;
+               comm = user.user.u_comm;
        printf("%-8.8s %-10.10s %5d  ", uname, comm, mproc->p_pid);
        printf("%-8.8s %-10.10s %5d  ", uname, comm, mproc->p_pid);
-       if (fno == WD)
-               printf("  wd");
-       else if (fno == TEXT)
-               printf("text");
-       else
+
+       switch(fno) {
+       case WD:
+               printf("  wd"); break;
+       case TEXT:
+               printf("text"); break;
+       default:
                printf("%4d", fno);
                printf("%4d", fno);
+       }
 
        if (g == 0) {
                printf("* (deallocated)\n");
                return;
        }
 
 
        if (g == 0) {
                printf("* (deallocated)\n");
                return;
        }
 
-       if (ftype == DTYPE_INODE) {
-               type = itype(inode.i_mode);  /* determine inode type */
-               printf("\t%2d, %2d\t%5d\t%6d\t%3s\n", major(inode.i_dev), minor(inode.i_dev),
-                       inode.i_number, type == SOC?0:inode.i_size, itypename[type]);
-       }
-       else if (ftype == DTYPE_SOCKET) {
+       switch(ftype) {
+       case DTYPE_INODE:
+               printf("\t%2d, %2d\t%5lu\t",
+                   major(inode.i_dev),
+                   minor(inode.i_dev), inode.i_number
+               );
+               switch(inode.i_mode & IFMT) {
+               case    IFSOCK:
+                       printf("     0\t");
+                       break;
+               case    IFCHR:
+                       printf("%2d, %2d\t", major(inode.i_rdev), minor(inode.i_rdev));
+                       break;
+               default:
+                       printf("%6ld\t", inode.i_size);
+               }
+               printf("%3s %s\n", itype(inode.i_mode), name ? name : "");
+               break;
+       case DTYPE_SOCKET:
                socktrans((struct socket *)g);
                socktrans((struct socket *)g);
-       }
+               break;
 #ifdef DTYPE_PORT
 #ifdef DTYPE_PORT
-       else if (ftype == DTYPE_PORT) {
+       case DTYPE_PORT:
                printf("* (fifo / named pipe)\n");
                printf("* (fifo / named pipe)\n");
-       }
-#endif DTYPE_PORT
-       else {
+               break;
+#endif
+       default:
                printf("* (unknown file type)\n");
        }
 }
                printf("* (unknown file type)\n");
        }
 }
-devmatch(idev, inum)
-dev_t idev;
-int inum;
+
+static char *
+itype(mode)
+       u_short mode;
 {
 {
-       struct devs *d = &devs;
-       for (d = d->next; d; d = d->next) {
-               if (d->dev == idev) {
-                       if (d->inum == 0)
-                               return(1);
-                       if (d->inum == inum)
-                               return(1);
-               }
+       switch(mode & IFMT) {
+       case IFCHR:
+               return("chr");
+       case IFDIR:
+               return("dir");
+       case IFBLK:
+               return("blk");
+       case IFREG:
+               return("reg");
+       case IFLNK:
+               return("lnk");
+       case IFSOCK:
+               return("soc");
+       default:
+               return("unk");
        }
        }
-       return(0);
+       /*NOTREACHED*/
 }
 
 }
 
+static
 socktrans(sock)
 socktrans(sock)
-struct socket *sock;
+       struct socket *sock;
 {
 {
-       struct socket   so;
-       struct protosw  proto;
-       struct domain   dom;
-       char    dname[32];      /* domain name, e.g. "inet" */
-       char    c;
-       char    *cp;
-       int     i;
-       char    *stype;
-       struct inpcb    inpcb;
-       struct unpcb    unpcb;
+       static char *stypename[] = {
+               "unused",       /* 0 */
+               "stream",       /* 1 */
+               "dgram",        /* 2 */
+               "raw",          /* 3 */
+               "rdm",          /* 4 */
+               "seqpak"        /* 5 */
+       };
+#define        STYPEMAX 5
+       struct socket   so;
+       struct protosw  proto;
+       struct domain   dom;
+       struct inpcb    inpcb;
+       struct unpcb    unpcb;
+       int len;
+       char dname[32], *strcpy();
 
        /* fill in socket */
 
        /* fill in socket */
-       lseek(kmem, (long) sock, 0);
-       if (read(kmem, (char *) &so, sizeof(struct socket)) 
-           != sizeof(struct socket)){
-               vprintf("error %d reading socket at %x from kmem\n", errno, sock);
+       (void)lseek(kmem, (off_t)sock, L_SET);
+       if (read(kmem, (char *)&so, sizeof(struct socket))
+           != sizeof(struct socket)) {
+               rerr2(errno, (int)sock, "socket");
                return;
        }
 
        /* fill in protosw entry */
                return;
        }
 
        /* fill in protosw entry */
-       lseek(kmem, (long) so.so_proto, 0);
-       if (read(kmem, (char *) &proto, sizeof(struct protosw)) 
-           != sizeof(struct protosw)){
-               vprintf("error %d reading protosw at %x from kmem\n", errno, so.so_proto);
+       (void)lseek(kmem, (off_t)so.so_proto, L_SET);
+       if (read(kmem, (char *)&proto, sizeof(struct protosw))
+           != sizeof(struct protosw)) {
+               rerr2(errno, (int)so.so_proto, "protosw");
                return;
        }
 
        /* fill in domain */
                return;
        }
 
        /* fill in domain */
-       lseek(kmem, (long) proto.pr_domain, 0);
-       if (read(kmem, (char *) &dom, sizeof(struct domain)) 
-           != sizeof(struct domain)){
-               vprintf("error %d reading domain at %x from kmem\n", errno, proto.pr_domain);
+       (void)lseek(kmem, (off_t)proto.pr_domain, L_SET);
+       if (read(kmem, (char *)&dom, sizeof(struct domain))
+           != sizeof(struct domain)) {
+               rerr2(errno, (int)proto.pr_domain, "domain");
                return;
        }
 
                return;
        }
 
-       /* Grab domain name */
-       lseek(kmem, (long) dom.dom_name, 0);
-       for (cp=dname, i=0; i < 30; i++, cp++) { /* 30 leaves room for null byte */
-               if (read(kmem, (char *)&c, sizeof(char)) != sizeof(char)) {
-                   vprintf("error %d reading char at %x from kmem\n", errno, dom.dom_name+i);
-                   break;
+       /*
+        * grab domain name
+        * kludge "internet" --> "inet" for brevity
+        */
+       if (dom.dom_family == AF_INET)
+               (void)strcpy(dname, "inet");
+       else {
+               (void)lseek(kmem, (off_t)dom.dom_name, L_SET);
+               if ((len = read(kmem, dname, sizeof(dname) - 1)) < 0) {
+                       rerr2(errno, (int)dom.dom_name, "char");
+                       dname[0] = '\0';
                }
                }
-               if (c == '\0')
-                       break;
-               *cp = c;
+               else
+                       dname[len] = '\0';
        }
        }
-       *cp='\0';
-       /* kludge "internet" --> "inet" for brevity */
-       if (dom.dom_family == AF_INET)  
-               strcpy(dname, "inet");
-
-       if (so.so_type < 1 || so.so_type > STYPEMAX) {
-               
-               stype = emalloc(10);
-               (void)sprintf(stype,"unk%d", so.so_type);
-       } else
-               stype = stypename[so.so_type];
 
 
-       /* print sock type, sock state, and domain name */
-       printf("* (%s %s %x", dname, stype, so.so_state);
+       if ((u_short)so.so_type > STYPEMAX)
+               printf("* (%s unk%d %x", dname, so.so_type, so.so_state);
+       else
+               printf("* (%s %s %x", dname, stypename[so.so_type],
+                   so.so_state);
 
        /* 
 
        /* 
-        * protocol specific formating 
+        * protocol specific formatting
         *
         *
-        * Try to find interesting things to print.  For tcp, the
-        * interesting thing is the address of the tcpcb, for udp
-        * and others, just the inpcb (socket pcb).  For unix
-        * domain, its the address of the socket pcb and the address of
-        * the connected pcb (if connected).  Otherwise just print
-        * the protocol number and address of the socket itself. The
-        * idea is not to duplicate netstat, but to make available
-        * enough information for further analysis. 
+        * Try to find interesting things to print.  For tcp, the interesting
+        * thing is the address of the tcpcb, for udp and others, just the
+        * inpcb (socket pcb).  For unix domain, its the address of the socket
+        * pcb and the address of the connected pcb (if connected).  Otherwise
+        * just print the protocol number and address of the socket itself.
+        * The idea is not to duplicate netstat, but to make available enough
+        * information for further analysis.
         */
         */
-       if (dom.dom_family == AF_INET) {
-               /* print name of protocol number */
-               printf(" %s", getinetproto(proto.pr_protocol));
+       switch(dom.dom_family) {
+       case AF_INET:
+               getinetproto(proto.pr_protocol);
                if (proto.pr_protocol == IPPROTO_TCP ) {
                        if (so.so_pcb) {
                if (proto.pr_protocol == IPPROTO_TCP ) {
                        if (so.so_pcb) {
-                               lseek(kmem, (long) so.so_pcb, 0);
-                               if (read(kmem, (char *) &inpcb, sizeof(struct inpcb)) 
+                               (void)lseek(kmem, (off_t)so.so_pcb, L_SET);
+                               if (read(kmem, (char *)&inpcb, sizeof(struct inpcb))
                                    != sizeof(struct inpcb)){
                                    != sizeof(struct inpcb)){
-                                       vprintf("error %d reading inpcb at %x from kmem\n",
-                                            errno, so.so_pcb);
+                                       rerr2(errno, (int)so.so_pcb, "inpcb");
                                        return;
                                }
                                        return;
                                }
-                               printf(" %x", inpcb.inp_ppcb);
+                               printf(" %x", (int)inpcb.inp_ppcb);
                        }
                        }
-               } else if (so.so_pcb) {
-                               printf(" %x", so.so_pcb);
                }
                }
-       } else if (dom.dom_family == AF_UNIX) { 
+               else if (so.so_pcb)
+                       printf(" %x", (int)so.so_pcb);
+               break;
+       case AF_UNIX:
                /* print address of pcb and connected pcb */
                if (so.so_pcb) {
                /* print address of pcb and connected pcb */
                if (so.so_pcb) {
-                       printf(" %x", so.so_pcb);
-                       lseek(kmem, (long) so.so_pcb, 0);
-                       if (read(kmem, (char *) &unpcb, sizeof(struct unpcb)) 
+                       printf(" %x", (int)so.so_pcb);
+                       (void)lseek(kmem, (off_t)so.so_pcb, L_SET);
+                       if (read(kmem, (char *)&unpcb, sizeof(struct unpcb))
                            != sizeof(struct unpcb)){
                            != sizeof(struct unpcb)){
-                               vprintf("error %d reading unpcb at %x from kmem\n",
-                                    errno, so.so_pcb);
+                               rerr2(errno, (int)so.so_pcb, "unpcb");
                                return;
                        }
                        if (unpcb.unp_conn) {
                                return;
                        }
                        if (unpcb.unp_conn) {
-                               char shoconn[4]; *shoconn = 0;
+                               char shoconn[4], *cp;
+
+                               cp = shoconn;
                                if (!(so.so_state & SS_CANTRCVMORE))
                                if (!(so.so_state & SS_CANTRCVMORE))
-                                       strcat(shoconn, "<");
-                               strcat(shoconn,"-");
+                                       *cp++ = '<';
+                               *cp++ = '-';
                                if (!(so.so_state & SS_CANTSENDMORE))
                                if (!(so.so_state & SS_CANTSENDMORE))
-                                       strcat(shoconn, ">");
-                               printf(" %s %x", shoconn, unpcb.unp_conn);
+                                       *cp++ = '>';
+                               *cp = '\0';
+                               printf(" %s %x", shoconn, (int)unpcb.unp_conn);
                        }
                }
                        }
                }
-       } else {
+               break;
+       default:
                /* print protocol number and socket address */
                /* print protocol number and socket address */
-               printf(" %d %x", proto.pr_protocol, sock);
+               printf(" %d %x", proto.pr_protocol, (int)sock);
        }
        printf(")\n");
 }
 
        }
        printf(")\n");
 }
 
-char *
+/*
+ * getinetproto --
+ *     print name of protocol number
+ */
+static
 getinetproto(number)
 getinetproto(number)
+       int number;
 {
 {
-       char    *cp;
+       char *cp;
 
        switch(number) {
 
        switch(number) {
-       case 0:  return("ip");
-       case 1:  return("icmp");
-       case 2:  return("ggp");
-       case 6:  return("tcp");
-       case 8:  return("egp");
-       case 12: return("pup");
-       case 17: return("udp");
-       case 22: return("idp");
-       case 255: return("raw");
+       case IPPROTO_IP:
+               cp = "ip"; break;
+       case IPPROTO_ICMP:
+               cp ="icmp"; break;
+       case IPPROTO_GGP:
+               cp ="ggp"; break;
+       case IPPROTO_TCP:
+               cp ="tcp"; break;
+       case IPPROTO_EGP:
+               cp ="egp"; break;
+       case IPPROTO_PUP:
+               cp ="pup"; break;
+       case IPPROTO_UDP:
+               cp ="udp"; break;
+       case IPPROTO_IDP:
+               cp ="idp"; break;
+       case IPPROTO_RAW:
+               cp ="raw"; break;
        default:
        default:
-               (void)sprintf(emalloc(16),"%d",number);
-               return(cp);
-       }
-}
-               
-char *
-emalloc(size)
-{
-       char *cp;
-       cp = (char *)malloc(size);
-       if (cp < 0) {
-               fprintf(stderr,"Out of space.\n");
-               exit(1);
+               printf(" %d", number);
+               return;
        }
        }
-       return(cp);
+       printf(" %s", cp);
 }
 
 }
 
-struct  file  *
-getf()
+static
+readf()
 {
 {
-       int     i;
-       struct file     file;
+       struct file lfile;
+       int i;
 
 
-       itrans(DTYPE_INODE, u.u_cdir, WD);
+       itrans(DTYPE_INODE, user.user.u_cdir, WD);
        for (i = 0; i < NOFILE; i++) {
        for (i = 0; i < NOFILE; i++) {
-               if (u.u_ofile[i] == 0)
+               if (user.user.u_ofile[i] == 0)
                        continue;
                        continue;
-               lseek(kmem, (long) u.u_ofile[i], 0);
-               if (read(kmem, (char *) &file, sizeof(file)) != sizeof(file)) {
-                       cantread("file", kmemf);
+               (void)lseek(kmem, (off_t)user.user.u_ofile[i], L_SET);
+               if (read(kmem, (char *)&lfile, sizeof(lfile))
+                   != sizeof(lfile)) {
+                       rerr1("file", _PATH_KMEM);
                        continue;
                }
                        continue;
                }
-               /*printf("flag: %x count: %x ",file.f_flag, file.f_count);
-               /*fflush(stdout);
-                */
-               itrans(file.f_type, file.f_data, i); 
+               itrans(lfile.f_type, (struct inode *)lfile.f_data, i);
        }
 }
 
        }
 }
 
-usage()
+static
+devmatch(idev, inum, name)
+       dev_t idev;
+       ino_t inum;
+       char  **name;
 {
 {
-       fputs("usage: fstat [-u user] [-f filename] [-p pid]\n", stderr);
-       exit(1);
-}
+       register DEVS *d;
 
 
-getuname(uname)
-char   *uname;
-{
-       struct passwd   *passwd, *getpwnam();
-       
-       if ((passwd = getpwnam(uname)) == NULL)
-               return(-1);
-       return(passwd->pw_uid);
+       for (d = devs; d; d = d->next)
+               if (d->dev == idev && (d->inum == 0 || d->inum == inum)) {
+                       *name = d->name;
+                       return(1);
+               }
+       return(0);
 }
 
 }
 
+static
 getfname(filename)
 getfname(filename)
-char   *filename;
+       char *filename;
 {
 {
-       struct  stat statbuf;
-       struct devs *d, *oldd;
-       dev_t dev;
-       int inum;
+       struct stat statbuf;
+       DEVS *cur;
+       char *malloc();
 
 
-       if (stat(filename, &statbuf) != 0)
-               return(-1);
+       if (stat(filename, &statbuf)) {
+               fprintf(stderr, "fstat: %s: %s\n", strerror(errno), filename);
+               return(0);
+       }
+       if ((cur = (DEVS *)malloc(sizeof(DEVS))) == NULL) {
+               fprintf(stderr, "fstat: out of space.\n");
+               exit(1);
+       }
+       cur->next = devs;
+       devs = cur;
 
 
-       /*
-        *      if file is block special, look for open files on it
-        */
+       /* if file is block special, look for open files on it */
        if ((statbuf.st_mode & S_IFMT) != S_IFBLK) {
        if ((statbuf.st_mode & S_IFMT) != S_IFBLK) {
-               inum = statbuf.st_ino;
-               dev = statbuf.st_dev;
-       } else {
-               inum = 0;
-               dev = statbuf.st_rdev;
+               cur->inum = statbuf.st_ino;
+               cur->dev = statbuf.st_dev;
+       }
+       else {
+               cur->inum = 0;
+               cur->dev = statbuf.st_rdev;
        }
        }
-       for (d = oldd = &devs; d; oldd = d, d = d->next)
-               ;
-       d = (struct devs *)emalloc(sizeof(struct devs));
-       oldd->next = d;
-       d->next = 0;
-       d->dev = dev;
-       d->inum = inum;
+       cur->name = filename;
+       return(1);
 }
 
 }
 
-Atoi(p)
-register char *p;
+static
+openfiles()
 {
 {
-       register int n = 0;
+       if ((kmem = open(_PATH_KMEM, O_RDONLY, 0)) < 0) {
+               (void)fprintf(stderr, "fstat: %s: %s\n",
+                   strerror(errno), _PATH_KMEM);
+               exit(1);
+       }
+       if ((mem = open(_PATH_MEM, O_RDONLY, 0)) < 0) {
+               (void)fprintf(stderr, "fstat: %s: %s\n",
+                   strerror(errno), _PATH_MEM);
+               exit(1);
+       }
+       if ((swap = open(_PATH_SWAP, O_RDONLY, 0)) < 0) {
+               (void)fprintf(stderr, "fstat: %s: %s\n",
+                   strerror(errno), _PATH_SWAP);
+               exit(1);
+       }
+}
 
 
-       while(*p >= '0' && *p <= '9')
-               n = n*10 + *p++ - '0';
-       return(*p ? -n : n);
+static
+rerr1(what, fromwhat)
+       char *what, *fromwhat;
+{
+       if (vflg)
+               printf("error reading %s from %s", what, fromwhat);
 }
 
 }
 
-klseek(fd, loc, off)
-       int fd;
-       long loc;
-       int off;
+static
+rerr2(err, address, what)
+       int err, address;
+       char *what;
 {
 {
-       static int      sizeSysmap;
+       if (vflg)
+               printf("error %d reading %s at %x from %s\n",
+                   errno, what, address, _PATH_KMEM);
+}
 
 
-       if( kflg && Sysmap == 0)
-               {/* initialize Sysmap */
+static long
+lgetw(loc)
+       off_t loc;
+{
+       long word;
 
 
-               sizeSysmap = nl[SSYSSIZE].n_value * sizeof( struct pte);
-               Sysmap = (struct pte *)calloc( sizeSysmap, 1);
-               lseek( kmem, clear( nl[SSYSMAP].n_value), 0);
-               if( read( kmem, Sysmap, sizeSysmap) != sizeSysmap)
-                       {
-                       printf( "Cant read system page table\n");
-                       exit(1);
-                       }
-               }
-       if( kflg && (loc&0x80000000))
-               {/* do mapping for kernel virtual addresses */
-               struct pte *ptep;
-
-               loc &= 0x7fffffff;
-               ptep = &Sysmap[btop(loc)];
-               if( (char *)ptep - (char *)Sysmap > sizeSysmap)
-                       {
-                       printf( "no system pte for %s\n", loc);
-                       exit(1);
-                       }
-               if( ptep->pg_v == 0)
-                       {
-                       printf( "system pte invalid for %x\n", loc);
-                       exit(1);
-                       }
-               loc = (off_t)((loc&PGOFSET) + ptob(ptep->pg_pfnum));
-               }
-       (void) lseek(fd, (long)loc, off);
+       (void)lseek(kmem, (off_t)loc, L_SET);
+       if (read(kmem, (char *)&word, sizeof(word)) != sizeof(word))
+               rerr2(errno, (int)loc, "word");
+       return(word);
+}
+
+static
+usage()
+{
+       fputs("usage: fstat [-u user] [-p pid] [filename ...]\n", stderr);
+       exit(1);
 }
 }