void-packages/srcpkgs/procps/patches/watch_exec_beep.patch

259 lines
7.4 KiB
Diff

Description: Adds -exec and -beep flags and has better quoting #410967
Adds -errexit flag now too #183346
Author: Mordechai T. Abzug <morty@frakir.org>
Bug-Debian: http://bugs.debian.org/410967
Bug-Debian: http://bugs.debian.org/183346
Reviewed-by: Craig Small <csmall@debian.org>
Index: b/watch.1
===================================================================
--- a/watch.1 2009-11-24 21:00:36.000000000 +1100
+++ b/watch.1 2009-11-24 21:00:43.000000000 +1100
@@ -4,10 +4,13 @@
.SH SYNOPSIS
.na
.B watch
-.RB [ \-dhvt ]
+.RB [ \-bdehvtx ]
.RB [ \-n
.IR seconds ]
+.RB [ \-\-beep ]
.RB [ \-\-differences[=\fIcumulative\fP]]
+.RB [ \-\-errexit ]
+.RB [ \-\-exec ]
.RB [ \-\-help ]
.RB [ \-\-interval=\fIseconds\fP]
.RB [ \-\-no\-title ]
@@ -17,7 +20,8 @@
.B watch
runs
.I command
-repeatedly, displaying its output (the first screenfull). This allows you to
+repeatedly, displaying its output and errors (the first screenfull). This
+allows you to
watch the program output change over time. By default, the program is run
every 2 seconds; use
.B \-n
@@ -37,15 +41,33 @@
or
.B \-\-no\-title
option turns off the header showing the interval, command, and current
-time at the top of the display, as well as the following blank line.
+time at the top of the display, as well as the following blank line. The
+.I \-b
+or
+.I \-\-beep
+option causes the command to beep if it has a non-zero exit.
.PP
.B watch
-will run until interrupted.
+will normally run until interrupted. If you want
+.B watch
+to exit on an error from the program running use the
+.I \-e
+or
+.I \-\-errexit
+options, which will cause
+.B watch
+to exit if the return value from the program is non-zero.
+
.SH NOTE
Note that
.I command
is given to "sh \-c"
which means that you may need to use extra quoting to get the desired effect.
+You can disable this with the
+.I -x
+or
+.I --exec
+option, which passes the command to exec(2) instead.
.PP
Note that POSIX option processing is used (i.e., option processing stops at
the first non\-option argument). This means that flags after
@@ -93,4 +115,5 @@
.B watch
was written by Tony Rems <rembo@unisoft.com> in 1991, with mods and
corrections by Francois Pinard. It was reworked and new features added by
-Mike Coleman <mkc@acm.org> in 1999.
+Mike Coleman <mkc@acm.org> in 1999. The beep, exec, and error handling
+features were added by Morty Abzug <morty@frakir.org> in 2008.
Index: b/watch.c
===================================================================
--- a/watch.c 2009-11-24 21:00:40.000000000 +1100
+++ b/watch.c 2009-11-24 21:00:43.000000000 +1100
@@ -8,6 +8,7 @@
* Mike Coleman <mkc@acm.org>.
*
* Changes by Albert Cahalan, 2002-2003.
+ * stderr handling, exec, and beep option added by Morty Abzug, 2008
*/
#define VERSION "0.2.0"
@@ -35,13 +36,16 @@
{"differences", optional_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"interval", required_argument, 0, 'n'},
+ {"beep", no_argument, 0, 'b'},
+ {"errexit", no_argument, 0, 'e'},
+ {"exec", no_argument, 0, 'x'},
{"no-title", no_argument, 0, 't'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
static char usage[] =
- "Usage: %s [-dhntv] [--differences[=cumulative]] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
+ "Usage: %s [-bdhntvx] [--beep] [--differences[=cumulative]] [--exec] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
static char *progname;
@@ -140,28 +144,44 @@
int optc;
int option_differences = 0,
option_differences_cumulative = 0,
+ option_exec = 0,
+ option_beep = 0,
+ option_errexit = 0,
option_help = 0, option_version = 0;
double interval = 2;
char *command;
+ char **command_argv;
int command_length = 0; /* not including final \0 */
+ int pipefd[2];
+ int status;
+ pid_t child;
setlocale(LC_ALL, "");
progname = argv[0];
- while ((optc = getopt_long(argc, argv, "+d::hn:vt", longopts, (int *) 0))
+ while ((optc = getopt_long(argc, argv, "+bed::hn:vtx", longopts, (int *) 0))
!= EOF) {
switch (optc) {
+ case 'b':
+ option_beep = 1;
+ break;
case 'd':
option_differences = 1;
if (optarg)
option_differences_cumulative = 1;
break;
+ case 'e':
+ option_errexit = 1;
+ break;
case 'h':
option_help = 1;
break;
case 't':
show_title = 0;
break;
+ case 'x':
+ option_exec = 1;
+ break;
case 'n':
{
char *str;
@@ -191,18 +211,23 @@
if (option_help) {
fprintf(stderr, usage, progname);
+ fputs(" -b, --beep\t\t\t\tbeep if the command has a non-zero exit\n", stderr);
fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr);
fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr);
+ fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr);
fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr);
fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr);
fputs(" -v, --version\t\t\t\tprint the version number\n", stderr);
fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr);
+ fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr);
exit(0);
}
if (optind >= argc)
do_usage();
+ command_argv=&(argv[optind]); /* save for later */
+
command = strdup(argv[optind++]);
command_length = strlen(command);
for (; optind < argc; optind++) {
@@ -261,11 +286,57 @@
free(header);
}
- if (!(p = popen(command, "r"))) {
- perror("popen");
+ /* allocate pipes */
+ if (pipe(pipefd)<0) {
+ perror("pipe");
+ do_exit(7);
+ }
+
+ /* flush stdout and stderr, since we're about to do fd stuff */
+ fflush(stdout);
+ fflush(stderr);
+
+ /* fork to prepare to run command */
+ child=fork();
+
+ if (child<0) { /* fork error */
+ perror("fork");
do_exit(2);
+ } else if (child==0) { /* in child */
+ close (pipefd[0]); /* child doesn't need read side of pipe */
+ close (1); /* prepare to replace stdout with pipe */
+ if (dup2 (pipefd[1], 1)<0) { /* replace stdout with write side of pipe */
+ perror("dup2");
+ exit(3);
+ }
+ dup2(1, 2); /* stderr should default to stdout */
+
+ if (option_exec) { /* pass command to exec instead of system */
+ if (execvp(command_argv[0], command_argv)==-1) {
+ perror("exec");
+ exit(4);
+ }
+ } else {
+ status=system(command); /* watch manpage promises sh quoting */
+
+ /* propagate command exit status as child exit status */
+ if (!WIFEXITED(status)) { /* child exits nonzero if command does */
+ exit(1);
+ } else {
+ exit(WEXITSTATUS(status));
+ }
+ }
+
+ }
+
+ /* otherwise, we're in parent */
+ close(pipefd[1]); /* close write side of pipe */
+ if ((p=fdopen(pipefd[0], "r"))==NULL) {
+ perror("fdopen");
+ do_exit(5);
}
+
for (y = show_title; y < height; y++) {
int eolseen = 0, tabpending = 0;
for (x = 0; x < width; x++) {
@@ -313,7 +384,19 @@
oldeolseen = eolseen;
}
- pclose(p);
+ fclose(p);
+
+ /* harvest child process and get status, propagated from command */
+ if (waitpid(child, &status, 0)<0) {
+ perror("waitpid");
+ do_exit(8);
+ };
+
+ /* if child process exited in error, beep if option_beep is set */
+ if ((!WIFEXITED(status) || WEXITSTATUS(status))) {
+ if (option_beep) beep();
+ if (option_errexit) do_exit(8);
+ }
first_screen = 0;
refresh();