X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fpick.c;h=f700a0c7fe25a0fe710bcc9d961fa9ab4e795b5f;hp=1c195be4249316bccbf73cda589a04f5ac5a7529;hb=ec2171174c019bdc83002cc29d06357e30b4b90d;hpb=e0bd1185d5a6a854a04f3c567195cfe96df112d0 diff --git a/uip/pick.c b/uip/pick.c index 1c195be..f700a0c 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -71,9 +71,13 @@ static struct swit switches[] = { { "format format", 0 }, #define WIDTHSW 23 { "width columns", 0 }, -#define VERSIONSW 24 +#define THREADSW 24 + { "thread", 0 }, +#define FILESW 25 + { "file file", 0 }, +#define VERSIONSW 26 { "Version", 0 }, -#define HELPSW 25 +#define HELPSW 27 { "help", 0 }, { NULL, 0 } }; @@ -96,6 +100,9 @@ static boolean body = FALSE; */ static int pcompile(char **, char *); static int pmatches(FILE *, int); +static struct nexus * createonethread(char *); +static struct nexus * createpickthread(char *); +static void scan_mbox(char *, char *, int); static int listsw = -1; @@ -118,6 +125,7 @@ main(int argc, char **argv) char *form = NULL; char *fmtstr; FILE *fp; + char *file = NULL; if (atexit(putzero_done) != 0) { adios(EX_OSERR, NULL, "atexit failed"); @@ -169,6 +177,7 @@ main(int argc, char **argv) case AFTRSW: case BEFRSW: case SRCHSW: + case THREADSW: vec[vecp++] = --cp; pattern: if (!(cp = *argp++)) /* allow -xyz arguments */ @@ -232,6 +241,15 @@ main(int argc, char **argv) } width = atoi(cp); continue; + case FILESW: + if (!(cp = *argp++) || (cp[0] == '-' && cp[1])) { + adios(EX_USAGE, NULL, "missing argument to %s", + argp[-2]); + } + if (strcmp(file = cp, "-")!=0) { + file = mh_xstrdup(expanddir(cp)); + } + continue; } } if (*cp == '+' || *cp == '@') { @@ -246,6 +264,21 @@ main(int argc, char **argv) fmtstr = new_fs(form, "pick.default"); + if (file) { + if (folder) { + adios(EX_USAGE, NULL, "\"+folder\" not allowed with -file"); + } + if (msgs.size) { + adios(EX_USAGE, NULL, "\"msgs\" not allowed with -file"); + } + if (vecp) { + adios(EX_USAGE, NULL, "section arguments not allowed with -file"); + } + + scan_mbox(file, fmtstr, width); + exit(EX_OK); + } + /* ** If we didn't specify which messages to search, ** then search the whole folder. @@ -324,7 +357,9 @@ main(int argc, char **argv) } } - head->free(&head); + if (head) { + head->free(&head); + } mp->lowsel = lo; mp->hghsel = hi; @@ -356,6 +391,29 @@ main(int argc, char **argv) return 0; } +static void +scan_mbox(char *file, char *fmtstr, int width) +{ + FILE *in; + int msgnum; + int state; + + if (strcmp(file, "-") == 0) { + in = stdin; + file = "stdin"; + } else if (!(in = fopen(file, "r"))) { + adios(EX_IOERR, file, "unable to open"); + } + + for (msgnum = 1; ;msgnum++) { + state = scan(in, msgnum, SCN_MBOX, fmtstr, width, 0, 0); + if (state != SCNMSG) { + break; + } + } + fclose(in); +} + void putzero_done() @@ -421,6 +479,8 @@ static struct swit parswit[] = { { "before date", 0 }, #define PRDATF 14 { "datefield field", 5 }, +#define PRTHREAD 15 + { "thread msg", 0 }, { NULL, 0 } }; @@ -731,6 +791,11 @@ nexp3(void) prvarg(); return NULL; + case PRTHREAD: + if (!(cp = nxtarg())) { /* allow -xyz arguments */ + padvise(NULL, "missing argument to %s", argp[-2]); + } + return createpickthread(cp); case PRCC: case PRDATE: case PRFROM: @@ -975,8 +1040,13 @@ BINaction(struct field *f, int msgnum, void *data) static void BINfree(struct nexus **n) { - struct nexus *bin = *n; - struct bin_data *bd = bin->data; + struct bin_data *bd; + + if (!(*n)) { + return; + } + + bd = (*n)->data; if (bd->left && bd->left->free) { bd->left->free(&bd->left); @@ -1018,26 +1088,29 @@ GREPaction(struct field *f, int msgnum, void *data) { struct grep_data *g = data; int ret; - char *buf; + char buf[BUFSIZ]; - /* check for the write field */ - if (g->header && *g->header && mh_strcasecmp(g->header, f->name)) { + if (!g->header && *f->name) { return FALSE; } - if (!g->header && *f->name) { + /* check for the right field */ + if (!(g->header && *g->header && mh_strcasecmp(g->header, f->name)==0)) { return FALSE; } - ret = regexec(g->preg, f->value, 0, NULL, 0) == REG_NOMATCH; + if(decode_rfc2047(f->value, buf, sizeof(buf))) { + ret = regexec(g->preg, buf, 0, NULL, 0); + } else { + ret = regexec(g->preg, f->value, 0, NULL, 0); + } switch (ret) { case 0: return TRUE; case REG_NOMATCH: return FALSE; default: - buf = mh_xcalloc(BUFSIZ, sizeof(char)); - regerror(ret, g->preg, buf, BUFSIZ*sizeof(char)); + regerror(ret, g->preg, buf, sizeof(buf)); fprintf(stderr, "%s\n", buf); return FALSE; } @@ -1047,7 +1120,11 @@ GREPaction(struct field *f, int msgnum, void *data) static void GREPfree(struct nexus **n) { - struct grep_data *gd = (*n)->data; + struct grep_data *gd; + if (!(*n)) { + return; + } + gd = (*n)->data; mh_free0(&gd->header); regfree(gd->preg); mh_free0(n); @@ -1202,9 +1279,12 @@ DATEaction(struct field *f, int msgnum, void *data) static void DATEfree(struct nexus **n) { - struct date_data *dd = (*n)->data; + struct date_data *dd; + if (!(*n)) { + return; + } + dd = (*n)->data; - mh_free0(&dd->datef); mh_free0(n); } @@ -1215,3 +1295,101 @@ DATEdebug(void *data, size_t level) print_debug_level(level); fprintf(stderr, "TEMPORAL(%s) %s: %s\n",dd->after ? "after" : "before", dd->datef, dasctime(&dd->tws)); } + +static struct nexus * +createpickthread(char *msgs) +{ + char *folder = NULL; + struct msgs_array msgarray = {0}; + struct msgs_array files = {0}; + struct nexus *ret = NULL; + struct nexus *c; + struct nexus *or; + struct bin_data *bd; + char *buf; + char **cp = brkstring(msgs, " \t", NULL); + int i; + + for (; cp && *cp; cp++) { + switch (**cp) { + case '@': + case '+': + if (folder) { + advise("",""); + break; + } + folder = mh_xstrdup(*cp); + break; + default: + app_msgarg(&msgarray, mh_xstrdup(*cp)); + } + } + + parse_msgs(&msgarray, folder, &files); + + for (i = 0; i < files.size; i++) { + buf = getthreadid(files.msgs[i]); + if (!buf) { + adios(EX_DATAERR, NULL, "message %s is not part of a thread", basename(files.msgs[i])); + continue; + } + + c = createonethread(buf); + + if (!ret) { + ret = c; + continue; + } + + + or = newnexus(TYPE_OR); + bd = or->data; + bd->right = ret; + bd->left = c; + ret = or; + } + + mh_free0(&(files.msgs)); + mh_free0(&(msgarray.msgs)); + + return ret; +} + +static struct nexus * +createonethread(char *c) +{ + struct nexus *ret = newnexus(TYPE_OR); + struct nexus *left = newnexus(TYPE_GREP); + struct nexus *right = newnexus(TYPE_GREP); + struct bin_data *bd = ret->data; + struct grep_data *gd = left->data; + char buf[BUFSIZ]; + + bd->left = left; + bd->right = right; + gd->header = mh_xstrdup("message-id"); + + snprintf(buf, sizeof(buf), "^[ \t]*<%s>", c); + if(!gcompile(gd, buf)) { + padvise(NULL, "pattern error %s", c); + goto error; + } + + gd = right->data; + gd->header = mh_xstrdup("references"); + + snprintf(buf, sizeof(buf), "^[ \t]*<%s>", c); + if(!gcompile(gd, buf)) { + padvise(NULL, "pattern error in %s", c); + goto error; + } + + return ret; + +error: + GREPfree(&left); + GREPfree(&right); + BINfree(&ret); + return NULL; + +}