BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.sbin / iostat / iostat.c
index 98d655f..5d94dd7 100644 (file)
+/*-
+ * Copyright (c) 1986, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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
 #ifndef lint
-static char *sccsid = "@(#)iostat.c    4.17 (Berkeley) 89/05/29";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1986, 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
 
 
-/*
- * iostat
- */
-#include <sys/types.h>
-#include <sys/file.h>
+#ifndef lint
+static char sccsid[] = "@(#)iostat.c   5.9 (Berkeley) 6/27/91";
+#endif /* not lint */
+
+#include <sys/param.h>
 #include <sys/buf.h>
 #include <sys/dkstat.h>
 #include <sys/buf.h>
 #include <sys/dkstat.h>
-#include <sys/signal.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <nlist.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>
+#include <kvm.h>
 
 struct nlist nl[] = {
 
 struct nlist nl[] = {
-       { "_dk_busy" },
-#define        X_DK_BUSY       0
+#define        X_DK_TIME       0
        { "_dk_time" },
        { "_dk_time" },
-#define        X_DK_TIME       1
+#define        X_DK_XFER       1
        { "_dk_xfer" },
        { "_dk_xfer" },
-#define        X_DK_XFER       2
+#define        X_DK_WDS        2
        { "_dk_wds" },
        { "_dk_wds" },
-#define        X_DK_WDS        3
+#define        X_TK_NIN        3
        { "_tk_nin" },
        { "_tk_nin" },
-#define        X_TK_NIN        4
+#define        X_TK_NOUT       4
        { "_tk_nout" },
        { "_tk_nout" },
-#define        X_TK_NOUT       5
+#define        X_DK_SEEK       5
        { "_dk_seek" },
        { "_dk_seek" },
-#define        X_DK_SEEK       6
+#define        X_CP_TIME       6
        { "_cp_time" },
        { "_cp_time" },
-#define        X_CP_TIME       7
+#define        X_DK_WPMS       7
        { "_dk_wpms" },
        { "_dk_wpms" },
-#define        X_DK_WPMS       8
+#define        X_HZ            8
        { "_hz" },
        { "_hz" },
-#define        X_HZ            9
+#define        X_PHZ           9
        { "_phz" },
        { "_phz" },
-#define        X_PHZ           10
+#define        X_DK_NDRIVE     10
        { "_dk_ndrive" },
        { "_dk_ndrive" },
-#define        X_DK_NDRIVE     11
-#ifdef vax
-       { "_mbdinit" },
-#define X_MBDINIT      (X_DK_NDRIVE+1)
-       { "_ubdinit" },
-#define X_UBDINIT      (X_DK_NDRIVE+2)
+#define        X_END           11
+#ifdef hp300
+#define        X_HPDINIT       (X_END+1)
+       { "_hp_dinit" },
 #endif
 #ifdef tahoe
 #endif
 #ifdef tahoe
-#define        X_VBDINIT       (X_DK_NDRIVE+1)
+#define        X_VBDINIT       (X_END+1)
        { "_vbdinit" },
 #endif
        { "_vbdinit" },
 #endif
-       { 0 },
-};
-
-char   **dr_name;
-int    *dr_select;
-long   *dk_wpms;
-int    dk_ndrive;
-int    ndrives = 0;
 #ifdef vax
 #ifdef vax
-char   *defdrives[] = { "hp0", "hp1", "hp2",  0 };
-#else
-char   *defdrives[] = { 0 };
+       { "_mbdinit" },
+#define X_MBDINIT      (X_END+1)
+       { "_ubdinit" },
+#define X_UBDINIT      (X_END+2)
 #endif
 #endif
+       { NULL },
+};
 
 
-struct {
-       int     dk_busy;
+struct _disk {
        long    cp_time[CPUSTATES];
        long    *dk_time;
        long    *dk_wds;
        long    cp_time[CPUSTATES];
        long    *dk_time;
        long    *dk_wds;
@@ -73,97 +104,131 @@ struct {
        long    *dk_xfer;
        long    tk_nin;
        long    tk_nout;
        long    *dk_xfer;
        long    tk_nin;
        long    tk_nout;
-} s, s1;
+} cur, last;
+
+double etime;
+long *dk_wpms;
+int dk_ndrive, *dr_select, hz, kmemfd, ndrives;
+char **dr_name;
+
+#define nlread(x, v) \
+       kvm_read((void *)nl[x].n_value, (void *)&(v), sizeof(v))
 
 
-int    mf;
-int    hz;
-int    phz;
-double etime;
-int    tohdr = 1;
-int    printhdr();
+#include "names.c"                             /* XXX */
+
+static void cpustats __P((void)), dkstats __P((void)), phdr __P((int));
+static void usage __P((void)), err __P((const char *, ...));
 
 main(argc, argv)
 
 main(argc, argv)
-       char *argv[];
+       int argc;
+       char **argv;
 {
 {
-       extern char *ctime();
-       register  i;
-       int iter, ndrives;
-       double f1, f2;
-       long t;
-       char *arg, **cp, name[6], buf[BUFSIZ];
+       register int i;
+       long tmp;
+       int ch, hdrcnt, reps, interval, phz, ndrives;
+       char **cp, *memfile, *namelist, buf[30];
 
 
-       nlist(_PATH_UNIX, nl);
-       if(nl[X_DK_BUSY].n_type == 0) {
-               fprintf(stderr, "iostat: dk_busy not found in %s namelist\n",
-                   _PATH_UNIX);
-               exit(1);
-       }
-       mf = open(_PATH_KMEM, 0);
-       if(mf < 0) {
-               fprintf(stderr, "iostat: cannot open %s\n", _PATH_KMEM);
-               exit(1);
-       }
-       iter = 0;
-       for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
-               ;
-       if (nl[X_DK_NDRIVE].n_value == 0) {
-               printf("dk_ndrive undefined in system\n");
-               exit(1);
-       }
-       lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
-       read(mf, &dk_ndrive, sizeof (dk_ndrive));
-       if (dk_ndrive <= 0) {
-               printf("dk_ndrive %d\n", dk_ndrive);
-               exit(1);
-       }
-       dr_select = (int *)calloc(dk_ndrive, sizeof (int));
-       dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
-       dk_wpms = (long *)calloc(dk_ndrive, sizeof (long));
-#define        allocate(e, t) \
-    s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
-    s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
-       allocate(dk_time, long);
-       allocate(dk_wds, long);
-       allocate(dk_seek, long);
-       allocate(dk_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;
+       interval = reps = 0;
+       namelist = memfile = NULL;
+       while ((ch = getopt(argc, argv, "c:M:N:w:")) != EOF)
+               switch(ch) {
+               case 'c':
+                       reps = atoi(optarg);
+                       break;
+               case 'M':
+                       memfile = optarg;
+                       break;
+               case 'N':
+                       namelist = optarg;
+                       break;
+               case 'w':
+                       interval = atoi(optarg);
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (kvm_openfiles(namelist, memfile, NULL) == -1)
+               err("kvm_openfiles: %s", kvm_geterr());
+       if (kvm_nlist(nl) == -1)
+               err("kvm_nlist: %s", kvm_geterr());
+       if (nl[X_DK_NDRIVE].n_type == 0)
+               err("dk_ndrive not found in namelist");
+       (void)nlread(X_DK_NDRIVE, dk_ndrive);
+       if (dk_ndrive <= 0)
+               err("invalid dk_ndrive %d\n", dk_ndrive);
+
+       cur.dk_time = calloc(dk_ndrive, sizeof(long));
+       cur.dk_wds = calloc(dk_ndrive, sizeof(long));
+       cur.dk_seek = calloc(dk_ndrive, sizeof(long));
+       cur.dk_xfer = calloc(dk_ndrive, sizeof(long));
+       last.dk_time = calloc(dk_ndrive, sizeof(long));
+       last.dk_wds = calloc(dk_ndrive, sizeof(long));
+       last.dk_seek = calloc(dk_ndrive, sizeof(long));
+       last.dk_xfer = calloc(dk_ndrive, sizeof(long));
+       dr_select = calloc(dk_ndrive, sizeof(int));
+       dr_name = calloc(dk_ndrive, sizeof(char *));
+       dk_wpms = calloc(dk_ndrive, sizeof(long));
+
+       for (i = 0; i < dk_ndrive; i++) {
+               (void)sprintf(buf, "dk%d", i);
+               dr_name[i] = strdup(buf);
        }
        read_names();
        }
        read_names();
-       lseek(mf, (long)nl[X_HZ].n_value, L_SET);
-       read(mf, &hz, sizeof hz);
-       lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
-       read(mf, &phz, sizeof phz);
+       (void)nlread(X_HZ, hz);
+       (void)nlread(X_PHZ, phz);
        if (phz)
                hz = phz;
        if (phz)
                hz = phz;
-       lseek(mf, (long)nl[X_DK_WPMS].n_value, L_SET);
-       read(mf, dk_wpms, dk_ndrive*sizeof (dk_wpms));
+       (void)kvm_read((void *)nl[X_DK_WPMS].n_value, dk_wpms,
+               dk_ndrive * sizeof(dk_wpms));
+
        /*
        /*
-        * 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 and default drives.  If everything isn't
+        * filled in and there are drives not taken care of, display the first
+        * few that fit.
+        *
+        * The backward compatibility #ifdefs permit the syntax:
+        *      iostat [ drives ] [ interval [ count ] ]
         */
         */
-       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;
                }
                }
-               argc--, argv++;
        }
        }
+#ifdef BACKWARD_COMPATIBILITY
+       if (*argv) {
+               interval = atoi(*argv);
+               if (*++argv)
+                       reps = atoi(*argv);
+       }
+#endif
+
+       if (interval) {
+               if (!reps)
+                       reps = -1;
+       } else
+               if (reps)
+                       interval = 1;
+
        for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
                if (dr_select[i] || dk_wpms[i] == 0)
                        continue;
                for (cp = defdrives; *cp; cp++)
                        if (strcmp(dr_name[i], *cp) == 0) {
                                dr_select[i] = 1;
        for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
                if (dr_select[i] || dk_wpms[i] == 0)
                        continue;
                for (cp = defdrives; *cp; cp++)
                        if (strcmp(dr_name[i], *cp) == 0) {
                                dr_select[i] = 1;
-                               ndrives++;
+                               ++ndrives;
                                break;
                        }
        }
                                break;
                        }
        }
@@ -171,191 +236,162 @@ main(argc, argv)
                if (dr_select[i])
                        continue;
                dr_select[i] = 1;
                if (dr_select[i])
                        continue;
                dr_select[i] = 1;
-               ndrives++;
-       }
-       if (argc > 1)
-               iter = atoi(argv[1]);
-       signal(SIGCONT, printhdr);
-loop:
-       if (--tohdr == 0)
-               printhdr();
-       lseek(mf, (long)nl[X_DK_BUSY].n_value, L_SET);
-       read(mf, &s.dk_busy, sizeof s.dk_busy);
-       lseek(mf, (long)nl[X_DK_TIME].n_value, L_SET);
-       read(mf, s.dk_time, dk_ndrive*sizeof (long));
-       lseek(mf, (long)nl[X_DK_XFER].n_value, L_SET);
-       read(mf, s.dk_xfer, dk_ndrive*sizeof (long));
-       lseek(mf, (long)nl[X_DK_WDS].n_value, L_SET);
-       read(mf, s.dk_wds, dk_ndrive*sizeof (long));
-       lseek(mf, (long)nl[X_DK_SEEK].n_value, L_SET);
-       read(mf, s.dk_seek, dk_ndrive*sizeof (long));
-       lseek(mf, (long)nl[X_TK_NIN].n_value, L_SET);
-       read(mf, &s.tk_nin, sizeof s.tk_nin);
-       lseek(mf, (long)nl[X_TK_NOUT].n_value, L_SET);
-       read(mf, &s.tk_nout, sizeof s.tk_nout);
-       lseek(mf, (long)nl[X_CP_TIME].n_value, L_SET);
-       read(mf, s.cp_time, sizeof s.cp_time);
-       for (i = 0; i < dk_ndrive; i++) {
-               if (!dr_select[i])
-                       continue;
-#define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
-               X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
-       }
-       t = s.tk_nin; s.tk_nin -= s1.tk_nin; s1.tk_nin = t;
-       t = s.tk_nout; s.tk_nout -= s1.tk_nout; s1.tk_nout = t;
-       etime = 0;
-       for(i=0; i<CPUSTATES; i++) {
-               X(cp_time);
-               etime += s.cp_time[i];
+               ++ndrives;
        }
        }
-       if (etime == 0.0)
-               etime = 1.0;
-       etime /= (float) hz;
-       printf("%4.0f%5.0f", s.tk_nin/etime, s.tk_nout/etime);
-       for (i=0; i<dk_ndrive; i++)
-               if (dr_select[i])
-                       stats(i);
-       for (i=0; i<CPUSTATES; i++)
-               stat1(i);
-       printf("\n");
-       fflush(stdout);
-contin:
-       if (--iter && argc > 0) {
-               sleep(atoi(argv[0]));
-               goto loop;
+
+       (void)signal(SIGCONT, phdr);
+
+       for (hdrcnt = 1;;) {
+               if (!--hdrcnt) {
+                       phdr(0);
+                       hdrcnt = 20;
+               }
+               (void)kvm_read((void *)nl[X_DK_TIME].n_value,
+                   cur.dk_time, dk_ndrive * sizeof(long));
+               (void)kvm_read((void *)nl[X_DK_XFER].n_value,
+                   cur.dk_xfer, dk_ndrive * sizeof(long));
+               (void)kvm_read((void *)nl[X_DK_WDS].n_value,
+                   cur.dk_wds, dk_ndrive * sizeof(long));
+               (void)kvm_read((void *)nl[X_DK_SEEK].n_value,
+                   cur.dk_seek, dk_ndrive * sizeof(long));
+               (void)kvm_read((void *)nl[X_TK_NIN].n_value,
+                   &cur.tk_nin, sizeof(cur.tk_nin));
+               (void)kvm_read((void *)nl[X_TK_NOUT].n_value,
+                   &cur.tk_nout, sizeof(cur.tk_nout));
+               (void)kvm_read((void *)nl[X_CP_TIME].n_value,
+                   cur.cp_time, sizeof(cur.cp_time));
+               for (i = 0; i < dk_ndrive; i++) {
+                       if (!dr_select[i])
+                               continue;
+#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp
+                       X(dk_xfer);
+                       X(dk_seek);
+                       X(dk_wds);
+                       X(dk_time);
+               }
+               tmp = cur.tk_nin;
+               cur.tk_nin -= last.tk_nin;
+               last.tk_nin = tmp;
+               tmp = cur.tk_nout;
+               cur.tk_nout -= last.tk_nout;
+               last.tk_nout = tmp;
+               etime = 0;
+               for (i = 0; i < CPUSTATES; i++) {
+                       X(cp_time);
+                       etime += cur.cp_time[i];
+               }
+               if (etime == 0.0)
+                       etime = 1.0;
+               etime /= (float)hz;
+               (void)printf("%4.0f%5.0f",
+                   cur.tk_nin / etime, cur.tk_nout / etime);
+               dkstats();
+               cpustats();
+               (void)printf("\n");
+               (void)fflush(stdout);
+
+               if (reps >= 0 && --reps <= 0)
+                       break;
+               (void)sleep(interval);
        }
        }
+       exit(0);
 }
 
 }
 
-printhdr()
+/* ARGUSED */
+void
+phdr(notused)
+       int notused;
 {
        register int i;
 
 {
        register int i;
 
-       printf("      tty");
+       (void)printf("      tty");
        for (i = 0; i < dk_ndrive; i++)
                if (dr_select[i])
        for (i = 0; i < dk_ndrive; i++)
                if (dr_select[i])
-                       printf("          %3.3s ", dr_name[i]);
-       printf("         cpu\n");
-       printf(" tin tout");
+                       (void)printf("          %3.3s ", dr_name[i]);
+       (void)printf("         cpu\n tin tout");
        for (i = 0; i < dk_ndrive; i++)
                if (dr_select[i])
        for (i = 0; i < dk_ndrive; i++)
                if (dr_select[i])
-                       printf(" bps tps msps ");
-       printf(" us ni sy id\n");
-       tohdr = 19;
+                       (void)printf(" sps tps msps ");
+       (void)printf(" us ni sy id\n");
 }
 
 }
 
-stats(dn)
+void
+dkstats()
 {
 {
-       register i;
-       double atime, words, xtime, itime;
+       register int dn;
+       double atime, itime, msps, words, xtime;
+
+       for (dn = 0; dn < dk_ndrive; ++dn) {
+               if (!dr_select[dn])
+                       continue;
+               words = cur.dk_wds[dn] * 32;            /* words xfer'd */
+               (void)printf("%4.0f",                   /* sectors */
+                   words / (DEV_BSIZE / 2) / etime);
+
+               (void)printf("%4.0f", cur.dk_xfer[dn] / etime);
 
 
-       if (dk_wpms[dn] == 0) {
-               printf("%4.0f%4.0f%5.1f ", 0.0, 0.0, 0.0);
-               return;
+               if (dk_wpms[dn] && cur.dk_xfer[dn]) {
+                       atime = cur.dk_time[dn];        /* ticks disk busy */
+                       atime /= (float)hz;             /* ticks to seconds */
+                       xtime = words / dk_wpms[dn];    /* transfer time */
+                       itime = atime - xtime;          /* time not xfer'ing */
+                       if (itime < 0)
+                               msps = 0;
+                       else 
+                               msps = itime * 1000 / cur.dk_xfer[dn];
+               } else
+                       msps = 0;
+               (void)printf("%5.1f ", msps);
        }
        }
-       atime = s.dk_time[dn];
-       atime /= (float) hz;
-       words = s.dk_wds[dn]*32.0;      /* number of words transferred */
-       xtime = words/dk_wpms[dn];      /* transfer time */
-       itime = atime - xtime;          /* time not transferring */
-       if (xtime < 0)
-               itime += xtime, xtime = 0;
-       if (itime < 0)
-               xtime += itime, itime = 0;
-       printf("%4.0f", words/512/etime);
-       printf("%4.0f", s.dk_xfer[dn]/etime);
-       printf("%5.1f ",
-           s.dk_seek[dn] ? itime*1000./s.dk_seek[dn] : 0.0);
 }
 
 }
 
-stat1(o)
+void
+cpustats()
 {
 {
-       register i;
+       register int state;
        double time;
 
        time = 0;
        double time;
 
        time = 0;
-       for(i=0; i<CPUSTATES; i++)
-               time += s.cp_time[i];
-       if (time == 0.0)
-               time = 1.0;
-       printf("%3.0f", 100.*s.cp_time[o]/time);
+       for (state = 0; state < CPUSTATES; ++state)
+               time += cur.cp_time[state];
+       for (state = 0; state < CPUSTATES; ++state)
+               (void)printf("%3.0f",
+                   100. * cur.cp_time[state] / (time ? time : 1));
 }
 
 }
 
-#define steal(where, var) \
-    lseek(mf, where, L_SET); read(mf, &var, sizeof var);
-
-#ifdef vax
-#include <vaxuba/ubavar.h>
-#include <vaxmba/mbavar.h>
-
-read_names()
+void
+usage()
 {
 {
-       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, "iostat: Disk init info not in namelist\n");
-               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);
-       }
-       if (up) 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);
-       }
+       (void)fprintf(stderr,
+"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n");
+       exit(1);
 }
 }
-#endif
 
 
-#ifdef tahoe
-#include <tahoevba/vbavar.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
 
 
-/*
- * Read the drive names out of kmem.
- */
-read_names()
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
 {
 {
-       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");
-               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);
-       }
-}
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
 #endif
 #endif
+       (void)fprintf(stderr, "iostat: ");
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, "\n");
+       exit(1);
+       /* NOTREACHED */
+}