From ad6cec9e16bf41de2798a0d48ae4d08d019235c9 Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Thu, 28 Jul 2016 13:08:04 +0200 Subject: [PATCH] mhdr: almost-rewrite, use getopt --- man/mhdr.1 | 37 +++++++++-- mcomp | 22 +++---- mhdr.c | 188 +++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 186 insertions(+), 61 deletions(-) diff --git a/man/mhdr.1 b/man/mhdr.1 index 31648fc..48672fe 100644 --- a/man/mhdr.1 +++ b/man/mhdr.1 @@ -1,4 +1,4 @@ -.Dd July 22, 2016 +.Dd July 28, 2016 .Dt MHDR 1 .Os .Sh NAME @@ -6,7 +6,10 @@ .Nd show mail headers .Sh SYNOPSIS .Nm -.Op Fl Ar header +.Op Fl h Ar header +.Op Fl d +.Op Fl M +.Op Fl A | Fl D .Op Ar msgs\ ... .Sh DESCRIPTION .Nm @@ -24,16 +27,36 @@ will default to the current message. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl Ar header -Only print the value of the header -.Sq Ar header Ns Li \&: . -.Pp -By default, print all headers in normalized form (lowercase and unfolded). +.It Fl h Ar header +Only print the values of the headers in the colon-separated list +.Ar header . +.It Fl d +Decode the headers according to RFC 2047. +.It Fl M +Search for all occurrences of the headers +(default: only the first). +.It Fl A +Scan for RFC 5322 addresses in the headers and print them line by line. +.It Fl D +Assume header contains RFC 5322 date and print as Unix timestamp. .El .Sh EXIT STATUS .Ex -std .Sh SEE ALSO .Xr mmsg 7 +.Rs +.%A N. Freed +.%A N. Borenstein +.%B MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text +.%R RFC 2047 +.%D November 1996 +.Re +.Rs +.%A P. Resnick (ed.) +.%B Internet Message Format +.%R RFC 5322 +.%D October 2008 +.Re .Sh AUTHORS .An Christian Neukirchen Aq Mt chneukirchen@gmail.com .Sh LICENSE diff --git a/mcomp b/mcomp index c8d41ac..66980f4 100755 --- a/mcomp +++ b/mcomp @@ -19,7 +19,7 @@ draft="snd.$i" echo "Cc: " echo "Bcc: " echo "Subject: " - from=$(mhdr -local-mailbox ~/.santoku/profile) + from=$(mhdr -h local-mailbox ~/.santoku/profile) [ "$from" ] && echo "From: $from" cat ~/.santoku/headers 2>/dev/null echo @@ -28,30 +28,30 @@ draft="snd.$i" *mrepl*) [ "$#" -eq 0 ] && set -- . # XXX reply-all - echo "To: $(mhdr -from "$1")" + echo "To: $(mhdr -h from "$1")" echo "Cc: " echo "Bcc: " - s=$(mhdr -subject "$1") + s=$(mhdr -d -h subject "$1") os= while [ "$os" != "$s" ]; do os=$s - s=${s% } - s=${s%[Rr][Ee]:} - s=${s%[Aa][Ww]:} - s=${s%[Ff][Ww][Dd]:} + s=${s# } + s=${s#[Rr][Ee]:} + s=${s#[Aa][Ww]:} + s=${s#[Ff][Ww][Dd]:} done echo "Subject: Re: $s" cat ~/.santoku/headers 2>/dev/null echo -n "References:" { - mhdr -references "$1" - mhdr -message-id "$1" + mhdr -h references "$1" + mhdr -h message-id "$1" } | sed 's/^[^<]*//g;s/[^>]*$//g;s/>[^<]*\n /' diff --git a/mhdr.c b/mhdr.c index f177c5e..0820c85 100644 --- a/mhdr.c +++ b/mhdr.c @@ -11,22 +11,11 @@ #include "blaze822.h" -static size_t l; -static char *hdr; - -void -header(char *file) -{ - struct message *msg; - - msg = blaze822(file); - if (!msg) - return; - - char *v = blaze822_hdr_(msg, hdr, l); - if (v) - printf("%s\n", v); -} +static char *hflag; +static int Aflag; +static int Dflag; +static int Mflag; +static int dflag; static void printhdr(char *hdr) @@ -43,47 +32,160 @@ printhdr(char *hdr) } void -headerall(char *file) +headerall(struct message *msg) +{ + char *h = 0; + while ((h = blaze822_next_header(msg, h))) { + if (dflag) { + char d[4096]; + blaze822_decode_rfc2047(d, h, sizeof d, "UTF-8"); + printhdr(d); + } else { + printhdr(h); + } + } + + blaze822_free(msg); +} + +void +print_addresses(char *s) +{ + char *disp, *addr; + while ((s = blaze822_addr(s, &disp, &addr))) { + if (disp && addr) { + if (dflag) { + char d[4096]; + blaze822_decode_rfc2047(d, disp, sizeof d, + "UTF-8"); + printf("%s <%s>\n", d, addr); + } else { + printf("%s <%s>\n", disp, addr); + } + } else if (addr) { + printf("%s\n", addr); + } + } +} + +void +print_date(char *s) +{ + time_t t = blaze822_date(s); + if (t == -1) + return; + printf("%ld\n", t); +} + +void +print_decode_header(char *s) +{ + char d[4096]; + blaze822_decode_rfc2047(d, s, sizeof d, "UTF-8"); + printf("%s\n", d); +} + +void +print_header(char *v) +{ + if (Aflag) + print_addresses(v); + else if (Dflag) + print_date(v); + else if (dflag) + print_decode_header(v); + else + printf("%s\n", v); +} + +void +headermany(struct message *msg) +{ + char *hdr = 0; + while ((hdr = blaze822_next_header(msg, hdr))) { + char *h = hflag; + while (*h) { + char *n = strchr(h, ':'); + if (n) + *n = 0; + + size_t l = strlen(h); + if (strncmp(hdr, h, l) == 0 && hdr[l] == ':') { + hdr += l + 1; + while (*hdr == ' ' || *hdr == '\t') + hdr++; + print_header(hdr); + } + + if (n) { + *n = ':'; + h = n + 1; + } else { + break; + } + } + } + + blaze822_free(msg); +} + +void +header(char *file) { struct message *msg; + while (*file == ' ' || *file == '\t') + file++; + msg = blaze822(file); if (!msg) return; - char *h = 0; - while ((h = blaze822_next_header(msg, h))) { - char d[4096]; - blaze822_decode_rfc2047(d, h, sizeof d, "UTF-8"); - - printhdr(d); + if (!hflag) + return headerall(msg); + if (Mflag) + return headermany(msg); + + char *h = hflag; + while (*h) { + char *n = strchr(h, ':'); + if (n) + *n = 0; + char *v = blaze822_chdr(msg, h); + if (v) + print_header(v); + if (n) { + *n = ':'; + h = n + 1; + } else { + break; + } } + + blaze822_free(msg); } int main(int argc, char *argv[]) { - void (*cb)(char *) = headerall; - - if (argc >= 2 && argv[1][0] == '-') { - l = strlen(argv[1])+1; - hdr = malloc(l); - hdr[0] = 0; - char *s = hdr+1; - char *t = argv[1]+1; - while (*t) - *s++ = tolower(*t++); - *s = ':'; - - cb = header; - argc--; - argv++; - } - - if (argc == 1 && isatty(0)) - blaze822_loop1(".", cb); + int c; + while ((c = getopt(argc, argv, "h:ADMdv)) != -1) + switch(c) { + case 'h': hflag = optarg; break; + case 'A': Aflag = 1; break; + case 'D': Dflag = 1; break; + case 'M': Mflag = 1; break; + case 'd': dflag = 1; break; + default: + fprintf(stderr, +"Usage: mhdr [-h header] [-d] [-M] [-A|-D] [msgs...]\n"); + exit(1); + } + + if (argc == optind && isatty(0)) + blaze822_loop1(".", header); else - blaze822_loop(argc-1, argv+1, cb); + blaze822_loop(argc-optind, argv+optind, header); return 0; }