/*
* Copyright (c) 1996 John M. Vinopal
* 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 for the NetBSD Project
* by John M. Vinopal.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*-
* Copyright (c) 1986, 1991, 1993
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1986, 1991, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
/*
* Decide how many screen columns each output statistic is given
* (these are determined empirically ("looks good to me") and likely
* will require changes from time to time as technology advances).
*
* The odd "+ N" at the end of the summary (total width of stat) definition
* allows for the gaps between the columns, and is (#data cols - 1).
* So, tty stats have "in" and "out", 2 columns, so there is 1 extra space,
* whereas the cpu stats have 5 columns, so 4 extra spaces (etc).
*/
#define LAYOUT_TTY_IN 4 /* tty input in last interval */
#define LAYOUT_TTY_TIN 7 /* tty input forever */
#define LAYOUT_TTY_OUT 5 /* tty output in last interval */
#define LAYOUT_TTY_TOUT 10 /* tty output forever */
#define LAYOUT_TTY (((todo & SHOW_TOTALS) \
? (LAYOUT_TTY_TIN + LAYOUT_TTY_TOUT) \
: (LAYOUT_TTY_IN + LAYOUT_TTY_OUT)) + 1)
#define LAYOUT_TTY_GAP 0 /* always starts at left margin */
int
main(int argc, char *argv[])
{
int ch, hdrcnt, hdroffset, ndrives, lines;
struct timespec tv;
struct ttysize ts;
long width = -1, height = -1;
char *ep;
#if 0 /* -i and -u are not currently (sanely) implementable */
while ((ch = getopt(argc, argv, "Cc:dDH:iITuw:W:xXyz")) != -1)
#else
while ((ch = getopt(argc, argv, "Cc:dDH:ITw:W:xXyz")) != -1)
#endif
switch (ch) {
case 'c':
if ((reps = atoi(optarg)) <= 0)
errx(1, "repetition count <= 0.");
break;
case 'C':
todo |= SHOW_CPU;
break;
case 'd':
todo &= ~SHOW_STATS_ALL;
todo |= SHOW_STATS_1;
break;
case 'D':
todo &= ~SHOW_STATS_ALL;
todo |= SHOW_STATS_2;
break;
case 'H':
height = strtol(optarg, &ep, 10);
if (height < 0 || *ep != '\0')
errx(1, "bad height (-H) value.");
height += 2; /* magic, but needed to be sane */
break;
#if 0
case 'i':
todo |= SHOW_TOTALS | SHOW_NEW_TOTALS;
break;
#endif
case 'I':
todo |= SHOW_TOTALS;
break;
case 'T':
todo |= SHOW_TTY;
break;
#if 0
case 'u':
todo |= SHOW_UPDATES;
break;
#endif
case 'w':
if ((interval = atoi(optarg)) <= 0)
errx(1, "interval <= 0.");
break;
case 'W':
width = strtol(optarg, &ep, 10);
if (width < 0 || *ep != '\0')
errx(1, "bad width (-W) value.");
break;
case 'x':
todo &= ~SHOW_STATS_ALL;
todo |= SHOW_STATS_X;
break;
case 'X':
todo &= ~SHOW_STATS_ALL;
todo |= SHOW_STATS_3;
break;
case 'y':
todo &= ~SHOW_STATS_ALL;
todo |= SHOW_STATS_Y;
break;
case 'z':
todo |= SUPPRESS_ZERO;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (!ISSET(todo, SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL))
todo |= SHOW_CPU | SHOW_TTY | SHOW_STATS_1;
if (ISSET(todo, SHOW_STATS_X)) {
todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL);
todo |= SHOW_STATS_X;
}
if (ISSET(todo, SHOW_STATS_3)) {
todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL);
todo |= SHOW_STATS_3;
}
if (ISSET(todo, SHOW_STATS_Y)) {
todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL | SHOW_TOTALS);
todo |= SHOW_STATS_Y;
}
if (ioctl(STDOUT_FILENO, TIOCGSIZE, &ts) != -1) {
if (ts.ts_lines)
winlines = ts.ts_lines;
if (ts.ts_cols)
wincols = ts.ts_cols;
}
drvinit(0);
cpureadstats();
drvreadstats();
ordersize = 0;
ndrives = selectdrives(argc, argv, 1);
if (ndrives == 0) {
/* No drives are selected. No need to show drive stats. */
todo &= ~SHOW_STATS_ALL;
if (todo == 0)
errx(1, "no drives");
}
tv.tv_sec = interval;
tv.tv_nsec = 0;
/* print a new header on sigcont */
(void)signal(SIGCONT, sig_header);
do_header = 1;
if (ISSET(todo, SHOW_STATS_1)) {
drive_stats(ndrives, etime);
}
if (ISSET(todo, SHOW_STATS_2) || ISSET(todo, SHOW_STATS_3)) {
drive_stats2(ndrives, etime);
}
if (ISSET(todo, SHOW_CPU))
cpustats();
(void)printf("\n");
out:
(void)fflush(stdout);
}
static int
selectdrives(int argc, char *argv[], int first)
{
int i, maxdrives, ndrives, tried;
/*
* 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 ] ]
*/
#define BACKWARD_COMPATIBILITY
for (tried = ndrives = 0; *argv; ++argv) {
#ifdef BACKWARD_COMPATIBILITY
if (isdigit((unsigned char)**argv))
break;
#endif
tried++;
for (i = 0; i < (int)ndrive; i++) {
if (fnmatch(*argv, cur.name[i], 0))
continue;
cur.select[i] = 1;
if (ordersize <= ndrives) {
int *new = realloc(order,
(ordersize + 8) * sizeof *order);
if (new == NULL)
break;
ordersize += 8;
order = new;
}
order[ndrives++] = i;
}
}
if (ndrives == 0 && tried == 0) {
/*
* Pick up to defdrives (or all if -x is given) drives
* if none specified.
*/
maxdrives = (ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y) ||
(int)ndrive < defdrives)
? (int)(ndrive) : defdrives;
ordersize = maxdrives;
free(order);
order = calloc(ordersize, sizeof *order);
if (order == NULL)
errx(1, "Insufficient memory");
for (i = 0; i < maxdrives; i++) {
cur.select[i] = 1;
order[i] = i;