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[] = {
40 char *version=VERSION;
44 #define HRESENT (1<<1)
50 struct mailname head = {0};
51 struct mailname *mp = &head;
55 static int resent = 0; /* consider normal or resent headers */
56 static int toccsw = 1; /* list sighted recipients */
57 static int dccsw = 1; /* list hidden dcc recipients */
58 static int bccsw = 1; /* list hidden bcc recipients */
59 static int alisw = 1; /* expand aliases on rcpt addrs */
61 static char *dccsep = "\t==DCC==";
62 static char *bccsep = "\t==BCC==";
68 static int process(char *);
69 static void proc_hdr(char *, char *);
70 static int print(void);
71 static int printdcc(void);
72 static int printbcc(void);
73 static void printone(struct mailname *);
77 main(int argc, char **argv)
79 int filep=0, naddrs=0, n;
81 char buf[BUFSIZ], **argp;
82 char **arguments, *files[NFILES];
85 setlocale(LC_ALL, "");
86 invo_name = mhbasename(argv[0]);
88 /* read user profile/context */
91 arguments = getarguments(invo_name, argc, argv, 1);
94 while ((cp = *argp++)) {
96 switch (smatch(++cp, switches)) {
98 ambigsw(cp, switches);
102 adios(EX_USAGE, NULL, "-%s unknown", cp);
105 snprintf(buf, sizeof(buf),
106 "%s [switches] file ...",
108 print_help(buf, switches, 1);
109 exit(argc == 2 ? EX_OK : EX_USAGE);
111 print_version(invo_name);
112 exit(argc == 2 ? EX_OK : EX_USAGE);
143 if (filep > NFILES) {
144 adios(EX_USAGE, NULL, "too many files (more than %d)",
152 adios(EX_USAGE, NULL, "usage: %s [switches] file ...", invo_name);
154 if (!toccsw && !dccsw && !bccsw) {
155 adios(EX_USAGE, NULL, "use at least one of: -tocc -dcc -bcc");
157 for (filep=0; files[filep]; filep++) {
158 process(files[filep]);
161 cmd = add("ali -list", NULL);
162 if ((n=print()) && alisw) {
163 if (!(in = popen(cmd, "r"))) {
164 adios(EX_IOERR, "popen", "unable to");
166 while (fgets(buf, sizeof buf, in)) {
174 cmd = add("ali -list", NULL);
175 if ((n=printdcc()) && alisw) {
176 if (!(in = popen(cmd, "r"))) {
177 adios(EX_IOERR, "popen", "unable to");
179 while (fgets(buf, sizeof buf, in)) {
187 cmd = add("ali -list", NULL);
188 if ((n=printbcc()) && alisw) {
189 if (!(in = popen(cmd, "r"))) {
190 adios(EX_IOERR, "popen", "unable to");
192 while (fgets(buf, sizeof buf, in)) {
200 return naddrs ? 0 : 1;
208 struct field f = {{0}};
213 if ((in = fopen(file, "r")) == NULL) {
214 adios(EX_IOERR, file, "unable to open");
217 for (compnum=1, state=FLD2;; compnum++) {
218 switch (state = m_getfld2(state, &f, in)) {
223 proc_hdr(f.name, f.value);
231 advise(NULL, "message format error in component #%d", compnum);
235 adios(EX_DATAERR, NULL, "message format error in component #%d",
239 adios(EX_SOFTWARE, NULL, "getfld() returned %d", state);
249 ** Check if the header contains addresses we're interested in.
250 ** If so, extract the addresses and add them to the global list.
253 proc_hdr(char *name, char *val)
258 while (*val==' ' || *val=='\t' || *val=='\n') {
261 if (strncasecmp(name, "resent-", 7)==0) {
264 if (mh_strcasecmp(name, "to")==0) {
266 } else if (mh_strcasecmp(name, "cc")==0) {
268 } else if (mh_strcasecmp(name, "dcc")==0) {
270 } else if (mh_strcasecmp(name, "bcc")==0) {
272 } else if (mh_strcasecmp(name, "resent-to")==0) {
273 type = (HRESENT | HTO);
274 } else if (mh_strcasecmp(name, "resent-cc")==0) {
275 type = (HRESENT | HCC);
276 } else if (mh_strcasecmp(name, "resent-dcc")==0) {
277 type = (HRESENT | HDCC);
278 } else if (mh_strcasecmp(name, "resent-bcc")==0) {
279 type = (HRESENT | HBCC);
281 /* ignore non-recpient headers */
285 /* ignore recipient headers we are not interested in */
286 if ((type&HTO || type&HCC) && !toccsw) {
289 if ((type&HDCC) && !dccsw) {
292 if ((type&HBCC) && !bccsw) {
296 while ((cp = getname(val))) {
297 if (!(mp->m_next = getm(cp, NULL, 0, AD_NAME, NULL))) {
298 adios(EX_DATAERR, NULL, "illegal address: %s", cp);
301 if (mp->m_type == BADHOST) {
302 admonish(NULL, "bad address `%s'", mp->m_text);
311 ** Walk through the list of addresses and print the right ones.
318 for (mp=head.m_next; mp; mp=mp->m_next) {
319 /* skip unless both are resent or neither one is */
320 if (resent != (mp->m_type&HRESENT)) {
323 if (mp->m_type & (HTO|HCC)) {
332 ** Walk through the list of addresses and print the right ones.
339 for (mp=head.m_next; mp; mp=mp->m_next) {
340 /* skip unless both are resent or neither one is */
341 if (resent != (mp->m_type&HRESENT)) {
344 if (mp->m_type & HDCC) {
345 if (!naddrs && (toccsw || bccsw)) {
356 ** Walk through the list of addresses and print the right ones.
363 for (mp=head.m_next; mp; mp=mp->m_next) {
364 /* skip unless both are resent or neither one is */
365 if (resent != (mp->m_type&HRESENT)) {
368 if (mp->m_type & HBCC) {
369 if (!naddrs && (toccsw || dccsw)) {
381 ** Print one single address in appropriate form.
384 printone(struct mailname *mp)
389 snprintf(buf, sizeof buf, " %s@%s", mp->m_mbox, mp->m_host);
391 snprintf(buf, sizeof buf, " %s", mp->m_mbox);