BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / vmstat / vmstat.c
index b9fc6b6..481aa07 100644 (file)
 /*
 /*
- * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1980, 1986, 1991 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: (1) source distributions retain this entire copyright notice and
- * comment, and (2) distributions including binaries display the following
- * acknowledgement:  ``This product includes software developed by the
- * University of California, Berkeley and its contributors'' in the
- * documentation or other materials provided with the distribution and in
- * all advertising materials mentioning features or use of this software.
- * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY 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) 1980 The Regents of the University of California.\n\
+"@(#) Copyright (c) 1980, 1986, 1991 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
-static char sccsid[] = "@(#)vmstat.c   5.21 (Berkeley) 6/6/90";
+static char sccsid[] = "@(#)vmstat.c   5.31 (Berkeley) 7/2/91";
 #endif /* not lint */
 
 #include <sys/param.h>
 #endif /* not lint */
 
 #include <sys/param.h>
-#include <sys/file.h>
-#include <sys/vm.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
 #include <sys/dkstat.h>
 #include <sys/buf.h>
 #include <sys/namei.h>
 #include <sys/dkstat.h>
 #include <sys/buf.h>
 #include <sys/namei.h>
-#include <sys/text.h>
 #include <sys/malloc.h>
 #include <sys/malloc.h>
+#include <sys/signal.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/vmmeter.h>
+#include <vm/vm.h>
+#include <vm/vm_statistics.h>
+#include <time.h>
+#include <nlist.h>
+#include <kvm.h>
+#include <errno.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <ctype.h>
-#include <nlist.h>
+#include <stdlib.h>
+#include <string.h>
 #include <paths.h>
 
 #include <paths.h>
 
+#define NEWVM                  /* XXX till old has been updated or purged */
 struct nlist nl[] = {
 #define        X_CPTIME        0
        { "_cp_time" },
 struct nlist nl[] = {
 #define        X_CPTIME        0
        { "_cp_time" },
-#define        X_RATE          1
-       { "_rate" },
-#define X_TOTAL                2
+#define X_TOTAL                1
        { "_total" },
        { "_total" },
-#define        X_DEFICIT       3
-       { "_deficit" },
-#define        X_FORKSTAT      4
-       { "_forkstat" },
-#define X_SUM          5
-       { "_sum" },
-#define        X_FIRSTFREE     6
-       { "_firstfree" },
-#define        X_MAXFREE       7
-       { "_maxfree" },
-#define        X_BOOTTIME      8
+#define X_SUM          2
+       { "_cnt" },             /* XXX for now that's where it is */
+#define        X_BOOTTIME      3
        { "_boottime" },
        { "_boottime" },
-#define        X_DKXFER        9
+#define        X_DKXFER        4
        { "_dk_xfer" },
        { "_dk_xfer" },
-#define X_REC          10
-       { "_rectime" },
-#define X_PGIN         11
-       { "_pgintime" },
-#define X_HZ           12
+#define X_HZ           5
        { "_hz" },
        { "_hz" },
-#define X_PHZ          13
+#define X_PHZ          6
        { "_phz" },
        { "_phz" },
-#define X_NCHSTATS     14
+#define X_NCHSTATS     7
        { "_nchstats" },
        { "_nchstats" },
-#define        X_INTRNAMES     15
+#define        X_INTRNAMES     8
        { "_intrnames" },
        { "_intrnames" },
-#define        X_EINTRNAMES    16
+#define        X_EINTRNAMES    9
        { "_eintrnames" },
        { "_eintrnames" },
-#define        X_INTRCNT       17
+#define        X_INTRCNT       10
        { "_intrcnt" },
        { "_intrcnt" },
-#define        X_EINTRCNT      18
+#define        X_EINTRCNT      11
        { "_eintrcnt" },
        { "_eintrcnt" },
-#define        X_DK_NDRIVE     19
+#define        X_DK_NDRIVE     12
        { "_dk_ndrive" },
        { "_dk_ndrive" },
-#define        X_XSTATS        20
-       { "_xstats" },
-#define        X_KMEMSTAT      21
+#define        X_KMEMSTAT      13
        { "_kmemstats" },
        { "_kmemstats" },
-#define        X_KMEMBUCKETS   22
+#define        X_KMEMBUCKETS   14
        { "_bucket" },
        { "_bucket" },
-#define X_END          22
-#ifdef vax
-#define X_MBDINIT      (X_END+1)
-       { "_mbdinit" },
-#define X_UBDINIT      (X_END+2)
-       { "_ubdinit" },
+#define        X_VMSTAT        15
+       { "_vm_stat" },
+#ifdef notdef
+#define        X_DEFICIT       15
+       { "_deficit" },
+#define        X_FORKSTAT      16
+       { "_forkstat" },
+#define X_REC          17
+       { "_rectime" },
+#define X_PGIN         18
+       { "_pgintime" },
+#define        X_XSTATS        19
+       { "_xstats" },
+#define X_END          19
+#else
+#define X_END          15
+#endif
+#ifdef hp300
+#define        X_HPDINIT       (X_END+1)
+       { "_hp_dinit" },
 #endif
 #ifdef tahoe
 #define        X_VBDINIT       (X_END+1)
 #endif
 #ifdef tahoe
 #define        X_VBDINIT       (X_END+1)
@@ -102,180 +127,211 @@ struct nlist nl[] = {
 #define        X_DKEYSTATS     (X_END+3)
        { "_dkeystats" },
 #endif
 #define        X_DKEYSTATS     (X_END+3)
        { "_dkeystats" },
 #endif
-#ifdef hp300
-#define        X_HPDINIT       (X_END+1)
-       { "_hp_dinit" },
+#ifdef vax
+#define X_MBDINIT      (X_END+1)
+       { "_mbdinit" },
+#define X_UBDINIT      (X_END+2)
+       { "_ubdinit" },
 #endif
        { "" },
 };
 
 #endif
        { "" },
 };
 
+struct _disk {
+       long time[CPUSTATES];
+       long *xfer;
+} cur, last;
+
+struct vm_statistics vm_stat, ostat;
+struct vmmeter sum, osum;
+char   *vmunix = _PATH_UNIX;
 char   **dr_name;
 char   **dr_name;
-int    *dr_select;
-int    dk_ndrive;
-int    ndrives = 0;
-#ifdef vax
-char   *defdrives[] = { "hp0", "hp1", "hp2",  0 };
-#else
-#ifdef hp300
-char   *defdrives[] = { "rd0", "rd1", "rd2",  0 };
-#else
-char   *defdrives[] = { 0 };
-#endif
-#endif
-double stat1();
-int    firstfree, maxfree;
-int    hz;
-int    phz;
-int    HZ;
-
-struct {
-       int     busy;
-       long    time[CPUSTATES];
-       long    *xfer;
-       struct  vmmeter Rate;
-       struct  vmtotal Total;
-       struct  vmmeter Sum;
-       struct  forkstat Forkstat;
-       unsigned rectime;
-       unsigned pgintime;
-} s, s1, z;
-#define        rate            s.Rate
-#define        total           s.Total
-#define        sum             s.Sum
-#define        forkstat        s.Forkstat
-
-struct vmmeter osum;
-int    deficit;
-double etime;
-int    mf;
-time_t now, boottime;
-int    printhdr();
-int    lines = 1;
-
-#define        INTS(x) ((x) - (hz + phz))
+int    *dr_select, dk_ndrive, ndrives;
 
 
-main(argc, argv)
-       int argc;
-       char **argv;
-{
-       extern char *ctime();
-       register i;
-       int iter, nintv, iflag = 0;
-       long t;
-       char *arg, **cp, buf[BUFSIZ];
-
-       nlist(_PATH_UNIX, nl);
-       if(nl[0].n_type == 0) {
-               fprintf(stderr, "vmstat: no %s namelist\n", _PATH_UNIX);
-               exit(1);
-       }
-       mf = open(_PATH_KMEM, 0);
-       if(mf < 0) {
-               fprintf(stderr, "vmstat: cannot open %s\n", _PATH_KMEM);
-               exit(1);
-       }
-       iter = 0;
-       argc--, argv++;
-       while (argc>0 && argv[0][0]=='-') {
-               char *cp = *argv++;
-               argc--;
-               while (*++cp) switch (*cp) {
+int    winlines = 20;
 
 
-               case 't':
-                       dotimes();
-                       exit(0);
+#define        FORKSTAT        0x01
+#define        INTRSTAT        0x02
+#define        MEMSTAT         0x04
+#define        SUMSTAT         0x08
+#define        TIMESTAT        0x10
+#define        VMSTAT          0x20
 
 
-               case 'z':
-                       close(mf);
-                       mf = open(_PATH_KMEM, 2);
-                       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
-                       write(mf, &z.Sum, sizeof z.Sum);
-                       exit(0);
+#include "names.c"                     /* disk names -- machine dependent */
 
 
+void   cpustats(), dkstats(), dointr(), domem(), dosum();
+void   dovmstat(), kread(), usage();
+#ifdef notdef
+void   dotimes(), doforkst();
+#endif
+
+main(argc, argv)
+       register int argc;
+       register char **argv;
+{
+       extern int optind;
+       extern char *optarg;
+       register int c, todo;
+       u_int interval;
+       int reps;
+       char *kmem;
+
+       kmem = NULL;
+       interval = reps = todo = 0;
+       while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) {
+               switch (c) {
+               case 'c':
+                       reps = atoi(optarg);
+                       break;
+#ifndef notdef
                case 'f':
                case 'f':
-                       doforkst();
-                       exit(0);
-               
+                       todo |= FORKSTAT;
+                       break;
+#endif
+               case 'i':
+                       todo |= INTRSTAT;
+                       break;
+               case 'M':
+                       kmem = optarg;
+                       break;
                case 'm':
                case 'm':
-                       domem();
-                       exit(0);
-
+                       todo |= MEMSTAT;
+                       break;
+               case 'N':
+                       vmunix = optarg;
+                       break;
                case 's':
                case 's':
-                       dosum();
-                       exit(0);
-
-               case 'i':
-                       iflag++;
+                       todo |= SUMSTAT;
                        break;
                        break;
-
+#ifndef notdef
+               case 't':
+                       todo |= TIMESTAT;
+                       break;
+#endif
+               case 'w':
+                       interval = atoi(optarg);
+                       break;
+               case '?':
                default:
                default:
-                       fprintf(stderr,
-                           "usage: vmstat [ -fsim ] [ interval ] [ count]\n");
-                       exit(1);
+                       usage();
                }
        }
                }
        }
-       lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET);
-       read(mf, &firstfree, sizeof firstfree);
-       lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET);
-       read(mf, &maxfree, sizeof maxfree);
-       lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET);
-       read(mf, &boottime, sizeof boottime);
-       lseek(mf, (long)nl[X_HZ].n_value, L_SET);
-       read(mf, &hz, sizeof hz);
-       if (nl[X_PHZ].n_value != 0) {
-               lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
-               read(mf, &phz, sizeof phz);
-       }
-       HZ = phz ? phz : hz;
-       if (nl[X_DK_NDRIVE].n_value == 0) {
-               fprintf(stderr, "dk_ndrive undefined in system\n");
+       argc -= optind;
+       argv += optind;
+
+       if (todo == 0)
+               todo = VMSTAT;
+
+       if (kvm_openfiles(vmunix, kmem, NULL) < 0) {
+               (void)fprintf(stderr,
+                   "vmstat: kvm_openfiles: %s\n", kvm_geterr());
                exit(1);
        }
                exit(1);
        }
-       lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
-       read(mf, &dk_ndrive, sizeof (dk_ndrive));
-       if (dk_ndrive <= 0) {
-               fprintf(stderr, "dk_ndrive %d\n", dk_ndrive);
+
+       if ((c = kvm_nlist(nl)) != 0) {
+               if (c > 0) {
+                       (void)fprintf(stderr,
+                           "vmstat: undefined symbols in %s:", vmunix);
+                       for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++)
+                               if (nl[c].n_type == 0)
+                                       printf(" %s", nl[c].n_name);
+                       (void)fputc('\n', stderr);
+               } else
+                       (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
+                           kvm_geterr());
                exit(1);
        }
                exit(1);
        }
-       dr_select = (int *)calloc(dk_ndrive, sizeof (int));
-       dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
-#define        allocate(e, t) \
-    s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
-    s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
-       allocate(xfer, long);
-       for (arg = buf, i = 0; i < dk_ndrive; i++) {
-               dr_name[i] = arg;
-               sprintf(dr_name[i], "dk%d", i);
-               arg += strlen(dr_name[i]) + 1;
+
+       if (todo & VMSTAT) {
+               char **getdrivedata();
+               struct winsize winsize;
+
+               argv = getdrivedata(argv);
+               winsize.ws_row = 0;
+               (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
+               if (winsize.ws_row > 0)
+                       winlines = winsize.ws_row;
+
        }
        }
-       read_names();
-       time(&now);
-       nintv = now - boottime;
-       if (nintv <= 0 || nintv > 60*60*24*365*10) {
-               fprintf(stderr,
-                   "Time makes no sense... namelist must be wrong.\n");
-               exit(1);
+
+#define        BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+       if (*argv) {
+               interval = atoi(*argv);
+               if (*++argv)
+                       reps = atoi(*argv);
        }
        }
-       if (iflag) {
-               dointr(nintv);
-               exit(0);
+#endif
+
+       if (interval) {
+               if (!reps)
+                       reps = -1;
+       } else if (reps)
+               interval = 1;
+
+#ifdef notdef
+       if (todo & FORKSTAT)
+               doforkst();
+#endif
+       if (todo & MEMSTAT)
+               domem();
+       if (todo & SUMSTAT)
+               dosum();
+#ifdef notdef
+       if (todo & TIMESTAT)
+               dotimes();
+#endif
+       if (todo & INTRSTAT)
+               dointr();
+       if (todo & VMSTAT)
+               dovmstat(interval, reps);
+       exit(0);
+}
+
+char **
+getdrivedata(argv)
+       char **argv;
+{
+       register int i;
+       register char **cp;
+       char buf[30];
+
+       kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
+       if (dk_ndrive <= 0) {
+               (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
+               exit(1);
        }
        }
+       dr_select = calloc((size_t)dk_ndrive, sizeof(int));
+       dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
+       for (i = 0; i < dk_ndrive; i++)
+               dr_name[i] = NULL;
+       cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
+       last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
+       read_names();
+       for (i = 0; i < dk_ndrive; i++)
+               if (dr_name[i] == NULL) {
+                       (void)sprintf(buf, "??%d", i);
+                       dr_name[i] = strdup(buf);
+               }
+
        /*
        /*
-        * Choose drives to be displayed.  Priority
-        * goes to (in order) drives supplied as arguments,
-        * default drives.  If everything isn't filled
-        * in and there are drives not taken care of,
-        * display the first few that fit.
+        * Choose drives to be displayed.  Priority goes to (in order) drives
+        * supplied as arguments, default drives.  If everything isn't filled
+        * in and there are drives not taken care of, display the first few
+        * that fit.
         */
         */
-       ndrives = 0;
-       while (argc > 0 && !isdigit(argv[0][0])) {
+#define BACKWARD_COMPATIBILITY
+       for (ndrives = 0; *argv; ++argv) {
+#ifdef BACKWARD_COMPATIBILITY
+               if (isdigit(**argv))
+                       break;
+#endif
                for (i = 0; i < dk_ndrive; i++) {
                for (i = 0; i < dk_ndrive; i++) {
-                       if (strcmp(dr_name[i], argv[0]))
+                       if (strcmp(dr_name[i], *argv))
                                continue;
                        dr_select[i] = 1;
                                continue;
                        dr_select[i] = 1;
-                       ndrives++;
+                       ++ndrives;
+                       break;
                }
                }
-               argc--, argv++;
        }
        for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
                if (dr_select[i])
        }
        for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
                if (dr_select[i])
@@ -283,7 +339,7 @@ main(argc, argv)
                for (cp = defdrives; *cp; cp++)
                        if (strcmp(dr_name[i], *cp) == 0) {
                                dr_select[i] = 1;
                for (cp = defdrives; *cp; cp++)
                        if (strcmp(dr_name[i], *cp) == 0) {
                                dr_select[i] = 1;
-                               ndrives++;
+                               ++ndrives;
                                break;
                        }
        }
                                break;
                        }
        }
@@ -291,476 +347,475 @@ main(argc, argv)
                if (dr_select[i])
                        continue;
                dr_select[i] = 1;
                if (dr_select[i])
                        continue;
                dr_select[i] = 1;
-               ndrives++;
+               ++ndrives;
        }
        }
-       if (argc > 1)
-               iter = atoi(argv[1]);
-       signal(SIGCONT, printhdr);
-loop:
-       if (--lines == 0)
-               printhdr();
-       lseek(mf, (long)nl[X_CPTIME].n_value, L_SET);
-       read(mf, s.time, sizeof s.time);
-       lseek(mf, (long)nl[X_DKXFER].n_value, L_SET);
-       read(mf, s.xfer, dk_ndrive * sizeof (long));
-       if (nintv != 1)
-               lseek(mf, (long)nl[X_SUM].n_value, L_SET);
-       else
-               lseek(mf, (long)nl[X_RATE].n_value, L_SET);
-       read(mf, &rate, sizeof rate);
-       lseek(mf, (long)nl[X_TOTAL].n_value, L_SET);
-       read(mf, &total, sizeof total);
-       osum = sum;
-       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
-       read(mf, &sum, sizeof sum);
-       lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET);
-       read(mf, &deficit, sizeof deficit);
-       etime = 0;
-       for (i=0; i < dk_ndrive; i++) {
-               t = s.xfer[i];
-               s.xfer[i] -= s1.xfer[i];
-               s1.xfer[i] = t;
-       }
-       for (i=0; i < CPUSTATES; i++) {
-               t = s.time[i];
-               s.time[i] -= s1.time[i];
-               s1.time[i] = t;
-               etime += s.time[i];
-       }
-       if(etime == 0.)
-               etime = 1.;
-       printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
-#define pgtok(a) ((a)*NBPG/1024)
-       printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free));
-       printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
-           (rate.v_xsfrec+rate.v_xifrec)/nintv);
-       printf("%4d", pgtok(rate.v_pgpgin)/nintv);
-       printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
-           pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
-       etime /= (float)HZ;
-       for (i = 0; i < dk_ndrive; i++)
-               if (dr_select[i])
-                       stats(i);
-       printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
-           rate.v_swtch/nintv);
-       for(i=0; i<CPUSTATES; i++) {
-               float f = stat1(i);
-               if (i == 0) {           /* US+NI */
-                       i++;
-                       f += stat1(i);
-               }
-               printf("%3.0f", f);
+       return(argv);
+}
+
+long
+getuptime()
+{
+       static time_t now, boottime;
+       time_t uptime;
+
+       if (boottime == 0)
+               kread(X_BOOTTIME, &boottime, sizeof(boottime));
+       (void)time(&now);
+       uptime = now - boottime;
+       if (uptime <= 0 || uptime > 60*60*24*365*10) {
+               (void)fprintf(stderr,
+                   "vmstat: time makes no sense; namelist must be wrong.\n");
+               exit(1);
        }
        }
-       printf("\n");
-       fflush(stdout);
-       nintv = 1;
-       if (--iter &&argc > 0) {
-               sleep(atoi(argv[0]));
-               goto loop;
+       return(uptime);
+}
+
+int    hz, hdrcnt;
+
+void
+dovmstat(interval, reps)
+       u_int interval;
+       int reps;
+{
+       struct vmtotal total;
+       time_t uptime, halfuptime;
+       void needhdr();
+#ifndef notdef
+       int deficit;
+#endif
+
+       uptime = getuptime();
+       halfuptime = uptime / 2;
+       (void)signal(SIGCONT, needhdr);
+
+       if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0)
+               kread(X_PHZ, &hz, sizeof(hz));
+       if (!hz)
+               kread(X_HZ, &hz, sizeof(hz));
+
+       for (hdrcnt = 1;;) {
+               if (!--hdrcnt)
+                       printhdr();
+               kread(X_CPTIME, cur.time, sizeof(cur.time));
+               kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive));
+               kread(X_SUM, &sum, sizeof(sum));
+               kread(X_TOTAL, &total, sizeof(total));
+               kread(X_VMSTAT, &vm_stat, sizeof(vm_stat));
+#ifdef notdef
+               kread(X_DEFICIT, &deficit, sizeof(deficit));
+#endif
+               (void)printf("%2d %1d %1d ",
+                   total.t_rq, total.t_dw + total.t_pw, total.t_sw);
+#define pgtok(a) ((a)*NBPG >> 10)
+#define        rate(x) (((x) + halfuptime) / uptime)   /* round */
+               (void)printf("%5ld %5ld ",
+                   pgtok(total.t_avm), pgtok(total.t_free));
+#ifdef NEWVM
+               (void)printf("%4lu ", rate(vm_stat.faults - ostat.faults));
+               (void)printf("%3lu ",
+                   rate(vm_stat.reactivations - ostat.reactivations));
+               (void)printf("%3lu ", rate(vm_stat.pageins - ostat.pageins));
+               (void)printf("%3lu %3lu ",
+                   rate(vm_stat.pageouts - ostat.pageouts), 0);
+#else
+               (void)printf("%3lu %2lu ",
+                   rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) -
+                   (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))),
+                   rate(sum.v_xsfrec + sum.v_xifrec -
+                   osum.v_xsfrec - osum.v_xifrec));
+               (void)printf("%3lu ",
+                   rate(pgtok(sum.v_pgpgin - osum.v_pgpgin)));
+               (void)printf("%3lu %3lu ",
+                   rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)),
+                   rate(pgtok(sum.v_dfree - osum.v_dfree)));
+               (void)printf("%3d ", pgtok(deficit));
+#endif
+               (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan));
+               dkstats();
+               (void)printf("%4lu %4lu %3lu ",
+                   rate(sum.v_intr - osum.v_intr),
+                   rate(sum.v_syscall - osum.v_syscall),
+                   rate(sum.v_swtch - osum.v_swtch));
+               cpustats();
+               (void)printf("\n");
+               (void)fflush(stdout);
+               if (reps >= 0 && --reps <= 0)
+                       break;
+               osum = sum;
+               ostat = vm_stat;
+               uptime = interval;
+               /*
+                * We round upward to avoid losing low-frequency events
+                * (i.e., >= 1 per interval but < 1 per second).
+                */
+               halfuptime = (uptime + 1) / 2;
+               (void)sleep(interval);
        }
 }
 
 printhdr()
 {
        }
 }
 
 printhdr()
 {
-       register int i, j;
-
-       printf(" procs     memory              page           ");
-       i = (ndrives * 3 - 6) / 2;
-       if (i < 0)
-               i = 0;
-       for (j = 0; j < i; j++)
-               putchar(' ');
-       printf("faults");
-       i = ndrives * 3 - 6 - i;
-       for (j = 0; j < i; j++)
-               putchar(' ');
-       printf("               cpu\n");
-       printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
+       register int i;
+
+       (void)printf(" procs   memory     page%*s", 20, "");
+       if (ndrives > 1)
+               (void)printf("disks %*s  faults      cpu\n",
+                  ndrives * 3 - 6, "");
+       else
+               (void)printf("%*s  faults      cpu\n", ndrives * 3, "");
+#ifndef NEWVM
+       (void)printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
+#else
+       (void)printf(" r b w   avm   fre  flt  re  pi  po  fr  sr ");
+#endif
        for (i = 0; i < dk_ndrive; i++)
                if (dr_select[i])
        for (i = 0; i < dk_ndrive; i++)
                if (dr_select[i])
-                       printf("%c%c ", dr_name[i][0], dr_name[i][2]);  
-       printf(" in  sy  cs us sy id\n");
-       lines = 19;
+                       (void)printf("%c%c ", dr_name[i][0],
+                           dr_name[i][strlen(dr_name[i]) - 1]);
+       (void)printf("  in   sy  cs us sy id\n");
+       hdrcnt = winlines - 2;
+}
+
+/*
+ * Force a header to be prepended to the next output.
+ */
+void
+needhdr()
+{
+
+       hdrcnt = 1;
 }
 
 }
 
+#ifdef notdef
+void
 dotimes()
 {
 dotimes()
 {
+       u_int pgintime, rectime;
+
+       kread(X_REC, &rectime, sizeof(rectime));
+       kread(X_PGIN, &pgintime, sizeof(pgintime));
+       kread(X_SUM, &sum, sizeof(sum));
+       (void)printf("%u reclaims, %u total time (usec)\n",
+           sum.v_pgrec, rectime);
+       (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
+       (void)printf("\n");
+       (void)printf("%u page ins, %u total time (msec)\n",
+           sum.v_pgin, pgintime / 10);
+       (void)printf("average: %8.1f msec / page in\n",
+           pgintime / (sum.v_pgin * 10.0));
+}
+#endif
 
 
-       lseek(mf, (long)nl[X_REC].n_value, L_SET);
-       read(mf, &s.rectime, sizeof s.rectime);
-       lseek(mf, (long)nl[X_PGIN].n_value, L_SET);
-       read(mf, &s.pgintime, sizeof s.pgintime);
-       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
-       read(mf, &sum, sizeof sum);
-       printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
-       printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
-       printf("\n");
-       printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
-       printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
+pct(top, bot)
+       long top, bot;
+{
+       if (bot == 0)
+               return(0);
+       return((top * 100) / bot);
 }
 
 }
 
+#define        PCT(top, bot) pct((long)(top), (long)(bot))
+
 #if defined(tahoe)
 #if defined(tahoe)
-#include <tahoe/cpu.h>
+#include <machine/cpu.h>
 #endif
 
 #endif
 
+void
 dosum()
 {
        struct nchstats nchstats;
 dosum()
 {
        struct nchstats nchstats;
+#ifndef NEWVM
        struct xstats xstats;
        struct xstats xstats;
+#endif
        long nchtotal;
 #if defined(tahoe)
        struct keystats keystats;
 #endif
 
        long nchtotal;
 #if defined(tahoe)
        struct keystats keystats;
 #endif
 
-       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
-       read(mf, &sum, sizeof sum);
-       printf("%9d swap ins\n", sum.v_swpin);
-       printf("%9d swap outs\n", sum.v_swpout);
-       printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
-       printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
-       printf("%9d total address trans. faults taken\n", sum.v_faults);
-       printf("%9d page ins\n", sum.v_pgin);
-       printf("%9d page outs\n", sum.v_pgout);
-       printf("%9d pages paged in\n", sum.v_pgpgin);
-       printf("%9d pages paged out\n", sum.v_pgpgout);
-       printf("%9d sequential process pages freed\n", sum.v_seqfree);
-       printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
-           pct(sum.v_fastpgrec, sum.v_pgrec));
-       printf("%9d reclaims from free list\n", sum.v_pgfrec);
-       printf("%9d intransit blocking page faults\n", sum.v_intrans);
-       printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
-       printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
-       printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
-       printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
-       printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
-       printf("%9d inode text pages found in free list\n", sum.v_xifrec);
-       printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
-       printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
-       printf("%9d pages examined by the clock daemon\n", sum.v_scan);
-       printf("%9d revolutions of the clock hand\n", sum.v_rev);
-       printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
-       printf("%9d cpu context switches\n", sum.v_swtch);
-       printf("%9d device interrupts\n", sum.v_intr);
-       printf("%9d software interrupts\n", sum.v_soft);
+       kread(X_SUM, &sum, sizeof(sum));
+#ifdef NEWVM
+       kread(X_VMSTAT, &vm_stat, sizeof(vm_stat));
+#else
+       (void)printf("%9u swap ins\n", sum.v_swpin);
+       (void)printf("%9u swap outs\n", sum.v_swpout);
+       (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
+       (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
+       (void)printf("%9u total address trans. faults taken\n", sum.v_faults);
+       (void)printf("%9u page ins\n", sum.v_pgin);
+       (void)printf("%9u page outs\n", sum.v_pgout);
+       (void)printf("%9u pages paged in\n", sum.v_pgpgin);
+       (void)printf("%9u pages paged out\n", sum.v_pgpgout);
+       (void)printf("%9u sequential process pages freed\n", sum.v_seqfree);
+       (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec,
+           PCT(sum.v_fastpgrec, sum.v_pgrec));
+       (void)printf("%9u reclaims from free list\n", sum.v_pgfrec);
+       (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
+       (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
+       (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
+       (void)printf("%9u executable fill pages created\n",
+           sum.v_nexfod / CLSIZE);
+       (void)printf("%9u executable fill page faults\n",
+           sum.v_exfod / CLSIZE);
+       (void)printf("%9u swap text pages found in free list\n",
+           sum.v_xsfrec);
+       (void)printf("%9u inode text pages found in free list\n",
+           sum.v_xifrec);
+       (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE);
+       (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE);
+       (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
+       (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
+       (void)printf("%9u pages freed by the clock daemon\n",
+           sum.v_dfree / CLSIZE);
+#endif
+       (void)printf("%9u cpu context switches\n", sum.v_swtch);
+       (void)printf("%9u device interrupts\n", sum.v_intr);
+       (void)printf("%9u software interrupts\n", sum.v_soft);
 #ifdef vax
 #ifdef vax
-       printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma);
+       (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
+#endif
+       (void)printf("%9u traps\n", sum.v_trap);
+       (void)printf("%9u system calls\n", sum.v_syscall);
+#ifdef NEWVM
+       (void)printf("%9u bytes per page\n", vm_stat.pagesize);
+       (void)printf("%9u pages free\n", vm_stat.free_count);
+       (void)printf("%9u pages active\n", vm_stat.active_count);
+       (void)printf("%9u pages inactive\n", vm_stat.inactive_count);
+       (void)printf("%9u pages wired down\n", vm_stat.wire_count);
+       (void)printf("%9u zero-fill pages\n", vm_stat.zero_fill_count);
+       (void)printf("%9u pages reactivated\n", vm_stat.reactivations);
+       (void)printf("%9u pageins\n", vm_stat.pageins);
+       (void)printf("%9u pageouts\n", vm_stat.pageouts);
+       (void)printf("%9u VM faults\n", vm_stat.faults);
+       (void)printf("%9u copy-on-write faults\n", vm_stat.cow_faults);
+       (void)printf("%9u VM object cache lookups\n", vm_stat.lookups);
+       (void)printf("%9u VM object hits\n", vm_stat.hits);
 #endif
 #endif
-       printf("%9d traps\n", sum.v_trap);
-       printf("%9d system calls\n", sum.v_syscall);
-       lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
-       read(mf, &nchstats, sizeof nchstats);
+
+       kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
        nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
            nchstats.ncs_badhits + nchstats.ncs_falsehits +
            nchstats.ncs_miss + nchstats.ncs_long;
        nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
            nchstats.ncs_badhits + nchstats.ncs_falsehits +
            nchstats.ncs_miss + nchstats.ncs_long;
-       printf("%9d total name lookups\n", nchtotal);
-       printf("%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
-           "", pct(nchstats.ncs_goodhits, nchtotal),
-           pct(nchstats.ncs_neghits, nchtotal),
-           pct(nchstats.ncs_pass2, nchtotal));
-       printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
-           pct(nchstats.ncs_badhits, nchtotal),
-           pct(nchstats.ncs_falsehits, nchtotal),
-           pct(nchstats.ncs_long, nchtotal));
-       lseek(mf, (long)nl[X_XSTATS].n_value, 0);
-       read(mf, &xstats, sizeof xstats);
-       printf("%9d total calls to xalloc (cache hits %d%%)\n",
-           xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
-       printf("%9s sticky %d flushed %d unused %d\n", "",
+       (void)printf("%9ld total name lookups\n", nchtotal);
+       (void)printf(
+           "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
+           "", PCT(nchstats.ncs_goodhits, nchtotal),
+           PCT(nchstats.ncs_neghits, nchtotal),
+           PCT(nchstats.ncs_pass2, nchtotal));
+       (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
+           PCT(nchstats.ncs_badhits, nchtotal),
+           PCT(nchstats.ncs_falsehits, nchtotal),
+           PCT(nchstats.ncs_long, nchtotal));
+#ifndef NEWVM
+       kread(X_XSTATS, &xstats, sizeof(xstats));
+       (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n",
+           xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc));
+       (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "",
            xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
            xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
-       printf("%9d total calls to xfree", xstats.free);
-       printf(" (sticky %d cached %d swapped %d)\n",
+       (void)printf("%9lu total calls to xfree", xstats.free);
+       (void)printf(" (sticky %lu cached %lu swapped %lu)\n",
            xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
            xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
+#endif
 #if defined(tahoe)
 #if defined(tahoe)
-       lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
-       read(mf, &keystats, sizeof keystats);
-       printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
+       kread(X_CKEYSTATS, &keystats, sizeof(keystats));
+       (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
            keystats.ks_allocs, "code cache keys allocated",
            keystats.ks_allocs, "code cache keys allocated",
-           pct(keystats.ks_allocfree, keystats.ks_allocs),
-           pct(keystats.ks_norefs, keystats.ks_allocs),
-           pct(keystats.ks_taken, keystats.ks_allocs),
-           pct(keystats.ks_shared, keystats.ks_allocs));
-       lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
-       read(mf, &keystats, sizeof keystats);
-       printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
+           PCT(keystats.ks_allocfree, keystats.ks_allocs),
+           PCT(keystats.ks_norefs, keystats.ks_allocs),
+           PCT(keystats.ks_taken, keystats.ks_allocs),
+           PCT(keystats.ks_shared, keystats.ks_allocs));
+       kread(X_DKEYSTATS, &keystats, sizeof(keystats));
+       (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
            keystats.ks_allocs, "data cache keys allocated",
            keystats.ks_allocs, "data cache keys allocated",
-           pct(keystats.ks_allocfree, keystats.ks_allocs),
-           pct(keystats.ks_norefs, keystats.ks_allocs),
-           pct(keystats.ks_taken, keystats.ks_allocs),
-           pct(keystats.ks_shared, keystats.ks_allocs));
+           PCT(keystats.ks_allocfree, keystats.ks_allocs),
+           PCT(keystats.ks_norefs, keystats.ks_allocs),
+           PCT(keystats.ks_taken, keystats.ks_allocs),
+           PCT(keystats.ks_shared, keystats.ks_allocs));
 #endif
 }
 
 #endif
 }
 
+#ifdef notdef
+void
 doforkst()
 {
 doforkst()
 {
+       struct forkstat fks;
 
 
-       lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
-       read(mf, &forkstat, sizeof forkstat);
-       printf("%d forks, %d pages, average=%.2f\n",
-               forkstat.cntfork, forkstat.sizfork,
-               (float) forkstat.sizfork / forkstat.cntfork);
-       printf("%d vforks, %d pages, average=%.2f\n",
-               forkstat.cntvfork, forkstat.sizvfork,
-               (float)forkstat.sizvfork / forkstat.cntvfork);
+       kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
+       (void)printf("%d forks, %d pages, average %.2f\n",
+           fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
+       (void)printf("%d vforks, %d pages, average %.2f\n",
+           fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
 }
 }
+#endif
 
 
-stats(dn)
+void
+dkstats()
 {
 {
-
-       if (dn >= dk_ndrive) {
-               printf("  0");
-               return;
+       register int dn, state;
+       double etime;
+       long tmp;
+
+       for (dn = 0; dn < dk_ndrive; ++dn) {
+               tmp = cur.xfer[dn];
+               cur.xfer[dn] -= last.xfer[dn];
+               last.xfer[dn] = tmp;
+       }
+       etime = 0;
+       for (state = 0; state < CPUSTATES; ++state) {
+               tmp = cur.time[state];
+               cur.time[state] -= last.time[state];
+               last.time[state] = tmp;
+               etime += cur.time[state];
+       }
+       if (etime == 0)
+               etime = 1;
+       etime /= hz;
+       for (dn = 0; dn < dk_ndrive; ++dn) {
+               if (!dr_select[dn])
+                       continue;
+               (void)printf("%2.0f ", cur.xfer[dn] / etime);
        }
        }
-       printf("%3.0f", s.xfer[dn]/etime);
-}
-
-double
-stat1(row)
-{
-       double t;
-       register i;
-
-       t = 0;
-       for(i=0; i<CPUSTATES; i++)
-               t += s.time[i];
-       if(t == 0.)
-               t = 1.;
-       return(s.time[row]*100./t);
 }
 
 }
 
-pct(top, bot)
+void
+cpustats()
 {
 {
-
-       if (bot == 0)
-               return (0);
-       return ((top * 100) / bot);
+       register int state;
+       double pct, total;
+
+       total = 0;
+       for (state = 0; state < CPUSTATES; ++state)
+               total += cur.time[state];
+       if (total)
+               pct = 100 / total;
+       else
+               pct = 0;
+       (void)printf("%2.0f ",                          /* user + nice */
+           (cur.time[0] + cur.time[1]) * pct);
+       (void)printf("%2.0f ", cur.time[2] * pct);      /* system */
+       (void)printf("%2.0f", cur.time[3] * pct);       /* idle */
 }
 
 }
 
-dointr(nintv)
+void
+dointr()
 {
 {
-       int nintr, inttotal;
-       long *intrcnt;
-       char *intrname, *malloc();
-
-       nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
-       intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
-               nl[X_INTRCNT].n_value);
-       intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
+       register long *intrcnt, inttotal, uptime;
+       register int nintr, inamlen;
+       register char *intrname;
+
+       uptime = getuptime();
+       nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value;
+       inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value;
+       intrcnt = malloc((size_t)nintr);
+       intrname = malloc((size_t)inamlen);
        if (intrcnt == NULL || intrname == NULL) {
        if (intrcnt == NULL || intrname == NULL) {
-               fprintf(stderr, "vmstat: out of memory\n");
-               exit(9);
+               (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
+               exit(1);
        }
        }
-       lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
-       read(mf, intrcnt, nintr * sizeof (long));
-       lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
-       read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
-       printf("interrupt      total      rate\n");
+       kread(X_INTRCNT, intrcnt, (size_t)nintr);
+       kread(X_INTRNAMES, intrname, (size_t)inamlen);
+       (void)printf("interrupt      total      rate\n");
        inttotal = 0;
        inttotal = 0;
-       while (nintr--) {
+       nintr /= sizeof(long);
+       while (--nintr >= 0) {
                if (*intrcnt)
                if (*intrcnt)
-                       printf("%-12s %8ld %8ld\n", intrname,
-                           *intrcnt, *intrcnt / nintv);
+                       (void)printf("%-12s %8ld %8ld\n", intrname,
+                           *intrcnt, *intrcnt / uptime);
                intrname += strlen(intrname) + 1;
                inttotal += *intrcnt++;
        }
                intrname += strlen(intrname) + 1;
                inttotal += *intrcnt++;
        }
-       printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
+       (void)printf("Total        %8ld %8ld\n", inttotal, inttotal / uptime);
 }
 
 /*
 }
 
 /*
- * These names must be kept in sync with
- * the types defined in <sys/malloc.h>.
+ * These names are defined in <sys/malloc.h>.
  */
  */
-char *kmemnames[] = {
-       "free",         /* 0 M_FREE */
-       "mbuf",         /* 1 M_MBUF */
-       "devbuf",       /* 2 M_DEVBUF */
-       "socket",       /* 3 M_SOCKET */
-       "pcb",          /* 4 M_PCB */
-       "routetbl",     /* 5 M_RTABLE */
-       "hosttbl",      /* 6 M_HTABLE */
-       "fragtbl",      /* 7 M_FTABLE */
-       "zombie",       /* 8 M_ZOMBIE */
-       "ifaddr",       /* 9 M_IFADDR */
-       "soopts",       /* 10 M_SOOPTS */
-       "soname",       /* 11 M_SONAME */
-       "namei",        /* 12 M_NAMEI */
-       "gprof",        /* 13 M_GPROF */
-       "ioctlops",     /* 14 M_IOCTLOPS */
-       "superblk",     /* 15 M_SUPERBLK */
-       "cred",         /* 16 M_CRED */
-       "pgrp",         /* 17 M_PGRP */
-       "session",      /* 18 M_SESSION */
-       "iov",          /* 19 M_IOV */
-       "mount",        /* 20 M_MOUNT */
-       "fhandle",      /* 21 M_FHANDLE */
-       "NFS req",      /* 22 M_NFSREQ */
-       "NFS mount",    /* 23 M_NFSMNT */
-       "vnodes",       /* 24 M_VNODE */
-       "namecache",    /* 25 M_CACHE */
-       "UFS quota",    /* 26 M_DQUOT */
-       "UFS mount",    /* 27 M_UFSMNT */
-       "mapmem",       /* 28 M_MAPMEM */
-       "shm",          /* 29 M_SHM */
-       0, 0, 0, 0,
-       0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0,
-       "temp",         /* 49 M_TEMP */
-};
+char *kmemnames[] = INITKMEMNAMES;
 
 
+void
 domem()
 {
 domem()
 {
-       struct kmemstats kmemstats[M_LAST];
-       struct kmembuckets buckets[MINBUCKET + 16];
        register struct kmembuckets *kp;
        register struct kmemstats *ks;
        register struct kmembuckets *kp;
        register struct kmemstats *ks;
-       int i;
+       register int i;
+       int size;
+       long totuse = 0, totfree = 0, totreq = 0;
+       struct kmemstats kmemstats[M_LAST];
+       struct kmembuckets buckets[MINBUCKET + 16];
 
 
-       lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
-       read(mf, buckets, sizeof buckets);
-       printf("Memory statistics by bucket size\n");
-       printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
+       kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
+       (void)printf("Memory statistics by bucket size\n");
+       (void)printf(
+           "    Size   In Use   Free   Requests  HighWater  Couldfree\n");
        for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
                if (kp->kb_calls == 0)
                        continue;
        for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
                if (kp->kb_calls == 0)
                        continue;
-               printf("%8d%9d%7d%11d%8d%11d\n", 1 << i, 
+               size = 1 << i;
+               (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 
                        kp->kb_total - kp->kb_totalfree,
                        kp->kb_totalfree, kp->kb_calls,
                        kp->kb_highwat, kp->kb_couldfree);
                        kp->kb_total - kp->kb_totalfree,
                        kp->kb_totalfree, kp->kb_calls,
                        kp->kb_highwat, kp->kb_couldfree);
-               
+               totfree += size * kp->kb_totalfree;
        }
        }
-       lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
-       read(mf, kmemstats, sizeof kmemstats);
-       printf("Memory statistics by type\n");
-       printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
-               "TypeLimit KernLimit");
+
+       kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
+       (void)printf("\nMemory statistics by type\n");
+       (void)printf(
+"      Type  In Use  MemUse   HighUse  Limit Requests  TypeLimit KernLimit\n");
        for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
                if (ks->ks_calls == 0)
                        continue;
        for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
                if (ks->ks_calls == 0)
                        continue;
-               printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
-                       kmemnames[i] ? kmemnames[i] : "undefined",
-                       ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
-                       (ks->ks_maxused + 1023) / 1024,
-                       (ks->ks_limit + 1023) / 1024, ks->ks_calls,
-                       ks->ks_limblocks, ks->ks_mapblocks);
+               (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n",
+                   kmemnames[i] ? kmemnames[i] : "undefined",
+                   ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
+                   (ks->ks_maxused + 1023) / 1024,
+                   (ks->ks_limit + 1023) / 1024, ks->ks_calls,
+                   ks->ks_limblocks, ks->ks_mapblocks);
+               totuse += ks->ks_memuse;
+               totreq += ks->ks_calls;
        }
        }
+       (void)printf("\nMemory Totals:  In Use    Free    Requests\n");
+       (void)printf("              %7ldK %6ldK    %8ld\n",
+            (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
 }
 
 }
 
-#define steal(where, var) \
-       lseek(mf, where, L_SET); read(mf, &var, sizeof var);
 /*
 /*
- * Read the drive names out of kmem.
+ * kread reads something from the kernel, given its nlist index.
  */
  */
-#ifdef vax
-#include <vaxuba/ubavar.h>
-#include <vaxmba/mbavar.h>
-
-read_names()
+void
+kread(nlx, addr, size)
+       int nlx;
+       void *addr;
+       size_t size;
 {
 {
-       struct mba_device mdev;
-       register struct mba_device *mp;
-       struct mba_driver mdrv;
-       short two_char;
-       char *cp = (char *) &two_char;
-       struct uba_device udev, *up;
-       struct uba_driver udrv;
-
-       mp = (struct mba_device *) nl[X_MBDINIT].n_value;
-       up = (struct uba_device *) nl[X_UBDINIT].n_value;
-       if (up == 0) {
-               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
+       char *sym;
+
+       if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) {
+               sym = nl[nlx].n_name;
+               if (*sym == '_')
+                       ++sym;
+               (void)fprintf(stderr,
+                   "vmstat: %s: symbol %s not defined\n", vmunix, sym);
                exit(1);
        }
                exit(1);
        }
-       if (mp) for (;;) {
-               steal(mp++, mdev);
-               if (mdev.mi_driver == 0)
-                       break;
-               if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
-                       continue;
-               steal(mdev.mi_driver, mdrv);
-               steal(mdrv.md_dname, two_char);
-               sprintf(dr_name[mdev.mi_dk], "%c%c%d",
-                   cp[0], cp[1], mdev.mi_unit);
-       }
-       for (;;) {
-               steal(up++, udev);
-               if (udev.ui_driver == 0)
-                       break;
-               if (udev.ui_dk < 0 || udev.ui_alive == 0)
-                       continue;
-               steal(udev.ui_driver, udrv);
-               steal(udrv.ud_dname, two_char);
-               sprintf(dr_name[udev.ui_dk], "%c%c%d",
-                   cp[0], cp[1], udev.ui_unit);
-       }
-}
-#endif
-
-#ifdef tahoe
-#include <tahoevba/vbavar.h>
-
-/*
- * Read the drive names out of kmem.
- */
-read_names()
-{
-       struct vba_device udev, *up;
-       struct vba_driver udrv;
-       short two_char;
-       char *cp = (char *)&two_char;
-
-       up = (struct vba_device *) nl[X_VBDINIT].n_value;
-       if (up == 0) {
-               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
+       if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) {
+               sym = nl[nlx].n_name;
+               if (*sym == '_')
+                       ++sym;
+               (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr());
                exit(1);
        }
                exit(1);
        }
-       for (;;) {
-               steal(up++, udev);
-               if (udev.ui_driver == 0)
-                       break;
-               if (udev.ui_dk < 0 || udev.ui_alive == 0)
-                       continue;
-               steal(udev.ui_driver, udrv);
-               steal(udrv.ud_dname, two_char);
-               sprintf(dr_name[udev.ui_dk], "%c%c%d",
-                    cp[0], cp[1], udev.ui_unit);
-       }
 }
 }
-#endif
-
-#ifdef hp300
-#include <hpdev/device.h>
-
-#define validdisk(cp)  ((cp)[1] == 'd' && ((cp)[0] == 'r' || (cp)[0] == 's'))
 
 
-read_names()
+void
+usage()
 {
 {
-       struct hp_device hdev;
-       register struct hp_device *hp;
-       struct driver hdrv;
-       short two_char;
-       char *cp = (char *) &two_char;
-       register char *dp;
-
-       hp = (struct hp_device *) nl[X_HPDINIT].n_value;
-       if (hp == 0) {
-               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
-               exit(1);
-       }
-       for (;;) {
-               steal(hp++, hdev);
-               if (hdev.hp_driver == 0)
-                       break;
-               steal(hdev.hp_driver, hdrv);
-               steal(hdrv.d_name, two_char);
-               /*
-                * hp_dk is meaningless if the device isn't a disk
-                * (d_name not valid) or the disk was not found when
-                * booting (hp_alive == 0).
-                */
-               if (!validdisk(cp) || hdev.hp_alive == 0)
-                       continue;
-               dp = dr_name[hdev.hp_dk];
-               sprintf(dp, "%c%c%d", cp[0], cp[1], hdev.hp_unit);
-       }
-}
+       (void)fprintf(stderr,
+#ifndef NEWVM
+           "usage: vmstat [-fimst] [-c count] [-M core] \
+[-N system] [-w wait] [disks]\n");
+#else
+           "usage: vmstat [-ims] [-c count] [-M core] \
+[-N system] [-w wait] [disks]\n");
 #endif
 #endif
+       exit(1);
+}