mhshow: Automatically invoke (one) pager for the whole message, if on TTY.
[mmh] / uip / mhshow.c
index 53f96f2..c323867 100644 (file)
@@ -79,6 +79,8 @@ void freects_done(int) NORETURN;
 ** static prototypes
 */
 static void pipeser(int);
+static void m_popen(char *);
+static void m_pclose(void);
 
 
 int
@@ -92,6 +94,7 @@ main(int argc, char **argv)
        struct msgs *mp = NULL;
        CT ct, *ctp;
        FILE *fp;
+       int ontty = 0;
 
        done=freects_done;
 
@@ -313,11 +316,19 @@ main(int argc, char **argv)
                }
        }
 
+       if ((ontty = isatty(fileno(stdout)))) {
+               m_popen(defaultpager);
+       }
+
        /*
        ** Show the message content
        */
        show_all_messages(cts);
 
+       if (ontty) {
+               m_pclose();
+       }
+
        /* Now free all the structures for the content */
        for (ctp = cts; *ctp; ctp++)
                free_content(*ctp);
@@ -351,3 +362,68 @@ pipeser(int i)
        done(1);
        /* NOTREACHED */
 }
+
+
+static int m_pid = NOTOK;
+static int sd = NOTOK;
+
+
+static void
+m_popen(char *name)
+{
+       int pd[2];
+
+       if ((sd = dup(fileno(stdout))) == NOTOK)
+               adios("standard output", "unable to dup()");
+
+       if (pipe(pd) == NOTOK)
+               adios("pipe", "unable to");
+
+       switch (m_pid = fork()) {
+       case NOTOK:
+               adios("fork", "unable to");
+
+       case OK:
+               SIGNAL(SIGINT, SIG_DFL);
+               SIGNAL(SIGQUIT, SIG_DFL);
+
+               close(pd[1]);
+               if (pd[0] != fileno(stdin)) {
+                       dup2(pd[0], fileno(stdin));
+                       close(pd[0]);
+               }
+               execlp(name, mhbasename(name), NULL);
+               fprintf(stderr, "unable to exec ");
+               perror(name);
+               _exit(-1);
+
+       default:
+               close(pd[0]);
+               if (pd[1] != fileno(stdout)) {
+                       dup2(pd[1], fileno(stdout));
+                       close(pd[1]);
+               }
+       }
+}
+
+
+void
+m_pclose(void)
+{
+       if (m_pid == NOTOK)
+               return;
+
+       if (sd != NOTOK) {
+               fflush(stdout);
+               if (dup2(sd, fileno(stdout)) == NOTOK)
+                       adios("standard output", "unable to dup2()");
+
+               clearerr(stdout);
+               close(sd);
+               sd = NOTOK;
+       } else
+               fclose(stdout);
+
+       pidwait(m_pid, OK);
+       m_pid = NOTOK;
+}