X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=uip%2Fwhom.c;fp=uip%2Fwhom.c;h=0451699b545de152d0337fd8330887739ac3c44f;hb=204c305913a20d207cba063ec2da8d0275d2da5d;hp=0000000000000000000000000000000000000000;hpb=c3b491e413335224388481939948dd6af4179851;p=mmh diff --git a/uip/whom.c b/uip/whom.c new file mode 100644 index 0000000..0451699 --- /dev/null +++ b/uip/whom.c @@ -0,0 +1,343 @@ +/* +** whom.c -- list recipients of message +** +** This code is Copyright (c) 2012, by the authors of mmh. See the +** COPYRIGHT file in the root directory of the nmh distribution for +** complete copyright information. +*/ + +#include +#include +#include +#include + +static struct swit switches[] = { +#define VERSIONSW 0 + { "Version", 0 }, +#define HELPSW 1 + { "help", 0 }, +#define TOCCSW 2 + { "tocc", 0 }, +#define NTOCCSW 3 + { "notocc", 2 }, +#define BCCSW 4 + { "bcc", 0 }, +#define NBCCSW 5 + { "nobcc", 2 }, +#define ALISW 6 + { "alias", 0 }, +#define NALISW 7 + { "noalias", 2 }, + { NULL, 0 } +}; + + +#define NFILES 32 + +#define HRESENT (1<<1) +#define HTO (1<<2) +#define HCC (1<<3) +#define HBCC (1<<4) + +struct mailname head = {0}; +struct mailname *mp = &head; + +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 alisw = 1; /* expand aliases on rcpt addrs */ + +static char *separator = "\t==BCC=="; + + +/* +** static prototypes +*/ +static int process(char *); +static void proc_hdr(char *, char *); +static int print(void); +static int printbcc(void); +static void printone(struct mailname *); + + +int +main(int argc, char **argv) +{ + int filep=0, naddrs=0, n; + char *cp; + char buf[BUFSIZ], **argp; + char **arguments, *files[NFILES]; + FILE *in; + + setlocale(LC_ALL, ""); + invo_name = mhbasename(argv[0]); + + /* read user profile/context */ + context_read(); + + arguments = getarguments(invo_name, argc, argv, 1); + argp = arguments; + + while ((cp = *argp++)) { + if (*cp == '-') { + switch (smatch(++cp, switches)) { + case AMBIGSW: + ambigsw(cp, switches); + done(1); + + case UNKWNSW: + adios(NULL, "-%s unknown", cp); + + case HELPSW: + snprintf(buf, sizeof(buf), + "%s [switches] file ...", + invo_name); + print_help(buf, switches, 1); + done(1); + case VERSIONSW: + print_version(invo_name); + done(1); + + case TOCCSW: + toccsw = 1; + continue; + case NTOCCSW: + toccsw = 0; + continue; + + case BCCSW: + bccsw = 1; + continue; + case NBCCSW: + bccsw = 0; + continue; + + case ALISW: + alisw = 1; + continue; + case NALISW: + alisw = 0; + continue; + } + } + if (filep > NFILES) { + adios(NULL, "too many files (more than %d)", + NFILES); + } else { + files[filep++] = cp; + } + } + files[filep] = NULL; + if (!filep) { + adios(NULL, "usage: %s [switches] file ...", invo_name); + } + if (!toccsw && !bccsw) { + adios(NULL, "give -tocc or -bcc or both to produce output"); + } + for (filep=0; files[filep]; filep++) { + process(files[filep]); + } + + cmd = add("ali -list", NULL); + if ((n=print()) && alisw) { + if (!(in = popen(cmd, "r"))) { + adios("popen", "unable to"); + } + while (fgets(buf, sizeof buf, in)) { + fputs(buf, stdout); + } + pclose(in); + } + free(cmd); + naddrs += n; + + if (toccsw && bccsw) { + puts(separator); + } + + cmd = add("ali -list", NULL); + if ((n=printbcc()) && alisw) { + if (!(in = popen(cmd, "r"))) { + adios("popen", "unable to"); + } + while (fgets(buf, sizeof buf, in)) { + fputs(buf, stdout); + } + pclose(in); + } + free(cmd); + naddrs += n; + return naddrs ? 0 : 1; +} + + +static int +process(char *file) +{ + int state, compnum; + char *cp; + char buf[BUFSIZ], name[NAMESZ]; + FILE *in; + + + if ((in = fopen(file, "r")) == NULL) { + adios(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); + 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: + break; + + case LENERR: + case FMTERR: + adios(NULL, "message format error in component #%d", + compnum); + + default: + adios(NULL, "getfld() returned %d", state); + } + break; + } + fclose(in); + return 0; +} + + +/* +** Check if the header contains addresses we're interested in. +** If so, extract the addresses and add them to the global list. +*/ +static void +proc_hdr(char *name, char *val) +{ + char *cp; + int type = 0; + + while (*val==' ' || *val=='\t' || *val=='\n') { + val++; + } + if (strncasecmp(name, "resent-", 7)==0) { + resent = HRESENT; + } + if (mh_strcasecmp(name, "to")==0) { + type = HTO; + } else if (mh_strcasecmp(name, "cc")==0) { + type = HCC; + } 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-bcc")==0) { + type = (HRESENT | HBCC); + } + /* ignore non-recpient headers */ + if (!type) { + return; + } + /* ignore recipient headers we are not interested in */ + if ((type&HTO || type&HCC) && !toccsw) { + 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); + } + mp = mp->m_next; + if (mp->m_type == BADHOST) { + admonish(NULL, "bad address `%s'", mp->m_text); + continue; + } + mp->m_type = type; + } +} + + +/* +** Walk through the list of addresses and print the right ones. +*/ +static int +print(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 & (HTO|HCC)) { + naddrs++; + printone(mp); + } + } + return naddrs; +} + +/* +** Walk through the list of addresses and print the right ones. +*/ +static int +printbcc(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 & HBCC) { + naddrs++; + printone(mp); + } + } + return naddrs; +} + + +/* +** Print one single address in appropriate form. +*/ +static void +printone(struct mailname *mp) +{ + char buf[BUFSIZ]; + + if (mp->m_host) { + snprintf(buf, sizeof buf, " %s@%s", mp->m_mbox, mp->m_host); + } else { + snprintf(buf, sizeof buf, " %s", mp->m_mbox); + } + if (alisw) { + cmd = add(buf, cmd); + } else { + puts(buf+1); + } +}