This problem has been annoying me for a while.  So I wrote a patch.
The attached patch provides an option for watch to monitor stderr as
well as stdout.  [I think that behavior should be the default, but for
now, I've just made it an option.]  It also provide an option for
watch to beep if the command fails.

I emailed it to the procps feedback list a couple of days ago, and
haven't heard back yet.  So I decided to open a debian bug for
tracking purposes. . . and found there already are a bunch.

Looks like 481679 is also a dup of this bug.

- Morty
Binary files procps-3.2.7-orig/.watch.c.swp and procps-3.2.7/.watch.c.swp differ
diff -Nur procps-3.2.7-orig/watch.1 procps-3.2.7/watch.1
--- procps-3.2.7-orig/watch.1   2003-02-09 02:05:25.000000000 -0500
+++ procps-3.2.7/watch.1        2008-08-06 07:01:05.000000000 -0400
@@ -3,7 +3,7 @@
 watch \- execute a program periodically, showing output fullscreen
 .SH SYNOPSIS
 .B watch
-.I [\-dhvt] [\-n <seconds>] [\-\-differences[=cumulative]] [\-\-help] 
[\-\-interval=<seconds>] [\-\-no\-title] [\-\-version] <command>
+.I [\-bdhvst] [\-n <seconds>] [\-\-beep] [\-\-differences[=cumulative]] 
[\-\-errors-too] [\-\-help] [\-\-interval=<seconds>] [\-\-no\-title] 
[\-\-version] <command>
 .SH DESCRIPTION
 .BR watch
 runs
@@ -28,7 +28,15 @@
 or
 .I --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.  The 
+.I -s 
+or 
+.I --errors-too
+option causes error output to be handled just like normal output.
 .PP
 .BR watch
 will run until interrupted.
@@ -84,4 +92,5 @@
 .B watch
 was written by Tony Rems <[EMAIL PROTECTED]> in 1991, with mods and
 corrections by Francois Pinard.  It was reworked and new features added by
-Mike Coleman <[EMAIL PROTECTED]> in 1999.
+Mike Coleman <[EMAIL PROTECTED]> in 1999.  The beep and errors-too features 
were
+added by Morty Abzug <[EMAIL PROTECTED]> in 2008.
diff -Nur procps-3.2.7-orig/watch.c procps-3.2.7/watch.c
--- procps-3.2.7-orig/watch.c   2006-06-17 05:18:38.000000000 -0400
+++ procps-3.2.7/watch.c        2008-08-06 07:06:06.000000000 -0400
@@ -8,6 +8,7 @@
  * Mike Coleman <[EMAIL PROTECTED]>.
  *
  * Changes by Albert Cahalan, 2002-2003.
+ * errors-too and beep options added by Morty Abzug, 2008
  */
 
 #define VERSION "0.2.0"
@@ -35,13 +36,15 @@
        {"differences", optional_argument, 0, 'd'},
        {"help", no_argument, 0, 'h'},
        {"interval", required_argument, 0, 'n'},
+       {"errors-too", no_argument, 0, 's'},
+       {"beep", no_argument, 0, 'b'},
        {"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 [-bdhnstv] [--beep] [--differences[=cumulative]] [--errors-too] 
[--help] [--interval=<n>] [--no-title] [--version] <command>\n";
 
 static char *progname;
 
@@ -140,17 +143,25 @@
        int optc;
        int option_differences = 0,
            option_differences_cumulative = 0,
+                       option_errors_too = 0,
+                       option_beep = 0,
            option_help = 0, option_version = 0;
        double interval = 2;
        char *command;
        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, "+bd::hn:vst", longopts, (int *) 
0))
               != EOF) {
                switch (optc) {
+               case 'b':
+                       option_beep = 1;
+                       break;
                case 'd':
                        option_differences = 1;
                        if (optarg)
@@ -159,6 +170,9 @@
                case 'h':
                        option_help = 1;
                        break;
+               case 's':
+                 option_errors_too = 1;
+                       break;
                case 't':
                        show_title = 0;
                        break;
@@ -191,11 +205,13 @@
 
        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("  -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("  -s, --errors-too\t\t\tredirects errors as well\n", 
stderr);
                fputs("  -t, --no-title\t\t\tturns off showing the header\n", 
stderr);
                exit(0);
        }
@@ -261,11 +277,50 @@
                        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 and exec */
+               child=fork();
+
+               if (child<0) { /* fork error */
+                 perror("fork");
                        do_exit(2);
+               } else if (child==0) { /* in child */
+                       close (pipefd[0]);
+                       close (1);
+                       if (dup2 (pipefd[1], 1)<0) {
+                         perror("dup2");
+                               exit(3);
+                       }
+                 if (option_errors_too) {
+                         close(2);
+                               dup2(1, 2);
+                       }
+                       /* this should use execvp, but the watch manpage 
promises quoting */
+                       status=system(command);
+                       if (!WIFEXITED(status)) {
+                         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 +368,18 @@
                        oldeolseen = eolseen;
                }
 
-               pclose(p);
+               fclose(p);
+
+               /* harvest child process and get status */
+               if (waitpid(child, &status, 0)<0) {
+                 perror("waitpid");
+                       do_exit(8);
+               };
+
+               /* if child process exited in error, beep */
+               if (option_beep && (!WIFEXITED(status) || WEXITSTATUS(status))) 
{
+                 beep();
+               }
 
                first_screen = 0;
                refresh();

Reply via email to