summaryrefslogtreecommitdiffstats
path: root/usr.sbin/iostat
diff options
context:
space:
mode:
authorkeramida <keramida@FreeBSD.org>2008-01-22 11:18:51 +0000
committerkeramida <keramida@FreeBSD.org>2008-01-22 11:18:51 +0000
commiteab3a8645ad6c5298a54a142684a90d7198a2345 (patch)
tree3310323b710a5c961c1cc1fc3ed01debdaa1eca3 /usr.sbin/iostat
parentfbb57a45f0382a1e48f07b11446be7fff8c234e6 (diff)
downloadFreeBSD-src-eab3a8645ad6c5298a54a142684a90d7198a2345.zip
FreeBSD-src-eab3a8645ad6c5298a54a142684a90d7198a2345.tar.gz
Repeat iostat header after rows-3 instead of a hardcoded 20.
Use ioctl() to get the window size in iostat(8), and force a new header to be prepended to the output every time the current window size changes. Change the number of lines before each header to `rows - 3' when the terminal is resized, so that the full terminal length can be used for output lines. PR: bin/119705 Submitted by: keramida Approved by: maxim MFC after: 2 weeks
Diffstat (limited to 'usr.sbin/iostat')
-rw-r--r--usr.sbin/iostat/iostat.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c
index 43d297e..f1a0556 100644
--- a/usr.sbin/iostat/iostat.c
+++ b/usr.sbin/iostat/iostat.c
@@ -113,6 +113,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
#include <limits.h>
#include <devstat.h>
@@ -131,17 +132,23 @@ struct nlist namelist[] = {
{ NULL },
};
+#define IOSTAT_DEFAULT_ROWS 20 /* Traditional default `wrows' */
+
struct statinfo cur, last;
int num_devices;
struct device_selection *dev_select;
int maxshowdevs;
volatile sig_atomic_t headercount;
+volatile sig_atomic_t wresized; /* Tty resized, when non-zero. */
+unsigned short wrows; /* Current number of tty rows. */
int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0;
int xflag = 0, zflag = 0;
/* local function declarations */
static void usage(void);
static void needhdr(int signo);
+static void needresize(int signo);
+static void doresize(void);
static void phdr(void);
static void devstats(int perf_select, long double etime, int havelast);
static void cpustats(void);
@@ -426,6 +433,20 @@ main(int argc, char **argv)
*/
(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;
+ wrows = IOSTAT_DEFAULT_ROWS;
+ }
+
for (headercount = 1;;) {
struct devinfo *tmp_dinfo;
long tmp;
@@ -451,7 +472,9 @@ main(int argc, char **argv)
if (!--headercount) {
phdr();
- headercount = 20;
+ if (wresized != 0)
+ doresize();
+ headercount = wrows;
}
tmp_dinfo = last.dinfo;
@@ -493,7 +516,9 @@ main(int argc, char **argv)
break;
case 1:
phdr();
- headercount = 20;
+ if (wresized != 0)
+ doresize();
+ headercount = wrows;
break;
default:
break;
@@ -528,7 +553,9 @@ main(int argc, char **argv)
break;
case 1:
phdr();
- headercount = 20;
+ if (wresized != 0)
+ doresize();
+ headercount = wrows;
break;
default:
break;
@@ -589,6 +616,47 @@ needhdr(int signo)
headercount = 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;
+ headercount = 1;
+}
+
+/*
+ * Update the global `wrows' 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)
+ wrows = w.ws_row - 3;
+ else
+ wrows = IOSTAT_DEFAULT_ROWS;
+ break;
+ }
+
+ /*
+ * Inhibit doresize() calls until we are rescheduled by SIGWINCH.
+ */
+ wresized = 0;
+}
+
static void
phdr(void)
{
OpenPOWER on IntegriCloud