{ "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 }
};
*/
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;
char *form = NULL;
char *fmtstr;
FILE *fp;
+ char *file = NULL;
if (atexit(putzero_done) != 0) {
adios(EX_OSERR, NULL, "atexit failed");
case AFTRSW:
case BEFRSW:
case SRCHSW:
+ case THREADSW:
vec[vecp++] = --cp;
pattern:
if (!(cp = *argp++)) /* allow -xyz arguments */
}
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 == '@') {
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.
}
}
- head->free(&head);
+ if (head) {
+ head->free(&head);
+ }
mp->lowsel = lo;
mp->hghsel = hi;
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()
{ "before date", 0 },
#define PRDATF 14
{ "datefield field", 5 },
+#define PRTHREAD 15
+ { "thread msg", 0 },
{ NULL, 0 }
};
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:
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);
{
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;
}
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);
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);
}
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) {
+ 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 = "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 = "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;
+
+}