2 ** whom.c -- list recipients of message
4 ** This code is Copyright (c) 2012, by the authors of mmh. See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
10 #include <h/addrsbr.h>
11 #include <h/fmt_scan.h>
16 static struct swit switches[] = {
39 #define HRESENT (1<<1)
44 struct mailname head = {0};
45 struct mailname *mp = &head;
49 static int resent = 0; /* consider normal or resent headers */
50 static int toccsw = 1; /* list sighted recipients */
51 static int bccsw = 1; /* list hidden recipients */
52 static int alisw = 1; /* expand aliases on rcpt addrs */
54 static char *separator = "\t==BCC==";
60 static int process(char *);
61 static void proc_hdr(char *, char *);
62 static int print(void);
63 static int printbcc(void);
64 static void printone(struct mailname *);
68 main(int argc, char **argv)
70 int filep=0, naddrs=0, n;
72 char buf[BUFSIZ], **argp;
73 char **arguments, *files[NFILES];
76 setlocale(LC_ALL, "");
77 invo_name = mhbasename(argv[0]);
79 /* read user profile/context */
82 arguments = getarguments(invo_name, argc, argv, 1);
85 while ((cp = *argp++)) {
87 switch (smatch(++cp, switches)) {
89 ambigsw(cp, switches);
93 adios(EX_USAGE, NULL, "-%s unknown", cp);
96 snprintf(buf, sizeof(buf),
97 "%s [switches] file ...",
99 print_help(buf, switches, 1);
100 exit(argc == 2 ? EX_OK : EX_USAGE);
102 print_version(invo_name);
103 exit(argc == 2 ? EX_OK : EX_USAGE);
127 if (filep > NFILES) {
128 adios(EX_USAGE, NULL, "too many files (more than %d)",
136 adios(EX_USAGE, NULL, "usage: %s [switches] file ...", invo_name);
138 if (!toccsw && !bccsw) {
139 adios(EX_USAGE, NULL, "give -tocc or -bcc or both to produce output");
141 for (filep=0; files[filep]; filep++) {
142 process(files[filep]);
145 cmd = add("ali -list", NULL);
146 if ((n=print()) && alisw) {
147 if (!(in = popen(cmd, "r"))) {
148 adios(EX_IOERR, "popen", "unable to");
150 while (fgets(buf, sizeof buf, in)) {
158 cmd = add("ali -list", NULL);
159 if ((n=printbcc()) && alisw) {
160 if (!(in = popen(cmd, "r"))) {
161 adios(EX_IOERR, "popen", "unable to");
163 while (fgets(buf, sizeof buf, in)) {
170 return naddrs ? 0 : 1;
179 char buf[BUFSIZ], name[NAMESZ];
183 if ((in = fopen(file, "r")) == NULL) {
184 adios(EX_IOERR, file, "unable to open");
187 for (compnum = 1, state = FLD;;) {
188 switch (state = m_getfld(state, name, buf, sizeof(buf), in)) {
197 while (state == FLDPLUS) {
198 state = m_getfld(state, name, buf,
212 adios(EX_DATAERR, NULL, "message format error in component #%d",
216 adios(EX_SOFTWARE, NULL, "getfld() returned %d", state);
226 ** Check if the header contains addresses we're interested in.
227 ** If so, extract the addresses and add them to the global list.
230 proc_hdr(char *name, char *val)
235 while (*val==' ' || *val=='\t' || *val=='\n') {
238 if (strncasecmp(name, "resent-", 7)==0) {
241 if (mh_strcasecmp(name, "to")==0) {
243 } else if (mh_strcasecmp(name, "cc")==0) {
245 } else if (mh_strcasecmp(name, "bcc")==0) {
247 } else if (mh_strcasecmp(name, "resent-to")==0) {
248 type = (HRESENT | HTO);
249 } else if (mh_strcasecmp(name, "resent-cc")==0) {
250 type = (HRESENT | HCC);
251 } else if (mh_strcasecmp(name, "resent-bcc")==0) {
252 type = (HRESENT | HBCC);
254 /* ignore non-recpient headers */
258 /* ignore recipient headers we are not interested in */
259 if ((type&HTO || type&HCC) && !toccsw) {
262 if ((type&HBCC) && !bccsw) {
266 while ((cp = getname(val))) {
267 if (!(mp->m_next = getm(cp, NULL, 0, AD_NAME, NULL))) {
268 adios(EX_DATAERR, NULL, "illegal address: %s", cp);
271 if (mp->m_type == BADHOST) {
272 admonish(NULL, "bad address `%s'", mp->m_text);
281 ** Walk through the list of addresses and print the right ones.
288 for (mp=head.m_next; mp; mp=mp->m_next) {
289 /* skip unless both are resent or neither one is */
290 if (resent != (mp->m_type&HRESENT)) {
293 if (mp->m_type & (HTO|HCC)) {
302 ** Walk through the list of addresses and print the right ones.
309 for (mp=head.m_next; mp; mp=mp->m_next) {
310 /* skip unless both are resent or neither one is */
311 if (resent != (mp->m_type&HRESENT)) {
314 if (mp->m_type & HBCC) {
315 if (!naddrs && toccsw) {
327 ** Print one single address in appropriate form.
330 printone(struct mailname *mp)
335 snprintf(buf, sizeof buf, " %s@%s", mp->m_mbox, mp->m_host);
337 snprintf(buf, sizeof buf, " %s", mp->m_mbox);