Date: Wed, 16 Jan 2008 07:40:04 GMT From: Giorgos Keramidas <keramida@FreeBSD.org> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/119705: [PATCH] make iostat a bit smarter about the number of tty rows Message-ID: <200801160740.m0G7e4JL087071@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/119705; it has been noted by GNATS. From: Giorgos Keramidas <keramida@freebsd.org> To: Maxim Konovalov <maxim@macomnet.ru> Cc: Bruce Evans <bde@freebsd.org>, bug-followup@freebsd.org Subject: Re: bin/119705: [PATCH] make iostat a bit smarter about the number of tty rows Date: Wed, 16 Jan 2008 09:39:37 +0200 On 2008-01-16 09:13, Giorgos Keramidas <keramida@freebsd.org> wrote: > On 2008-01-16 09:29, Maxim Konovalov <maxim@macomnet.ru> wrote: > > Hi Giorgos, > > It seems for me you forget to clear wresized flag -- I added > > printf("%s\n", __func__); at the beginning of doresize() to notice > > this. > > Indeed. Thanks for catching this. > > > IMHO the isatty() check doesn't belong to a pseudo signal handler > > doresize(). Install SIGWINCH handler if and only if stdout is a tty. > > That's a good suggestion too, and it will save one isatty() call for > each SIGWINCH delivery. I'll update the patch and follow-up with a > second version in the PR. Nice... Both fixed, I think. The new version of the patch is attached below, after the following changes: iostat-rows: fix a couple of nits reported by maxim * Reset wresized when doresize() completes its work * Only call isatty(fileno(stdout)) once, instead of every time doresize() is called * Only install a SIGWINCH handler if isatty() is true While here, also fix another potential problem, when a terminal has 3 rows or less. Instead of blindly subtracting 3 from w.ws_row and ending up with a negative wrows value, default to 20 in that case. Since the traditional value of 20 rows is now used in two places with this change, #define it as IOSTAT_DEFAULT_ROWS, to avoid repeating a magic number multiple times. %%% diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c --- 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 { + wrows = IOSTAT_DEFAULT_ROWS; + return; + } + 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; @@ -587,6 +614,48 @@ 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; + + printf("wresized = %d\n", wresized); + 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 %%%
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801160740.m0G7e4JL087071>