From: Martin Mares Date: Tue, 6 Mar 2018 11:58:29 +0000 (+0100) Subject: Teach mparse to handle maildirs X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=HEAD;p=maildups.git Teach mparse to handle maildirs --- diff --git a/mparse.c b/mparse.c index 962755e..425adba 100644 --- a/mparse.c +++ b/mparse.c @@ -1,22 +1,34 @@ /* - * Mailbox Parser (so far very primitive) + * Mailbox and Maildir Parser (so far very primitive) * - * (c) 2010 Martin Mares + * (c) 2010--2018 Martin Mares */ #include #include #include +#include +#include #include +#include #include "util.h" const char progname[] = "mparse"; +static char **field_names; +static int num_fields; +static int mbox_fd; #define BUFSIZE 65536 static char buf[BUFSIZE]; -static char *bpos=buf, *bend=buf; +static char *bpos, *bend; + +static void reset_buf(void) +{ + bpos = buf; + bend = buf; +} static char *get_line(void) { @@ -46,7 +58,7 @@ static char *get_line(void) int space = BUFSIZE - remains; if (!space) die("Line too long"); - int len = read(0, bend, space); + int len = read(mbox_fd, bend, space); if (len < 0) die("Read error: %m"); if (!len) @@ -63,15 +75,15 @@ static char *get_line(void) } } -static int want_header(char *line, char **want, int n_want) +static int want_header(char *line) { - if (!n_want) + if (!num_fields) return 1; - for (int i=0; i\n", c); @@ -121,7 +133,7 @@ main(int argc, char **argv) } else { - want = want_header(c, argv+1, argc-1); + want = want_header(c); if (want) { putchar('\n'); @@ -133,6 +145,119 @@ main(int argc, char **argv) if (state == S_HEADER) printf("\nX-Warning: Incomplete mail\n\n"); +} + +static void parse_maildir_file(void) +{ + char *c; + int want = 0; + + reset_buf(); + while (c = get_line()) + { + // printf("<%s>\n", c); + if (!*c) + { + putchar('\n'); + return; + } + else if (*c == ' ' || *c == '\t') + { + if (want) + { + while (*c == ' ' || *c == '\t') + c++; + putchar(' '); + fputs(c, stdout); + } + } + else + { + want = want_header(c); + if (want) + { + putchar('\n'); + fputs(c, stdout); + } + } + } + + printf("\nX-Warning: Incomplete mail\n\n"); +} + +static void parse_maildir(char *dir, char *subdir) +{ + char buf[4096]; + snprintf(buf, sizeof(buf), "%s/%s", dir, subdir); + + DIR *d = opendir(buf); + if (!d) + return; + + struct dirent *e; + while (e = readdir(d)) + { + if (e->d_name[0] == '.') + continue; + snprintf(buf, sizeof(buf), "%s/%s/%s", dir, subdir, e->d_name); + mbox_fd = open(buf, O_RDONLY); + if (mbox_fd < 0) + continue; + parse_maildir_file(); + close(mbox_fd); + } + + closedir(d); +} + +static void usage(void) +{ + fprintf(stderr, "Usage: mparse [-f ] ...\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int opt; + char *folder = NULL; + + while ((opt = getopt(argc, argv, "f:")) >= 0) + switch (opt) + { + case 'f': + folder = optarg; + break; + default: + usage(); + } + + field_names = argv + optind; + num_fields = argc - optind; + + if (!folder) + { + parse_mbox(); + return 0; + } + + struct stat st; + if (stat(folder, &st) < 0) + die("Cannot stat %s: %m", folder); + + if (st.st_mode & S_IFDIR) + { + parse_maildir(folder, "cur"); + parse_maildir(folder, "new"); + } + else + { + mbox_fd = open(folder, O_RDONLY); + if (mbox_fd < 0) + die("Cannot open %s: %m", folder); + parse_mbox(); + close(mbox_fd); + } return 0; }