2016-08-02 13:50:30 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <regex.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "blaze822.h"
|
|
|
|
|
|
|
|
static int aflag;
|
|
|
|
static int cflag;
|
|
|
|
static int dflag;
|
2018-09-10 13:22:02 +00:00
|
|
|
static int hflag;
|
2016-08-02 13:50:30 +00:00
|
|
|
static int iflag;
|
2018-07-07 18:12:54 +00:00
|
|
|
static int lflag;
|
2017-02-15 17:28:42 +00:00
|
|
|
static int oflag;
|
|
|
|
static int pflag;
|
2016-08-02 13:50:30 +00:00
|
|
|
static int qflag;
|
|
|
|
static int vflag;
|
2016-08-02 15:03:32 +00:00
|
|
|
static long mflag;
|
2016-08-02 13:50:30 +00:00
|
|
|
static long matches;
|
|
|
|
|
|
|
|
static regex_t pattern;
|
|
|
|
static char *header;
|
2016-08-02 14:28:35 +00:00
|
|
|
static char *curfile;
|
2016-08-02 13:50:30 +00:00
|
|
|
|
|
|
|
int
|
2017-02-15 17:28:42 +00:00
|
|
|
match(char *file, char *hdr, char *s)
|
2016-08-02 13:50:30 +00:00
|
|
|
{
|
2018-07-07 18:12:54 +00:00
|
|
|
if (oflag && !cflag && !qflag && !vflag && !lflag) {
|
2019-02-28 16:31:13 +00:00
|
|
|
regmatch_t pmatch = {0};
|
2017-02-23 19:47:38 +00:00
|
|
|
int len, matched;
|
2017-02-15 17:28:42 +00:00
|
|
|
matched = 0;
|
|
|
|
while (*s && regexec(&pattern, s, 1, &pmatch, 0) == 0) {
|
|
|
|
s += pmatch.rm_so;
|
2017-02-23 19:47:38 +00:00
|
|
|
if (!(len = pmatch.rm_eo-pmatch.rm_so)) {
|
2017-02-15 17:28:42 +00:00
|
|
|
s += 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (pflag)
|
|
|
|
printf("%s: %s: ", file, hdr);
|
2018-09-10 13:22:02 +00:00
|
|
|
else if (hflag)
|
|
|
|
printf("%s: ", hdr);
|
2017-02-23 19:47:38 +00:00
|
|
|
printf("%.*s\n", len, s);
|
|
|
|
s += len;
|
|
|
|
matched++;
|
2017-02-15 17:28:42 +00:00
|
|
|
}
|
|
|
|
return (matched && matches++);
|
|
|
|
} else if (vflag ^ (regexec(&pattern, s, 0, 0, 0) == 0)) {
|
2016-08-02 13:50:30 +00:00
|
|
|
if (qflag)
|
|
|
|
exit(0);
|
2016-08-02 15:03:32 +00:00
|
|
|
matches++;
|
2017-02-15 17:28:42 +00:00
|
|
|
if (!cflag) {
|
2018-09-10 13:22:02 +00:00
|
|
|
if (vflag || !hflag)
|
|
|
|
printf("%s", file);
|
2017-02-15 17:28:42 +00:00
|
|
|
if (pflag && !vflag)
|
|
|
|
printf(": %s: %s", hdr, s);
|
2018-09-10 13:22:02 +00:00
|
|
|
else if (hflag && !vflag)
|
|
|
|
printf("%s: %s", hdr, s);
|
2017-02-15 17:28:42 +00:00
|
|
|
putchar('\n');
|
|
|
|
}
|
2016-08-02 15:03:32 +00:00
|
|
|
if (mflag && matches >= mflag)
|
|
|
|
exit(0);
|
2016-08-02 13:50:30 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-08-02 14:28:35 +00:00
|
|
|
blaze822_mime_action
|
|
|
|
match_part(int depth, struct message *msg, char *body, size_t bodylen)
|
|
|
|
{
|
2017-08-31 15:30:17 +00:00
|
|
|
(void)depth;
|
2016-08-02 14:28:35 +00:00
|
|
|
|
|
|
|
char *ct = blaze822_hdr(msg, "content-type");
|
|
|
|
|
|
|
|
blaze822_mime_action r = MIME_CONTINUE;
|
|
|
|
|
|
|
|
if (!ct || strncmp(ct, "text/plain", 10) == 0) {
|
|
|
|
char *charset = 0, *cs, *cse;
|
|
|
|
if (blaze822_mime_parameter(ct, "charset", &cs, &cse))
|
|
|
|
charset = strndup(cs, cse-cs);
|
|
|
|
if (!charset ||
|
|
|
|
strcasecmp(charset, "utf-8") == 0 ||
|
|
|
|
strcasecmp(charset, "utf8") == 0 ||
|
|
|
|
strcasecmp(charset, "us-ascii") == 0) {
|
2018-09-10 13:22:02 +00:00
|
|
|
if ((hflag || pflag) && !cflag && !oflag && !vflag) {
|
2017-02-16 15:32:51 +00:00
|
|
|
char *s, *p;
|
|
|
|
for (p = s = body; p < body+bodylen+1; p++) {
|
|
|
|
if (*p == '\r' || *p == '\n') {
|
|
|
|
*p = 0;
|
2017-02-21 17:34:22 +00:00
|
|
|
if (p-s > 1)
|
|
|
|
match(curfile, "/", s);
|
2017-02-16 15:32:51 +00:00
|
|
|
s = p+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (match(curfile, "/", body)) {
|
2016-08-02 14:28:35 +00:00
|
|
|
r = MIME_STOP;
|
2017-02-16 15:32:51 +00:00
|
|
|
}
|
2016-08-02 14:28:35 +00:00
|
|
|
} else {
|
|
|
|
/* XXX decode here */
|
|
|
|
}
|
|
|
|
free(charset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
match_body(char *file)
|
|
|
|
{
|
2017-11-15 17:15:38 +00:00
|
|
|
char *filename;
|
|
|
|
filename = curfile = file;
|
|
|
|
while (*filename == ' ' || *filename == '\t')
|
|
|
|
filename++;
|
2016-08-02 14:28:35 +00:00
|
|
|
|
2017-11-15 17:15:38 +00:00
|
|
|
struct message *msg = blaze822_file(filename);
|
2016-08-02 14:28:35 +00:00
|
|
|
if (!msg)
|
|
|
|
return;
|
|
|
|
|
|
|
|
blaze822_walk_mime(msg, 0, match_part);
|
2018-12-18 21:10:10 +00:00
|
|
|
blaze822_free(msg);
|
2016-08-02 14:28:35 +00:00
|
|
|
}
|
|
|
|
|
2018-07-07 18:12:54 +00:00
|
|
|
int
|
2018-02-04 19:10:49 +00:00
|
|
|
match_value(char *file, char *h, char *v)
|
|
|
|
{
|
|
|
|
if (dflag) {
|
|
|
|
char d[4096];
|
|
|
|
blaze822_decode_rfc2047(d, v, sizeof d, "UTF-8");
|
2018-07-07 18:12:54 +00:00
|
|
|
return match(file, h, d);
|
2018-02-04 19:10:49 +00:00
|
|
|
} else if (aflag) {
|
|
|
|
char *disp, *addr;
|
|
|
|
while ((v = blaze822_addr(v, &disp, &addr))) {
|
|
|
|
if (addr && match(file, h, addr))
|
2018-07-07 18:12:54 +00:00
|
|
|
return 1;
|
2018-02-04 19:10:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-07-07 18:12:54 +00:00
|
|
|
return match(file, h, v);
|
2018-02-04 19:10:49 +00:00
|
|
|
}
|
2018-07-07 18:12:54 +00:00
|
|
|
return 0;
|
2018-02-04 19:10:49 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 13:50:30 +00:00
|
|
|
void
|
|
|
|
magrep(char *file)
|
|
|
|
{
|
2016-08-02 14:02:46 +00:00
|
|
|
if (!*header) {
|
|
|
|
char *flags = strstr(file, ":2,");
|
|
|
|
if (flags)
|
2017-02-15 17:28:42 +00:00
|
|
|
match(file, "flags", flags+3);
|
2016-08-02 14:02:46 +00:00
|
|
|
return;
|
2016-08-02 14:28:35 +00:00
|
|
|
} else if (strcmp(header, "/") == 0) {
|
|
|
|
match_body(file);
|
|
|
|
return;
|
2016-08-02 14:02:46 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 13:50:30 +00:00
|
|
|
char *filename = file;
|
|
|
|
while (*filename == ' ' || *filename == '\t')
|
2016-08-02 15:03:32 +00:00
|
|
|
filename++;
|
2016-08-02 13:50:30 +00:00
|
|
|
|
|
|
|
struct message *msg = blaze822(filename);
|
|
|
|
if (!msg)
|
|
|
|
return;
|
|
|
|
|
2018-02-04 19:10:49 +00:00
|
|
|
if (strcmp(header, "*") == 0) {
|
|
|
|
char *hdr = 0;
|
|
|
|
while ((hdr = blaze822_next_header(msg, hdr))) {
|
|
|
|
char *v = strchr(hdr, ':');
|
|
|
|
if (v) {
|
|
|
|
*v = 0;
|
2018-07-07 18:12:54 +00:00
|
|
|
if (match_value(file, hdr, v + 1 + (v[1] == ' ')) && lflag)
|
|
|
|
break;
|
2018-02-04 19:10:49 +00:00
|
|
|
*v = ':';
|
2016-08-02 13:50:30 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-04 19:10:49 +00:00
|
|
|
} else {
|
|
|
|
char *v = blaze822_chdr(msg, header);
|
|
|
|
if (v)
|
2018-07-07 18:12:54 +00:00
|
|
|
(void)match_value(file, header, v);
|
2016-08-02 13:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
blaze822_free(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int c;
|
2018-09-10 13:22:02 +00:00
|
|
|
while ((c = getopt(argc, argv, "acdhilm:opqv")) != -1)
|
2017-08-31 15:30:17 +00:00
|
|
|
switch (c) {
|
2016-08-02 15:03:32 +00:00
|
|
|
case 'a': aflag = 1; break;
|
|
|
|
case 'c': cflag = 1; break;
|
|
|
|
case 'd': dflag = 1; break;
|
2018-09-10 13:22:02 +00:00
|
|
|
case 'h': hflag = 1; break;
|
2016-08-02 15:03:32 +00:00
|
|
|
case 'i': iflag = REG_ICASE; break;
|
2018-07-07 18:12:54 +00:00
|
|
|
case 'l': lflag = 1; break;
|
2016-08-02 15:03:32 +00:00
|
|
|
case 'm': mflag = atol(optarg); break;
|
2017-02-15 17:28:42 +00:00
|
|
|
case 'o': oflag = 1; break;
|
|
|
|
case 'p': pflag = 1; break;
|
2016-08-02 15:03:32 +00:00
|
|
|
case 'q': qflag = 1; break;
|
|
|
|
case 'v': vflag = 1; break;
|
2016-08-02 13:50:30 +00:00
|
|
|
default:
|
2017-08-31 15:30:17 +00:00
|
|
|
usage:
|
2016-08-02 13:50:30 +00:00
|
|
|
fprintf(stderr,
|
2018-09-10 13:22:02 +00:00
|
|
|
"Usage: magrep [-c|-h|-o|-p|-q|-m max] [-v] [-i] [-l] [-a|-d] header:regex [msgs...]\n");
|
2016-08-02 13:50:30 +00:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc == optind)
|
|
|
|
goto usage;
|
|
|
|
header = argv[optind++];
|
|
|
|
|
|
|
|
char *rx = strchr(header, ':');
|
|
|
|
if (!rx)
|
|
|
|
goto usage;
|
|
|
|
|
|
|
|
*rx++ = 0;
|
|
|
|
int r = regcomp(&pattern, rx, REG_EXTENDED | iflag);
|
|
|
|
if (r != 0) {
|
|
|
|
char buf[256];
|
|
|
|
regerror(r, &pattern, buf, sizeof buf);
|
|
|
|
fprintf(stderr, "magrep: regex error: %s\n", buf);
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc == optind && isatty(0))
|
|
|
|
blaze822_loop1(":", magrep);
|
|
|
|
else
|
|
|
|
blaze822_loop(argc-optind, argv+optind, magrep);
|
2017-08-31 15:30:17 +00:00
|
|
|
|
2016-08-02 15:03:32 +00:00
|
|
|
if (cflag && !qflag && !mflag)
|
2016-08-02 13:50:30 +00:00
|
|
|
printf("%ld\n", matches);
|
|
|
|
|
|
|
|
return !matches;
|
|
|
|
}
|