New command line syntax, and new atom protocol.
[xtoys] / xcatch.c
index 43d3b02..4f99d19 100644 (file)
--- a/xcatch.c
+++ b/xcatch.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: xcatch.c,v 1.4 1999/03/24 22:23:57 mdw Exp $
+ * $Id: xcatch.c,v 1.8 1999/06/19 23:42:55 mdw Exp $
  *
  * Catch input and trap it in an X window
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: xcatch.c,v $
+ * Revision 1.8  1999/06/19 23:42:55  mdw
+ * Improve signal handling.  Fix options parsing to POSIX order only.
+ *
+ * Revision 1.7  1999/05/21 22:09:19  mdw
+ * Take advantage of new dynamic string macros.
+ *
+ * Revision 1.6  1999/05/19 20:41:15  mdw
+ * Track gratuitous change in mdwopt interface.
+ *
+ * Revision 1.5  1999/05/05 18:55:18  mdw
+ * Block SIGCHLD around the `fork' call to prevent a race.
+ *
  * Revision 1.4  1999/03/24 22:23:57  mdw
  * Improve display for large files.  Keep newly added material in view if
  * scrolled to bottom of window.
@@ -225,6 +237,7 @@ static void reap(int sig)
 {
   pid_t k;
   int s;
+  int e = errno;
 
   for (;;) {
     k = waitpid(-1, &s, WNOHANG);
@@ -237,6 +250,7 @@ static void reap(int sig)
        status = 127;
     }
   }
+  errno = e;
 }
 
 /* --- Main program --- */
@@ -264,11 +278,11 @@ int main(int argc, char *argv[])
       { "help",                0,              0,      'h' },
       { "usage",       0,              0,      'u' },
       { "version",     0,              0,      'v' },
-      { "file",                gFlag_argReq,   0,      'f' },
-      { "font",                gFlag_argReq,   0,      'F' },
+      { "file",                OPTF_ARGREQ,    0,      'f' },
+      { "font",                OPTF_ARGREQ,    0,      'F' },
       { 0,             0,              0,      0 }
     };
-    int i = mdwopt(argc, argv, "huvf:F:", opt, 0, 0, 0);
+    int i = mdwopt(argc, argv, "+huvf:F:", opt, 0, 0, 0);
 
     if (i < 0)
       break;
@@ -327,23 +341,32 @@ int main(int argc, char *argv[])
     else {
       int pfd[2];
       struct sigaction sa;
+      sigset_t newmask, oldmask;
 
       /* --- Set up a signal handler --- */
 
       sa.sa_handler = reap;
       sigemptyset(&sa.sa_mask);
-      sa.sa_flags = 0;
+      sa.sa_flags = SA_NOCLDSTOP;
+#ifdef SA_RESTART
+      sa.sa_flags |= SA_RESTART;
+#endif
       sigaction(SIGCHLD, &sa, 0);
 
       /* --- Start a child program --- */
 
       if (pipe(pfd))
        die(1, "couldn't open pipe: %s", strerror(errno));
+
+      sigemptyset(&newmask);
+      sigaddset(&newmask, SIGCHLD);
+      sigprocmask(SIG_BLOCK, &newmask, &oldmask);
+
       kid = fork();
       if (kid < 0)
        die(1, "couldn't fork: %s", strerror(errno));
       if (kid == 0) {
-       dstr d;
+       dstr d = DSTR_INIT;
 
        close(pfd[0]);
        if (pfd[1] != STDOUT_FILENO)
@@ -354,12 +377,14 @@ int main(int argc, char *argv[])
          close(pfd[1]);
        execvp(argv[optind], argv + optind);
 
-       dstr_create(&d);
        dstr_putf(&d, "%s: couldn't run `%s': %s\n",
                  QUIS, argv[optind], strerror(errno));
        write(STDERR_FILENO, d.buf, d.len);
+       dstr_destroy(&d);
        _exit(127);
       }
+
+      sigprocmask(SIG_SETMASK, &oldmask, 0);
       fd = pfd[0];
       close(pfd[1]);
     }