|
|
|
@ -36,6 +36,7 @@ enum op {
|
|
|
|
|
EXPR_GLOBI,
|
|
|
|
|
EXPR_REGEX,
|
|
|
|
|
EXPR_REGEXI,
|
|
|
|
|
EXPR_PRUNE,
|
|
|
|
|
EXPR_PRINT,
|
|
|
|
|
EXPR_TYPE,
|
|
|
|
|
EXPR_ALLSET,
|
|
|
|
@ -72,6 +73,9 @@ enum flags {
|
|
|
|
|
/* custom */
|
|
|
|
|
FLAG_NEW = 64,
|
|
|
|
|
FLAG_CUR = 128,
|
|
|
|
|
|
|
|
|
|
FLAG_PARENT = 256,
|
|
|
|
|
FLAG_CHILD = 512,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct expr {
|
|
|
|
@ -92,12 +96,29 @@ struct mailinfo {
|
|
|
|
|
time_t date;
|
|
|
|
|
int depth;
|
|
|
|
|
int index;
|
|
|
|
|
int replies;
|
|
|
|
|
int matched;
|
|
|
|
|
int prune;
|
|
|
|
|
long flags;
|
|
|
|
|
off_t total;
|
|
|
|
|
char subject[100];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct mlist {
|
|
|
|
|
struct mailinfo *m;
|
|
|
|
|
struct mlist *next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct thread {
|
|
|
|
|
int matched;
|
|
|
|
|
struct mlist childs[100];
|
|
|
|
|
struct mlist *cur;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct thread *thr;
|
|
|
|
|
|
|
|
|
|
static char *argv0;
|
|
|
|
|
static int Tflag;
|
|
|
|
|
|
|
|
|
|
static long kept;
|
|
|
|
|
static long num;
|
|
|
|
@ -106,6 +127,7 @@ static struct expr *expr;
|
|
|
|
|
static char *cur;
|
|
|
|
|
static char *pos;
|
|
|
|
|
static time_t now;
|
|
|
|
|
static int prune;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ws()
|
|
|
|
@ -196,7 +218,10 @@ static struct expr *parse_or();
|
|
|
|
|
static struct expr *
|
|
|
|
|
parse_inner()
|
|
|
|
|
{
|
|
|
|
|
if (token("print")) {
|
|
|
|
|
if (token("prune")) {
|
|
|
|
|
struct expr *e = mkexpr(EXPR_PRUNE);
|
|
|
|
|
return e;
|
|
|
|
|
} else if (token("print")) {
|
|
|
|
|
struct expr *e = mkexpr(EXPR_PRINT);
|
|
|
|
|
return e;
|
|
|
|
|
} else if (token("!")) {
|
|
|
|
@ -688,6 +713,9 @@ eval(struct expr *e, struct mailinfo *m)
|
|
|
|
|
case EXPR_NOT:
|
|
|
|
|
return !eval(e->a.expr, m);
|
|
|
|
|
return 1;
|
|
|
|
|
case EXPR_PRUNE:
|
|
|
|
|
prune = 1;
|
|
|
|
|
return 1;
|
|
|
|
|
case EXPR_PRINT:
|
|
|
|
|
return 1;
|
|
|
|
|
case EXPR_LT:
|
|
|
|
@ -759,8 +787,8 @@ eval(struct expr *e, struct mailinfo *m)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
oneline(char *line)
|
|
|
|
|
struct mailinfo *
|
|
|
|
|
mailfile(char *file)
|
|
|
|
|
{
|
|
|
|
|
static int init;
|
|
|
|
|
if (!init) {
|
|
|
|
@ -772,60 +800,169 @@ oneline(char *line)
|
|
|
|
|
init = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mailinfo m;
|
|
|
|
|
|
|
|
|
|
memset(m.subject, 0, sizeof m.subject);
|
|
|
|
|
m.fpath = line;
|
|
|
|
|
m.index = num++;
|
|
|
|
|
m.flags = 0;
|
|
|
|
|
m.depth = 0;
|
|
|
|
|
m.sb = 0;
|
|
|
|
|
|
|
|
|
|
while (*m.fpath == ' ' || *m.fpath== '\t') {
|
|
|
|
|
m.depth++;
|
|
|
|
|
m.fpath++;
|
|
|
|
|
struct mailinfo *m;
|
|
|
|
|
m = calloc(1, sizeof *m);
|
|
|
|
|
if (!m) {
|
|
|
|
|
fprintf(stderr, "calloc");
|
|
|
|
|
exit(2);
|
|
|
|
|
}
|
|
|
|
|
memset(m->subject, 0, sizeof m->subject);
|
|
|
|
|
|
|
|
|
|
m->fpath = file;
|
|
|
|
|
m->index = num++;
|
|
|
|
|
m->flags = 0;
|
|
|
|
|
m->depth = 0;
|
|
|
|
|
m->sb = 0;
|
|
|
|
|
m->msg = 0;
|
|
|
|
|
|
|
|
|
|
while (*m->fpath == ' ' || *m->fpath== '\t') {
|
|
|
|
|
m->depth++;
|
|
|
|
|
m->fpath++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *e = m.fpath + strlen(m.fpath) - 1;
|
|
|
|
|
while (m.fpath < e && (*e == ' ' || *e == '\t'))
|
|
|
|
|
char *e = m->fpath + strlen(m->fpath) - 1;
|
|
|
|
|
while (m->fpath < e && (*e == ' ' || *e == '\t'))
|
|
|
|
|
*e-- = 0;
|
|
|
|
|
|
|
|
|
|
m.msg = blaze822(m.fpath);
|
|
|
|
|
if (!m.msg)
|
|
|
|
|
return;
|
|
|
|
|
m->msg = blaze822(m->fpath);
|
|
|
|
|
if (!m->msg)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if ((e = strrchr(m->fpath, '/') - 1) && (e - m->fpath) >= 2 &&
|
|
|
|
|
*e-- == 'w' && *e-- == 'e' && *e-- == 'n')
|
|
|
|
|
m.flags |= FLAG_NEW;
|
|
|
|
|
m->flags |= FLAG_NEW;
|
|
|
|
|
|
|
|
|
|
if (cur && strcmp(cur, m.fpath) == 0)
|
|
|
|
|
m.flags |= FLAG_CUR;
|
|
|
|
|
if (cur && strcmp(cur, m->fpath) == 0)
|
|
|
|
|
m->flags |= FLAG_CUR;
|
|
|
|
|
|
|
|
|
|
char *f = strstr(m.fpath, ":2,");
|
|
|
|
|
char *f = strstr(m->fpath, ":2,");
|
|
|
|
|
if (f) {
|
|
|
|
|
if (strchr(f, 'P'))
|
|
|
|
|
m.flags |= FLAG_PASSED;
|
|
|
|
|
m->flags |= FLAG_PASSED;
|
|
|
|
|
if (strchr(f, 'R'))
|
|
|
|
|
m.flags |= FLAG_REPLIED;
|
|
|
|
|
m->flags |= FLAG_REPLIED;
|
|
|
|
|
if (strchr(f, 'S'))
|
|
|
|
|
m.flags |= FLAG_SEEN;
|
|
|
|
|
m->flags |= FLAG_SEEN;
|
|
|
|
|
if (strchr(f, 'T'))
|
|
|
|
|
m.flags |= FLAG_TRASHED;
|
|
|
|
|
m->flags |= FLAG_TRASHED;
|
|
|
|
|
if (strchr(f, 'D'))
|
|
|
|
|
m.flags |= FLAG_DRAFT;
|
|
|
|
|
m->flags |= FLAG_DRAFT;
|
|
|
|
|
if (strchr(f, 'F'))
|
|
|
|
|
m.flags |= FLAG_FLAGGED;
|
|
|
|
|
m->flags |= FLAG_FLAGGED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
do_thr()
|
|
|
|
|
{
|
|
|
|
|
struct mlist *ml;
|
|
|
|
|
|
|
|
|
|
if (!thr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (ml = thr->childs; ml; ml = ml->next) {
|
|
|
|
|
if (!ml->m)
|
|
|
|
|
continue;
|
|
|
|
|
if ((ml->m->prune = prune) || (Tflag && thr->matched))
|
|
|
|
|
continue;
|
|
|
|
|
if (expr && eval(expr, ml->m)) {
|
|
|
|
|
ml->m->matched = 1;
|
|
|
|
|
thr->matched++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
prune = 0;
|
|
|
|
|
|
|
|
|
|
for (ml = thr->childs; ml; ml = ml->next) {
|
|
|
|
|
if (!ml->m)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (((Tflag && thr->matched) || ml->m->matched) && !ml->m->prune) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < ml->m->depth; i++)
|
|
|
|
|
putchar(' ');
|
|
|
|
|
|
|
|
|
|
fputs(ml->m->fpath, stdout);
|
|
|
|
|
putchar('\n');
|
|
|
|
|
|
|
|
|
|
kept++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free collected mails */
|
|
|
|
|
if (ml->m->msg)
|
|
|
|
|
blaze822_free(ml->m->msg);
|
|
|
|
|
|
|
|
|
|
if (ml->m->sb)
|
|
|
|
|
free(ml->m->sb);
|
|
|
|
|
|
|
|
|
|
free(ml->m->fpath);
|
|
|
|
|
free(ml->m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(thr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
collect(char *file)
|
|
|
|
|
{
|
|
|
|
|
struct mailinfo *m;
|
|
|
|
|
struct mlist *ml;
|
|
|
|
|
|
|
|
|
|
if ((m = mailfile(file)) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (m->depth == 0) {
|
|
|
|
|
if (thr)
|
|
|
|
|
do_thr();
|
|
|
|
|
|
|
|
|
|
/* new thread */
|
|
|
|
|
thr = calloc(1, sizeof *thr);
|
|
|
|
|
if (!thr) {
|
|
|
|
|
fprintf(stderr, "calloc");
|
|
|
|
|
exit(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thr->matched = 0;
|
|
|
|
|
thr->cur = thr->childs;
|
|
|
|
|
thr->cur->m = m;
|
|
|
|
|
} else {
|
|
|
|
|
ml = thr->cur + 1;
|
|
|
|
|
thr->cur->next = ml;
|
|
|
|
|
thr->cur = ml;
|
|
|
|
|
ml->m = m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expr && !eval(expr, &m))
|
|
|
|
|
m->fpath = strdup(m->fpath);
|
|
|
|
|
|
|
|
|
|
/* already one match in thread */
|
|
|
|
|
if (Tflag && thr->matched)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (expr && !eval(expr, m))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
thr->matched++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
oneline(char *file)
|
|
|
|
|
{
|
|
|
|
|
struct mailinfo *m;
|
|
|
|
|
|
|
|
|
|
if ((m = mailfile(file)) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (expr && !eval(expr, m))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
printf("%s\n", file);
|
|
|
|
|
kept++;
|
|
|
|
|
printf("%s\n", line);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
free(m.sb);
|
|
|
|
|
blaze822_free(m.msg);
|
|
|
|
|
blaze822_free(m->msg);
|
|
|
|
|
free(m->sb);
|
|
|
|
|
free(m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
@ -833,11 +970,13 @@ main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
long i;
|
|
|
|
|
int c;
|
|
|
|
|
void (*cb)(char *);
|
|
|
|
|
|
|
|
|
|
argv0 = argv[0];
|
|
|
|
|
|
|
|
|
|
while ((c = getopt(argc, argv, "t:")) != -1)
|
|
|
|
|
while ((c = getopt(argc, argv, "Tt:")) != -1)
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'T': Tflag = 1; break;
|
|
|
|
|
case 't': expr = chain(expr, EXPR_AND, parse_expr(optarg)); break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -845,10 +984,19 @@ main(int argc, char *argv[])
|
|
|
|
|
for (c = optind; c < argc; c++)
|
|
|
|
|
expr = chain(expr, EXPR_AND, parse_msglist(argv[c]));
|
|
|
|
|
|
|
|
|
|
if (Tflag)
|
|
|
|
|
cb = collect;
|
|
|
|
|
else
|
|
|
|
|
cb = oneline;
|
|
|
|
|
|
|
|
|
|
if (isatty(0)) {
|
|
|
|
|
i = blaze822_loop1(":", oneline);
|
|
|
|
|
i = blaze822_loop1(":", cb);
|
|
|
|
|
} else
|
|
|
|
|
i = blaze822_loop(0, NULL, oneline);
|
|
|
|
|
i = blaze822_loop(0, NULL, cb);
|
|
|
|
|
|
|
|
|
|
/* print and free last thread */
|
|
|
|
|
if (Tflag && thr)
|
|
|
|
|
do_thr();
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept);
|
|
|
|
|
return 0;
|
|
|
|
|