summaryrefslogtreecommitdiffstats
path: root/usr.bin/vmstat
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/vmstat')
-rw-r--r--usr.bin/vmstat/vmstat.c78
1 files changed, 69 insertions, 9 deletions
diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c
index 44b199ab..1aa440a 100644
--- a/usr.bin/vmstat/vmstat.c
+++ b/usr.bin/vmstat/vmstat.c
@@ -133,7 +133,10 @@ static devstat_select_mode select_mode;
static struct vmmeter sum, osum;
-static int winlines = 20;
+#define VMSTAT_DEFAULT_LINES 20 /* Default number of `winlines'. */
+volatile sig_atomic_t wresized; /* Tty resized, when non-zero. */
+static int winlines = VMSTAT_DEFAULT_LINES; /* Current number of tty rows. */
+
static int aflag;
static int nflag;
static int Pflag;
@@ -162,6 +165,8 @@ static void kread(int, void *, size_t);
static void kreado(int, void *, size_t, size_t);
static char *kgetstr(const char *);
static void needhdr(int);
+static void needresize(int);
+static void doresize(void);
static void printhdr(int, u_long);
static void usage(void);
@@ -277,8 +282,6 @@ main(int argc, char *argv[])
errx(1, "Cannot use -P with crash dumps");
if (todo & VMSTAT) {
- struct winsize winsize;
-
/*
* Make sure that the userland devstat version matches the
* kernel devstat version. If not, exit and print a
@@ -289,11 +292,6 @@ main(int argc, char *argv[])
argv = getdrivedata(argv);
- winsize.ws_row = 0;
- (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
- if (winsize.ws_row > 0)
- winlines = winsize.ws_row;
-
}
#define BACKWARD_COMPATIBILITY
@@ -578,8 +576,27 @@ dovmstat(unsigned int interval, int reps)
uptime = getuptime();
halfuptime = uptime / 2;
+
+ /*
+ * If the user stops the program (control-Z) and then resumes it,
+ * print out the header again.
+ */
(void)signal(SIGCONT, needhdr);
+ /*
+ * If our standard output is a tty, then install a SIGWINCH handler
+ * and set wresized so that our first iteration through the main
+ * iostat loop will peek at the terminal's current rows to find out
+ * how many lines can fit in a screenful of output.
+ */
+ if (isatty(fileno(stdout)) != 0) {
+ wresized = 1;
+ (void)signal(SIGWINCH, needresize);
+ } else {
+ wresized = 0;
+ winlines = VMSTAT_DEFAULT_LINES;
+ }
+
if (kd != NULL) {
if (namelist[X_STATHZ].n_type != 0 &&
namelist[X_STATHZ].n_value != 0)
@@ -758,7 +775,9 @@ printhdr(int ncpus, u_long cpumask)
printf("\n");
} else
printf(" us sy id\n");
- hdrcnt = winlines - 2;
+ if (wresized != 0)
+ doresize();
+ hdrcnt = winlines;
}
/*
@@ -771,6 +790,47 @@ needhdr(int dummy __unused)
hdrcnt = 1;
}
+/*
+ * When the terminal is resized, force an update of the maximum number of rows
+ * printed between each header repetition. Then force a new header to be
+ * prepended to the next output.
+ */
+void
+needresize(int signo)
+{
+
+ wresized = 1;
+ hdrcnt = 1;
+}
+
+/*
+ * Update the global `winlines' count of terminal rows.
+ */
+void
+doresize(void)
+{
+ int status;
+ struct winsize w;
+
+ for (;;) {
+ status = ioctl(fileno(stdout), TIOCGWINSZ, &w);
+ if (status == -1 && errno == EINTR)
+ continue;
+ else if (status == -1)
+ err(1, "ioctl");
+ if (w.ws_row > 3)
+ winlines = w.ws_row - 3;
+ else
+ winlines = VMSTAT_DEFAULT_LINES;
+ break;
+ }
+
+ /*
+ * Inhibit doresize() calls until we are rescheduled by SIGWINCH.
+ */
+ wresized = 0;
+}
+
#ifdef notyet
static void
dotimes(void)
OpenPOWER on IntegriCloud