From 204c305913a20d207cba063ec2da8d0275d2da5d Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Fri, 6 Jul 2012 17:51:37 +0200 Subject: [PATCH] Re-added whom(1). This implementation is written from scratch. This new version of whom(1) is quite different to the old one, yet it serves the same purpose: listing the recipients of a message. It still misses the ability to process +folder and msgs arguments. As this implementation is new and not much practically tested, it may change in the future, if flaws appear. --- man/Makefile.in | 2 +- man/whom.man1 | 83 ++++++++++++++ uip/Makefile.in | 7 +- uip/whom.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 432 insertions(+), 3 deletions(-) create mode 100644 man/whom.man1 create mode 100644 uip/whom.c diff --git a/man/Makefile.in b/man/Makefile.in index cf79c47..5b34a34 100644 --- a/man/Makefile.in +++ b/man/Makefile.in @@ -54,7 +54,7 @@ MAN1SRC = ali. anno. burst. comp. dist. flist. flists. folder. folders. \ mhmail. mhparam. mhpath. mhstore. new. fnext. \ fprev. unseen. next. packf. pick. prev. prompter. rcvdist. rcvpack. \ rcvstore. refile. repl. rmf. rmm. scan. send. sendfiles. \ - show. slocal. sortm. whatnow. + show. slocal. sortm. whatnow. whom. MAN5SRC = mh-alias. mh-format. mh-mail. mh-profile. mh-tailor. diff --git a/man/whom.man1 b/man/whom.man1 new file mode 100644 index 0000000..718ef2e --- /dev/null +++ b/man/whom.man1 @@ -0,0 +1,83 @@ +.\" +.\" %nmhwarning% +.\" +.TH WHOM %manext1% "%nmhdate%" MH.6.8 [%nmhversion%] +.SH NAME +whom \- report to whom a message would go +.SH SYNOPSIS +.HP 5 +.na +.B whom +.RB [ \-tocc " | " \-notocc ] +.RB [ \-bcc " | " \-nobcc ] +.RB [ \-alias " | " \-noalias ] +.RB [ \-Version ] +.RB [ \-help ] +.IR file ... +.ad +.SH DESCRIPTION +.B Whom +is used to list the recipient addresses in the headers of a message. +.PP +Per default, +.B whom +lists both, sighted and hidden, recipients. +The +.BR \-notocc +option suppresses the listing of sighted recipients. +The +.BR \-nobcc +option suppresses the listing of hidden recipients. +If both kinds of recipients are requested, they are separated by a +line similar to ``\0==BCC==''. +The actual separator may change, but the regular expression +/^[\0\\t].*BCC/ should always match. +.PP +With +.BR \-alias , +aliases for all recipients are expanded, according to the +alias files given by the `Aliasfile:' profile entry. +This is somehow similar to running: + +.RS 5 +.nf +ali `whom /path/to/msg` +.fi +.RE + +.SH FILES +.fc ^ ~ +.nf +.ta \w'%etcdir%/ExtraBigFileName 'u +^$HOME/.mmh/profile~^The user profile +.fi + +.SH "PROFILE COMPONENTS" +.fc ^ ~ +.nf +.ta 2.4i +.ta \w'ExtraBigProfileName 'u +^Path:~^To determine the user's mail storage +^Aliasfile:~^For default alias files +.fi + +.SH "SEE ALSO" +mh\-alias(5), spost(8) + +.SH DEFAULTS +.nf +.RB ` \-tocc ' +.RB ` \-bcc ' +.RB ` \-alias ' +.fi + +.SH CONTEXT +None + +.SH BUGS +.B whom +does not (yet) accept +.I msg +and +.I +folder +arguments. diff --git a/uip/Makefile.in b/uip/Makefile.in index 04df405..f0c258e 100644 --- a/uip/Makefile.in +++ b/uip/Makefile.in @@ -51,7 +51,7 @@ CMDS = ali anno burst comp dist flist folder forw mmh mark \ mhbuild mhl \ mhlist mhmail mhparam mhpath mhstore new packf pick \ print-mimetype prompter rcvdist rcvpack rcvstore refile repl rmf \ - rmm scan send sendfiles show slocal sortm spost whatnow + rmm scan send sendfiles show slocal sortm spost whatnow whom # commands that are links to other commands LCMDS = flists folders next prev fnext fprev unseen @@ -73,7 +73,7 @@ SRCS = ali.c aliasbr.c anno.c ap.c burst.c comp.c \ prompter.c rcvdist.c rcvpack.c rcvstore.c \ refile.c repl.c rmf.c rmm.c scan.c scansbr.c send.c \ sendfiles.sh slocal.c sortm.c spost.c termsbr.c \ - whatnow.c whatnowproc.c + whatnow.c whatnowproc.c whom.c # auxiliary files AUX = Makefile.in @@ -220,6 +220,9 @@ spost: spost.o aliasbr.o $(LOCALLIBS) whatnow: whatnow.o $(LOCALLIBS) $(LINK) whatnow.o $(LINKLIBS) +whom: whom.o $(LOCALLIBS) + $(LINK) whom.o $(LINKLIBS) + # ========== DEPENDENCIES FOR INSTALLING ========== # install everything 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); + } +} -- 1.7.10.4