mhshow: Automatically invoke (one) pager for the whole message, if on TTY.
authormarkus schnalke <meillo@marmaro.de>
Sat, 14 Apr 2012 17:59:54 +0000 (19:59 +0200)
committermarkus schnalke <meillo@marmaro.de>
Sat, 14 Apr 2012 17:59:54 +0000 (19:59 +0200)
Mhshow used to invoke the pager for each of the text/plain parts
independently. Now, we invoke it once for the whole message.
Remember: We serialize!
(Mhl(1) invokes a pager too, currently, but not much longer.)

man/mhshow.man1
uip/mhshow.c

index 79975ef..ecd2e9d 100644 (file)
@@ -118,6 +118,14 @@ non\-empty, then
 will remove each of the messages shown
 from each sequence named by the profile entry.
 .SS "Showing the Contents"
+.B Mhshow
+prints messages in a convenient representation.
+If
+.B mhshow
+is outputting to a terminal, then
+a pager will be placed between the terminal and
+.BR mhshow .
+.PP
 The headers of each message are displayed with
 .B mhl
 using the standard format file
@@ -366,7 +374,7 @@ installation.
 ^Current\-Folder:~^To find the default current folder
 ^Unseen\-Sequence:~^To name sequences denoting unseen messages
 ^mhshow-show-<type>*~^Template for displaying contents
-^Pager:~^Default program to display text/plain content
+^Pager:~^Program to use as interactive front\-end
 .fi
 
 .SH "SEE ALSO"
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;
+}