mshow: actually filter the parts

pull/2/head
Christian Neukirchen 8 years ago
parent 5d1266b38f
commit be2ca1ba42

@ -15,7 +15,7 @@ mmime: mmime.o
mpick: mpick.o blaze822.o seq.o rfc2047.c mymemmem.o
mscan: mscan.o blaze822.o seq.o rfc2047.o mymemmem.o
mseq: mseq.o seq.o
mshow: mshow.o blaze822.o seq.o rfc2045.o rfc2047.c mymemmem.o
mshow: mshow.o blaze822.o seq.o rfc2045.o rfc2047.c mymemmem.o filter.o
msort: msort.o blaze822.o seq.o mystrverscmp.o mymemmem.o
mthread: mthread.o blaze822.o seq.o mymemmem.o

@ -61,3 +61,7 @@ char *blaze822_seq_next(char *map, char *range, struct blaze822_seq_iter *iter);
int blaze822_loop(int, char **, void (*)(char *));
int blaze822_loop1(char *arg, void (*cb)(char *));
char *blaze822_home_file(char *basename);
// filter.c
int filter(char *input, size_t inlen, char *cmd, char **outputo, size_t *outleno);

@ -0,0 +1,124 @@
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int
filter(char *input, size_t inlen, char *cmd, char **outputo, size_t *outleno)
{
char *output;
size_t outlen;
ssize_t outalloc = 4096;
pid_t pid;
output = malloc(outalloc);
outlen = 0;
int pipe0[2];
int pipe1[2];
if (pipe(pipe0) != 0 || pipe(pipe1) != 0)
goto fail;
char *argv[] = { "/bin/sh", "-c", cmd, (char *)0 };
if (!(pid = fork())) {
dup2(pipe0[0], 0);
close(pipe0[1]);
close(pipe0[0]);
dup2(pipe1[1], 1);
close(pipe1[0]);
close(pipe1[1]);
execvp(argv[0], argv);
exit(-1);
}
close(pipe0[0]);
close(pipe1[1]);
if (pid < 0) {
close(pipe0[1]);
close(pipe1[0]);
goto fail;
}
struct pollfd fds[2];
fds[0].fd = pipe1[0];
fds[0].events = POLLIN;
fds[1].fd = pipe0[1];
fds[1].events = POLLOUT;
while ((fds[0].fd >= 0 || fds[1].fd >= 0) &&
poll(fds, sizeof fds / sizeof fds[0], -1) >= 0) {
if (fds[0].revents & POLLIN) {
if (outlen + 512 > outalloc) {
outalloc *= 2;
if (outalloc < 0)
exit(-1);
output = realloc(output, outalloc);
if (!output)
exit(-1);
}
ssize_t ret = read(fds[0].fd, output + outlen, 512);
if (ret > 0)
outlen += ret;
else if (ret < 0)
close(fds[0].fd);
} else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
fds[0].fd = -1;
}
if (fds[1].revents & POLLOUT) {
ssize_t ret = write(fds[1].fd, input, inlen);
if (ret > 0) {
input += ret;
inlen -= ret;
}
if (ret <= 0 || inlen == 0)
close(fds[1].fd);
} else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
fds[1].fd = -1;
}
}
// ok to fail when closed already
close(pipe0[1]);
close(pipe1[0]);
int status;
waitpid(pid, &status, 0);
*outputo = output;
*outleno = outlen;
return WEXITSTATUS(status);
fail:
*outputo = 0;
*outleno = 0;
return -1;
}
#ifdef TEST
int
main()
{
char *input = "foo\nbar\nbaz";
int e;
char *output;
size_t outlen;
e = filter(input, strlen(input), "rev;exit 2", &output, &outlen);
fwrite(output, 1, outlen, stdout);
printf("%ld -> %d\n", outlen, e);
return 0;
}
#endif

@ -149,6 +149,8 @@ typedef enum {
typedef mime_action (*mime_callback)(int, struct message *, char *, size_t);
mime_action walk_mime(struct message *msg, int depth, mime_callback visit);
char *
mime_filename(struct message *msg)
{
@ -199,19 +201,29 @@ render_mime(int depth, struct message *msg, char *body, size_t bodylen)
setenv("PIPE_CHARSET", charset, 1);
free(charset);
}
printf(" filter=\"%s\" ---\n", cmd);
FILE *p;
fflush(stdout);
p = popen(cmd, "w");
if (!p) {
perror("popen");
goto nofilter;
}
fwrite(body, 1, bodylen, p);
if (pclose(p) != 0) {
perror("pclose");
setenv("PIPE_CONTENTTYPE", ct, 1);
char *output;
size_t outlen;
int e = filter(body, bodylen, cmd, &output, &outlen);
if (e == 0) {
printf(" render=\"%s\" ---\n", cmd);
print_ascii(output, outlen);
} else if (e == 64) { // decode output again
printf(" filter=\"%s\" ---\n", cmd);
struct message *imsg = blaze822_mem(output, outlen);
if (imsg)
walk_mime(imsg, depth+1, render_mime);
blaze822_free(imsg);
} else {
printf(" filter=\"%s\" FAILED status=%d", cmd, e);
free(output);
goto nofilter;
}
free(output);
r = MIME_PRUNE;
} else {
nofilter:

Loading…
Cancel
Save