X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fwhom.c;h=e664f4b29b31d2344cd733cd4a56c3365ee3e033;hp=8ffe8b83b6f402ecd8a0d61b4d995b98b6d647f2;hb=5b483b0b8517541a8359d7049b4497c6efcb117e;hpb=921ea2dd0444ebe67a980b54b8017125d371c8e6 diff --git a/uip/whom.c b/uip/whom.c index 8ffe8b8..e664f4b 100644 --- a/uip/whom.c +++ b/uip/whom.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include static struct swit switches[] = { #define VERSIONSW 0 @@ -20,24 +22,30 @@ static struct swit switches[] = { { "tocc", 0 }, #define NTOCCSW 3 { "notocc", 2 }, -#define BCCSW 4 +#define DCCSW 4 + { "dcc", 0 }, +#define NDCCSW 5 + { "nodcc", 2 }, +#define BCCSW 6 { "bcc", 0 }, -#define NBCCSW 5 +#define NBCCSW 7 { "nobcc", 2 }, -#define ALISW 6 +#define ALISW 8 { "alias", 0 }, -#define NALISW 7 +#define NALISW 9 { "noalias", 2 }, { NULL, 0 } }; +char *version=VERSION; #define NFILES 32 #define HRESENT (1<<1) #define HTO (1<<2) #define HCC (1<<3) -#define HBCC (1<<4) +#define HDCC (1<<4) +#define HBCC (1<<5) struct mailname head = {0}; struct mailname *mp = &head; @@ -46,10 +54,12 @@ static char *cmd; static int resent = 0; /* consider normal or resent headers */ static int toccsw = 1; /* list sighted recipients */ -static int bccsw = 1; /* list hidden recipients */ +static int dccsw = 1; /* list hidden dcc recipients */ +static int bccsw = 1; /* list hidden bcc recipients */ static int alisw = 1; /* expand aliases on rcpt addrs */ -static char *separator = "\t==BCC=="; +static char *dccsep = "\t==DCC=="; +static char *bccsep = "\t==BCC=="; /* @@ -58,6 +68,7 @@ static char *separator = "\t==BCC=="; static int process(char *); static void proc_hdr(char *, char *); static int print(void); +static int printdcc(void); static int printbcc(void); static void printone(struct mailname *); @@ -65,11 +76,14 @@ static void printone(struct mailname *); int main(int argc, char **argv) { - int filep=0, naddrs=0, n; + int naddrs=0, n; char *cp; char buf[BUFSIZ], **argp; - char **arguments, *files[NFILES]; + char **arguments; + char *folder = NULL; FILE *in; + struct msgs_array msgs = {0}; + struct msgs_array files = {0}; setlocale(LC_ALL, ""); invo_name = mhbasename(argv[0]); @@ -85,20 +99,20 @@ main(int argc, char **argv) switch (smatch(++cp, switches)) { case AMBIGSW: ambigsw(cp, switches); - done(1); + exit(EX_USAGE); case UNKWNSW: - adios(NULL, "-%s unknown", cp); + adios(EX_USAGE, NULL, "-%s unknown", cp); case HELPSW: snprintf(buf, sizeof(buf), "%s [switches] file ...", invo_name); print_help(buf, switches, 1); - done(1); + exit(argc == 2 ? EX_OK : EX_USAGE); case VERSIONSW: print_version(invo_name); - done(1); + exit(argc == 2 ? EX_OK : EX_USAGE); case TOCCSW: toccsw = 1; @@ -107,6 +121,13 @@ main(int argc, char **argv) toccsw = 0; continue; + case DCCSW: + dccsw = 1; + continue; + case NDCCSW: + dccsw = 0; + continue; + case BCCSW: bccsw = 1; continue; @@ -122,49 +143,68 @@ main(int argc, char **argv) continue; } } - if (filep > NFILES) { - adios(NULL, "too many files (more than %d)", - NFILES); + if (*cp == '+' || *cp == '@') { + if (folder) { + adios(EX_USAGE, NULL, "only one folder at a time!"); + } else { + folder = mh_xstrdup(expandfol(cp)); + } } else { - files[filep++] = cp; + app_msgarg(&msgs, cp); } } - files[filep] = NULL; - if (!filep) { - adios(NULL, "usage: %s [switches] file ...", invo_name); + if (!msgs.size) { + adios(EX_USAGE, NULL, "usage: %s [switches] file ...", invo_name); + } + if (!toccsw && !dccsw && !bccsw) { + adios(EX_USAGE, NULL, "use at least one of: -tocc -dcc -bcc"); } - if (!toccsw && !bccsw) { - adios(NULL, "give -tocc or -bcc or both to produce output"); + if (parse_msgs(&msgs, folder, &files) < 0) { + exit(EX_IOERR); } - for (filep=0; files[filep]; filep++) { - process(files[filep]); + for (size_t filep = 0; filep < files.size; filep++) { + process(files.msgs[filep]); } cmd = add("ali -list", NULL); if ((n=print()) && alisw) { if (!(in = popen(cmd, "r"))) { - adios("popen", "unable to"); + adios(EX_IOERR, "popen", "unable to"); + } + while (fgets(buf, sizeof buf, in)) { + fputs(buf, stdout); + } + pclose(in); + } + mh_free0(&cmd); + naddrs += n; + + cmd = add("ali -list", NULL); + if ((n=printdcc()) && alisw) { + if (!(in = popen(cmd, "r"))) { + adios(EX_IOERR, "popen", "unable to"); } while (fgets(buf, sizeof buf, in)) { fputs(buf, stdout); } pclose(in); } - free(cmd); + mh_free0(&cmd); naddrs += n; cmd = add("ali -list", NULL); if ((n=printbcc()) && alisw) { if (!(in = popen(cmd, "r"))) { - adios("popen", "unable to"); + adios(EX_IOERR, "popen", "unable to"); } while (fgets(buf, sizeof buf, in)) { fputs(buf, stdout); } pclose(in); } - free(cmd); + mh_free0(&cmd); naddrs += n; + return naddrs ? 0 : 1; } @@ -172,46 +212,39 @@ main(int argc, char **argv) static int process(char *file) { - int state, compnum; - char *cp; - char buf[BUFSIZ], name[NAMESZ]; + enum state state; + struct field f = {{0}}; + int compnum; FILE *in; if ((in = fopen(file, "r")) == NULL) { - adios(file, "unable to open"); + adios(EX_IOERR, file, "unable to open"); } - for (compnum = 1, state = FLD;;) { - switch (state = m_getfld(state, name, buf, sizeof(buf), in)) { - case FLD: - compnum++; - proc_hdr(name, buf); + for (compnum=1, state=FLD2;; compnum++) { + switch (state = m_getfld2(state, &f, in)) { + case LENERR2: + state = FLD2; + /* FALL */ + case FLD2: + proc_hdr(f.name, f.value); continue; - case FLDPLUS: - compnum++; - cp = add(buf, cp); - while (state == FLDPLUS) { - state = m_getfld(state, name, buf, - sizeof(buf), in); - cp = add(buf, cp); - } - proc_hdr(name, cp); - free(cp); - continue; - - case BODY: - case FILEEOF: + case BODY2: + case FILEEOF2: break; - case LENERR: - case FMTERR: - adios(NULL, "message format error in component #%d", + case FMTERR2: + advise(NULL, "message format error in component #%d", compnum); + continue; + + case IOERR2: + adios(EX_DATAERR, NULL, "message format error in component #%d", compnum); default: - adios(NULL, "getfld() returned %d", state); + adios(EX_SOFTWARE, NULL, "getfld() returned %d", state); } break; } @@ -240,12 +273,16 @@ proc_hdr(char *name, char *val) type = HTO; } else if (mh_strcasecmp(name, "cc")==0) { type = HCC; + } else if (mh_strcasecmp(name, "dcc")==0) { + type = HDCC; } else if (mh_strcasecmp(name, "bcc")==0) { type = HBCC; } else if (mh_strcasecmp(name, "resent-to")==0) { type = (HRESENT | HTO); } else if (mh_strcasecmp(name, "resent-cc")==0) { type = (HRESENT | HCC); + } else if (mh_strcasecmp(name, "resent-dcc")==0) { + type = (HRESENT | HDCC); } else if (mh_strcasecmp(name, "resent-bcc")==0) { type = (HRESENT | HBCC); } @@ -257,13 +294,16 @@ proc_hdr(char *name, char *val) if ((type&HTO || type&HCC) && !toccsw) { return; } + if ((type&HDCC) && !dccsw) { + return; + } if ((type&HBCC) && !bccsw) { return; } while ((cp = getname(val))) { if (!(mp->m_next = getm(cp, NULL, 0, AD_NAME, NULL))) { - adios(NULL, "illegal address: %s", cp); + adios(EX_DATAERR, NULL, "illegal address: %s", cp); } mp = mp->m_next; if (mp->m_type == BADHOST) { @@ -300,6 +340,30 @@ print(void) ** Walk through the list of addresses and print the right ones. */ static int +printdcc(void) +{ + int naddrs = 0; + + for (mp=head.m_next; mp; mp=mp->m_next) { + /* skip unless both are resent or neither one is */ + if (resent != (mp->m_type&HRESENT)) { + continue; + } + if (mp->m_type & HDCC) { + if (!naddrs && (toccsw || bccsw)) { + puts(dccsep); + } + naddrs++; + printone(mp); + } + } + return naddrs; +} + +/* +** Walk through the list of addresses and print the right ones. +*/ +static int printbcc(void) { int naddrs = 0; @@ -310,8 +374,8 @@ printbcc(void) continue; } if (mp->m_type & HBCC) { - if (!naddrs && toccsw) { - puts(separator); + if (!naddrs && (toccsw || dccsw)) { + puts(bccsep); } naddrs++; printone(mp);