aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2017-05-23 15:16:27 +0200
committerLeah Neukirchen <leah@vuxu.org>2017-05-23 15:16:27 +0200
commite8107b1889a620b6ba446953e698b30f1803b2cb (patch)
tree762870878b73df56171da14d0cec1f74a64ee0a8
parente7ce5ecc78dc8c56f32cd839369066cf33997305 (diff)
downloadmblaze-e8107b1889a620b6ba446953e698b30f1803b2cb.tar.gz
mshow: spawn a pager for interactive use
-rw-r--r--Makefile2
-rw-r--r--blaze822.h6
-rw-r--r--man/mshow.117
-rw-r--r--mshow.c23
-rw-r--r--pipeto.c98
5 files changed, 144 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index bb21265..dc9f33e 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ maddr magrep mexport mflag mgenmid mhdr mlist mpick mscan msed mseq mshow msort
mthread : seq.o slurp.o
maddr magrep mhdr mpick mscan mshow : rfc2047.o
magrep mshow : rfc2045.o
-mshow : filter.o safe_u8putstr.o rfc2231.o
+mshow : filter.o safe_u8putstr.o rfc2231.o pipeto.o
msort : mystrverscmp.o
mmime : slurp.o
diff --git a/blaze822.h b/blaze822.h
index 4dfd8f5..a5cb008 100644
--- a/blaze822.h
+++ b/blaze822.h
@@ -91,3 +91,9 @@ int slurp(char *filename, char **bufo, off_t *leno);
#include <stdio.h>
void safe_u8putstr(char *s0, size_t l, FILE *stream);
+
+// pipeto.c
+
+pid_t pipeto(const char *cmdline);
+int pipeclose(pid_t pid);
+
diff --git a/man/mshow.1 b/man/mshow.1
index acce690..66c839b 100644
--- a/man/mshow.1
+++ b/man/mshow.1
@@ -30,7 +30,7 @@ See
.Xr mmsg 7
for the message argument syntax.
If used interactively and no messages are given,
-displays the current message.
+displays the current message using colorization and a pager.
.Pp
The options are as follows:
.Bl -tag -width Ds
@@ -118,6 +118,21 @@ The environment variable
.Ev PIPE_CHARSET
will be set to the charset declared in the MIME part,
if known.
+.Sh ENVIRONMENT
+.Bl -tag -width MBLAZE_NOCOLOR
+.It Ev MBLAZE_PAGER
+Any non-empty value of the environment variable
+.Ev MBLAZE_PAGER
+is used instead of the standard pagination program, specified in
+.Ev PAGER .
+When empty or set to
+.Sq Ic cat ,
+no pager is spawned.
+.It Ev MBLAZE_NOCOLOR
+If non-empty,
+.Nm
+will not spawn a colorization filter.
+.El
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
diff --git a/mshow.c b/mshow.c
index 4c62410..a96d540 100644
--- a/mshow.c
+++ b/mshow.c
@@ -703,6 +703,8 @@ done:
int
main(int argc, char *argv[])
{
+ pid_t pid1 = -1, pid2 = -1;
+
int c;
while ((c = getopt(argc, argv, "h:A:qrtHLx:O:Rn")) != -1)
switch(c) {
@@ -731,6 +733,22 @@ main(int argc, char *argv[])
if (!rflag && !Oflag && !Rflag)
safe_output = 1;
+ if (safe_output && isatty(1)) {
+ char *pg;
+ pg = getenv("MBLAZE_PAGER");
+ if (!pg)
+ pg = getenv("PAGER");
+ if (pg && *pg && strcmp(pg, "cat") != 0) {
+ pid2 = pipeto(pg);
+ if (pid2 < 0)
+ fprintf(stderr,
+ "mshow: spawning pager '%s': %s\n",
+ pg, strerror(errno));
+ else if (!getenv("MBLAZE_NOCOLOR"))
+ pid1 = pipeto("mcolor"); // ignore error
+ }
+ }
+
if (xflag) { // extract
extract(xflag, argc-optind, argv+optind, 0);
} else if (Oflag) { // extract to stdout
@@ -758,5 +776,10 @@ main(int argc, char *argv[])
blaze822_seq_setcur(newcur);
}
+ if (pid2 > 0)
+ pipeclose(pid2);
+ if (pid1 > 0)
+ pipeclose(pid1);
+
return 0;
}
diff --git a/pipeto.c b/pipeto.c
new file mode 100644
index 0000000..77982e1
--- /dev/null
+++ b/pipeto.c
@@ -0,0 +1,98 @@
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+pid_t
+pipeto(const char *cmdline)
+{
+ int pipe0[2]; // stdout -> stdin
+ int pipe1[2]; // child errno -> parent
+ pid_t pid;
+
+ if (pipe(pipe0) < 0)
+ return -1;
+ if (pipe(pipe1) < 0)
+ return -1;
+
+ pid = fork();
+ if (pid < 0) {
+ return -1;
+ } else if (pid == 0) { // in child
+ close(pipe1[0]);
+ // close errno pipe on successful exec
+ fcntl(pipe1[1], F_SETFD, FD_CLOEXEC);
+
+ if (dup2(pipe0[0], 0) < 0)
+ exit(111);
+
+ close(pipe0[0]);
+ close(pipe0[1]);
+
+ // split cmdline, just on spaces
+ char *argv[16];
+ int argc = 0;
+ char *cp = strdup(cmdline);
+ if (!cp)
+ exit(111);
+ while (argc < 16 && *cp) {
+ argv[argc++] = cp;
+ cp = strchr(cp, ' ');
+ if (!cp)
+ break;
+ *cp++ = 0;
+ while (*cp == ' ')
+ cp++;
+ }
+ argv[argc] = 0;
+
+ execvp(argv[0], argv);
+
+ // execvp failed, write errno to parent
+ long e = errno;
+ if (write(pipe1[1], &e, sizeof e) < 0)
+ exit(111); // do a magic dance for gcc -Wunused-result
+ exit(111);
+ } else { // in parent
+ close(pipe1[1]);
+
+ long e;
+ ssize_t n = read(pipe1[0], &e, sizeof e);
+ if (n < 0)
+ e = errno;
+ close(pipe1[0]);
+
+ if (n == 0) {
+ // child executed successfully, redirect stdout to it
+ if (dup2(pipe0[1], 1) < 0)
+ return -1;
+
+ close(pipe0[0]);
+ close(pipe0[1]);
+
+ return pid;
+ } else {
+ errno = e;
+ return -1;
+ }
+ }
+
+// return pid;
+}
+
+int
+pipeclose(pid_t pid)
+{
+ int s;
+
+ fflush(0);
+ close(1);
+ waitpid(pid, &s, 0);
+
+ return s;
+}