bin/119705: [PATCH] make iostat a bit smarter about the number of tty rows

Giorgos Keramidas keramida at FreeBSD.org
Wed Jan 16 03:00:04 UTC 2008


>Number:         119705
>Category:       bin
>Synopsis:       [PATCH] make iostat a bit smarter about the number of tty rows
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 16 03:00:03 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Giorgos Keramidas
>Release:        FreeBSD 8.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD kobe 8.0-CURRENT FreeBSD 8.0-CURRENT #0: \
Tue Jan 15 21:10:19 EET 2008 build at kobe:/home/build/obj/home/build/src/sys/KOBE i386

>Description:

The current iostat(8) utility repeats the header line every 20 lines,
and this number is hardcoded in the source of iostat.  This means that
with very short xterm windows, iostat may not display one header per
terminal, and when the window size changes, it doesn't detect this and
update its internal row count.

The attached patch modifies iostat() to trap SIGWINCH, and use it to
update its internal 'max rows' limit of output lines.  It also forces
a new header to be prepended to the output on every SIGWINCH, and it
changes the hardcoded '20' lines of output to 'wrows - 3' (two rows
are needed for the header itself, and one for the cursor below the last
output line of each screenful).

>How-To-Repeat:

Resize an xterm window to 80x10 lines, and watch the output of iostat
for a while, using:

	% iostat 1

>Fix:

--- iostat-rows.patch begins here ---
diff -r d03d5ae8b3ef -r 21be4228379f usr.sbin/iostat/iostat.c
--- a/usr.sbin/iostat/iostat.c	Tue Jan 15 15:04:40 2008 +0000
+++ b/usr.sbin/iostat/iostat.c	Wed Jan 16 04:50:48 2008 +0200
@@ -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>
@@ -136,12 +137,16 @@ struct device_selection *dev_select;
 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);
@@ -425,8 +430,9 @@ main(int argc, char **argv)
 	 * print out the header again.
 	 */
 	(void)signal(SIGCONT, needhdr);
+	(void)signal(SIGWINCH, needresize);
 
-	for (headercount = 1;;) {
+	for (wresized = 1, headercount = 1;;) {
 		struct devinfo *tmp_dinfo;
 		long tmp;
 		long double etime;
@@ -451,7 +457,9 @@ main(int argc, char **argv)
 
 		if (!--headercount) {
 			phdr();
-			headercount = 20;
+			if (wresized != 0)
+				doresize();
+			headercount = wrows - 3;
 		}
 
 		tmp_dinfo = last.dinfo;
@@ -493,7 +501,9 @@ main(int argc, char **argv)
 				break;
 			case 1:
 				phdr();
-				headercount = 20;
+				if (wresized != 0)
+					doresize();
+				headercount = wrows - 3;
 				break;
 			default:
 				break;
@@ -528,7 +538,9 @@ main(int argc, char **argv)
 				break;
 			case 1:
 				phdr();
-				headercount = 20;
+				if (wresized != 0)
+					doresize();
+				headercount = wrows - 3;
 				break;
 			default:
 				break;
@@ -587,6 +599,45 @@ 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 fd, status;
+	struct winsize w;
+
+	fd = fileno(stdout);
+	if (isatty(fd) == 0) {
+		wrows = 20;			/* Traditional default. */
+		return;
+	}
+
+	for (;;) {
+		status = ioctl(fd, TIOCGWINSZ, &w);
+		if (status == -1 && errno == EINTR)
+			continue;
+		else if (status == -1)
+			err(1, "ioctl");
+		wrows = w.ws_row;
+		break;
+	}
 }
 
 static void
--- iostat-rows.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list