From b2bfd76b06efc8c8b2a9d4b2d7d20c19b50a6fb4 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Tue, 17 Jan 2023 20:45:48 +1100 Subject: [PATCH] watch: add -r to not rexec on terminal resize If you have the watched program doing some other thing every time its run and you resize the window, you might get unexpected results. The -r option lets you run only when the interval has expired. References: procps-ng/procps!125 procps-ng/procps#190 --- NEWS | 1 + man/watch.1 | 50 ++++++++++++++++++++++++++++---------------------- src/watch.c | 40 +++++++++++++++++++++++++++------------- 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/NEWS b/NEWS index bb664d9a..c319ad53 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ procps-ng-NEXT * vmstat: Referesh memory statistics Debian #1027963 * w: Add --pids option merge #159 * watch: Pass through beep issue #104 + * watch: -r option to not re-exec on SIGWINCH merge #125 procps-ng-4.0.2 --------------- diff --git a/man/watch.1 b/man/watch.1 index d130ef75..2007e4fd 100644 --- a/man/watch.1 +++ b/man/watch.1 @@ -1,4 +1,4 @@ -.TH WATCH 1 "2023-01-16" "procps-ng" "User Commands" +.TH WATCH 1 "2023-01-17" "procps-ng" "User Commands" .SH NAME watch \- execute a program periodically, showing output fullscreen .SH SYNOPSIS @@ -13,12 +13,26 @@ allows you to watch the program output change over time. By default, \fIcommand\fR is run every 2 seconds and \fBwatch\fR will run until interrupted. .SH OPTIONS .TP +\fB\-b\fR, \fB\-\-beep\fR +Beep if command has a non-zero exit. +.TP +\fB\-c\fR, \fB\-\-color\fR +Interpret ANSI color and style sequences. +.TP \fB\-d\fR, \fB\-\-differences\fR[=\fIpermanent\fR] Highlight the differences between successive updates. If the optional \fIpermanent\fR argument is specified then .B watch will show all changes since the first iteration. .TP +\fB\-e\fR, \fB\-\-errexit\fR +Freeze updates on command error, and exit after a key press. +.TP +\fB\-g\fR, \fB\-\-chgexit\fR +Exit when the output of +.I command +changes. +.TP \fB\-n\fR, \fB\-\-interval\fR \fIseconds\fR Specify update interval. The command will not allow quicker than 0.1 second interval, in which the smaller values are converted. Both '.' and ',' work @@ -38,28 +52,21 @@ Try it with (if present) and notice how the fractional seconds stays (nearly) the same, as opposed to normal mode where they continuously increase. .TP -\fB\-t\fR, \fB\-\-no\-title\fR -Turn off the header showing the interval, command, and current time at the -top of the display, as well as the following blank line. -.TP -\fB\-b\fR, \fB\-\-beep\fR -Beep if command has a non-zero exit. -.TP -\fB\-e\fR, \fB\-\-errexit\fR -Freeze updates on command error, and exit after a key press. -.TP -\fB\-g\fR, \fB\-\-chgexit\fR -Exit when the output of -.I command -changes. -.TP \fB\-q\fR, \fB\-\-equexit\fR Exit when output of .I command does not change for the given number of cycles. .TP -\fB\-c\fR, \fB\-\-color\fR -Interpret ANSI color and style sequences. +\fB\-r\fR, \fB\-\-no-rerun\fR +Do not run the program on terminal resize, the output of the program will re-appear at the next +regular run time. +.TP +\fB\-t\fR, \fB\-\-no\-title\fR +Turn off the header showing the interval, command, and current time at the +top of the display, as well as the following blank line. +.TP +\fB\-w\fR, \fB\-\-no\-wrap\fR +Turn off line wrapping. Long lines will be truncated instead of wrapped to the next line. .TP \fB\-x\fR, \fB\-\-exec\fR Pass @@ -70,9 +77,6 @@ instead of .B sh \-c which reduces the need to use extra quoting to get the desired effect. .TP -\fB\-w\fR, \fB\-\-no\-wrap\fR -Turn off line wrapping. Long lines will be truncated instead of wrapped to the next line. -.TP \fB\-h\fR, \fB\-\-help\fR Display help text and exit. .TP @@ -134,7 +138,9 @@ itself. Upon terminal resize, the screen will not be correctly repainted until the next scheduled update. All .B \-\-differences -highlighting is lost on that update as well. +highlighting is lost on that update as well. When using the +.B \-\-no\-rerun +option, no output of will be visible. Non-printing characters are stripped from program output. Use \fBcat -v\fR as part of the command pipeline if you want to see them. diff --git a/src/watch.c b/src/watch.c index c65f69b8..b7ad005a 100644 --- a/src/watch.c +++ b/src/watch.c @@ -72,6 +72,7 @@ static int flags; #define WATCH_ERREXIT (1 << 6) #define WATCH_CHGEXIT (1 << 7) #define WATCH_EQUEXIT (1 << 8) +#define WATCH_NORERUN (1 << 9) static int curses_started = 0; static long height = 24, width = 80; @@ -101,6 +102,7 @@ static void __attribute__ ((__noreturn__)) " exit when output from command does not change\n"), out); fputs(_(" -n, --interval seconds to wait between updates\n"), out); fputs(_(" -p, --precise attempt run command in precise intervals\n"), out); + fputs(_(" -r, --no-rerun do not rerun program on window resize\n"), out); fputs(_(" -t, --no-title turn off header\n"), out); fputs(_(" -w, --no-wrap turn off line wrapping\n"), out); fputs(_(" -x, --exec pass command to exec instead of \"sh -c\"\n"), out); @@ -814,6 +816,7 @@ int main(int argc, char *argv[]) char *command; char **command_argv; int command_length = 0; /* not including final \0 */ + watch_usec_t last_run = 0; watch_usec_t next_loop; /* next loop time in us, used for precise time * keeping only */ #ifdef WITH_WATCH8BIT @@ -832,6 +835,7 @@ int main(int argc, char *argv[]) {"equexit", required_argument, 0, 'q'}, {"exec", no_argument, 0, 'x'}, {"precise", no_argument, 0, 'p'}, + {"no-rerun", no_argument, 0, 'r'}, {"no-title", no_argument, 0, 't'}, {"no-wrap", no_argument, 0, 'w'}, {"version", no_argument, 0, 'v'}, @@ -851,7 +855,7 @@ int main(int argc, char *argv[]) interval = strtod_nol_or_err(interval_string, _("Could not parse interval from WATCH_INTERVAL")); while ((optc = - getopt_long(argc, argv, "+bced::ghq:n:pvtwx", longopts, (int *)0)) + getopt_long(argc, argv, "+bced::ghq:n:prtwvx", longopts, (int *)0)) != EOF) { switch (optc) { case 'b': @@ -875,6 +879,9 @@ int main(int argc, char *argv[]) flags |= WATCH_EQUEXIT; max_cycles = strtod_nol_or_err(optarg, _("failed to parse argument")); break; + case 'r': + flags |= WATCH_NORERUN; + break; case 't': show_title = 0; break; @@ -990,18 +997,25 @@ int main(int argc, char *argv[]) output_header(command, interval); #endif /* WITH_WATCH8BIT */ - int exit = run_command(command, command_argv); - if (flags & WATCH_EQUEXIT) { - if (cycle_count == max_cycles && exit) { - break; - } else if (exit) { - cycle_count++; - } else { - cycle_count = 0; - } - } else if (exit) { - break; - } + if (!(flags & WATCH_NORERUN) || + get_time_usec() - last_run > interval * USECS_PER_SEC) { + last_run = get_time_usec(); + int exit = run_command(command, command_argv); + + if (flags & WATCH_EQUEXIT) { + if (cycle_count == max_cycles && exit) { + break; + } else if (exit) { + cycle_count++; + } else { + cycle_count = 0; + } + } else if (exit) { + break; + } + } else { + refresh(); + } if (precise_timekeeping) { watch_usec_t cur_time = get_time_usec();