+main(int argc, char **argv)
+{
+ int naddrs=0, n;
+ char *cp;
+ char buf[BUFSIZ], **argp;
+ char **arguments;
+ char *folder = NULL;
+ FILE *in;
+ struct msgs_array msgs = {0};
+ struct msgs_array files = {0};
+ size_t filep;
+
+ 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);
+ exit(EX_USAGE);
+
+ case UNKWNSW:
+ adios(EX_USAGE, NULL, "-%s unknown", cp);
+
+ case HELPSW:
+ snprintf(buf, sizeof(buf),
+ "%s [switches] file ...",
+ invo_name);
+ print_help(buf, switches, 1);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+ case VERSIONSW:
+ print_version(invo_name);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+
+ case TOCCSW:
+ toccsw = 1;
+ continue;
+ case NTOCCSW:
+ toccsw = 0;
+ continue;
+
+ case DCCSW:
+ dccsw = 1;
+ continue;
+ case NDCCSW:
+ dccsw = 0;
+ continue;
+
+ case BCCSW:
+ bccsw = 1;
+ continue;
+ case NBCCSW:
+ bccsw = 0;
+ continue;
+
+ case ALISW:
+ alisw = 1;
+ continue;
+ case NALISW:
+ alisw = 0;
+ continue;
+ }
+ }
+ if (*cp == '+' || *cp == '@') {
+ if (folder) {
+ adios(EX_USAGE, NULL, "only one folder at a time!");
+ } else {
+ folder = mh_xstrdup(expandfol(cp));
+ }
+ } else {
+ app_msgarg(&msgs, cp);
+ }
+ }
+ 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 (parse_msgs(&msgs, folder, &files) < 0) {
+ exit(EX_IOERR);
+ }
+ for (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(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);
+ }
+ mh_free0(&cmd);
+ naddrs += n;
+
+ cmd = add("ali -list", NULL);
+ if ((n=printbcc()) && alisw) {
+ if (!(in = popen(cmd, "r"))) {
+ adios(EX_IOERR, "popen", "unable to");
+ }
+ while (fgets(buf, sizeof buf, in)) {
+ fputs(buf, stdout);
+ }
+ pclose(in);
+ }
+ mh_free0(&cmd);
+ naddrs += n;
+
+ return naddrs ? 0 : 1;
+}
+
+
+static int
+process(char *file)
+{
+ enum state state;
+ struct field f = {{0}};
+ int compnum;
+ FILE *in;
+
+
+ if ((in = fopen(file, "r")) == NULL) {
+ adios(EX_IOERR, file, "unable to open");
+ }
+
+ 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 BODY2:
+ case FILEEOF2:
+ break;
+
+ 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(EX_SOFTWARE, 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, "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);
+ }
+ /* ignore non-recpient headers */
+ if (!type) {
+ return;
+ }
+ /* ignore recipient headers we are not interested in */
+ 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(EX_DATAERR, 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)