add free_field as standard for struct field
[mmh] / uip / whom.c
index 57fddc8..c4e7e8f 100644 (file)
@@ -10,6 +10,8 @@
 #include <h/addrsbr.h>
 #include <h/fmt_scan.h>
 #include <h/utils.h>
+#include <locale.h>
+#include <sysexits.h>
 
 static struct swit switches[] = {
 #define VERSIONSW 0
@@ -20,13 +22,17 @@ static struct swit switches[] = {
        { "tocc", 0 },
 #define NTOCCSW 3
        { "notocc", 2 },
-#define BCCSW 4
+#define DCCSW 4
+       { "dcc", 0 },
+#define NDCCSW 5
+       { "nodcc", 2 },
+#define BCCSW 6
        { "bcc", 0 },
-#define NBCCSW 5
+#define NBCCSW 7
        { "nobcc", 2 },
-#define ALISW 6
+#define ALISW 8
        { "alias", 0 },
-#define NALISW 7
+#define NALISW 9
        { "noalias", 2 },
        { NULL, 0 }
 };
@@ -37,7 +43,8 @@ static struct swit switches[] = {
 #define HRESENT (1<<1)
 #define HTO (1<<2)
 #define HCC (1<<3)
-#define HBCC (1<<4)
+#define HDCC (1<<4)
+#define HBCC (1<<5)
 
 struct mailname head = {0};
 struct mailname *mp = &head;
@@ -46,10 +53,12 @@ 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 dccsw = 1;  /* list hidden dcc recipients */
+static int bccsw = 1;  /* list hidden bcc recipients */
 static int alisw = 1;  /* expand aliases on rcpt addrs */
 
-static char *separator = "\t==BCC==";
+static char *dccsep = "\t==DCC==";
+static char *bccsep = "\t==BCC==";
 
 
 /*
@@ -58,6 +67,7 @@ static char *separator = "\t==BCC==";
 static int process(char *);
 static void proc_hdr(char *, char *);
 static int print(void);
+static int printdcc(void);
 static int printbcc(void);
 static void printone(struct mailname *);
 
@@ -85,20 +95,20 @@ main(int argc, char **argv)
                        switch (smatch(++cp, switches)) {
                        case AMBIGSW:
                                ambigsw(cp, switches);
-                               done(1);
+                               exit(EX_USAGE);
 
                        case UNKWNSW:
-                               adios(NULL, "-%s unknown", cp);
+                               adios(EX_USAGE, NULL, "-%s unknown", cp);
 
                        case HELPSW:
                                snprintf(buf, sizeof(buf),
                                                "%s [switches] file ...",
                                                invo_name);
                                print_help(buf, switches, 1);
-                               done(1);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
                        case VERSIONSW:
                                print_version(invo_name);
-                               done(1);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
 
                        case TOCCSW:
                                toccsw = 1;
@@ -107,6 +117,13 @@ main(int argc, char **argv)
                                toccsw = 0;
                                continue;
 
+                       case DCCSW:
+                               dccsw = 1;
+                               continue;
+                       case NDCCSW:
+                               dccsw = 0;
+                               continue;
+
                        case BCCSW:
                                bccsw = 1;
                                continue;
@@ -123,7 +140,7 @@ main(int argc, char **argv)
                        }
                }
                if (filep > NFILES) {
-                       adios(NULL, "too many files (more than %d)",
+                       adios(EX_USAGE, NULL, "too many files (more than %d)",
                                        NFILES);
                } else {
                        files[filep++] = cp;
@@ -131,10 +148,10 @@ main(int argc, char **argv)
        }
        files[filep] = NULL;
        if (!filep) {
-               adios(NULL, "usage: %s [switches] file ...", invo_name);
+               adios(EX_USAGE, NULL, "usage: %s [switches] file ...", invo_name);
        }
-       if (!toccsw && !bccsw) {
-               adios(NULL, "give -tocc or -bcc or both to produce output");
+       if (!toccsw && !dccsw && !bccsw) {
+               adios(EX_USAGE, NULL, "use at least one of: -tocc -dcc -bcc");
        }
        for (filep=0; files[filep]; filep++) {
                process(files[filep]);
@@ -143,7 +160,20 @@ main(int argc, char **argv)
        cmd = add("ali -list", NULL);
        if ((n=print()) && alisw) {
                if (!(in = popen(cmd, "r"))) {
-                       adios("popen", "unable to");
+                       adios(EX_IOERR, "popen", "unable to");
+               }
+               while (fgets(buf, sizeof buf, in)) {
+                       fputs(buf, stdout);
+               }
+               pclose(in);
+       }
+       free(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);
@@ -156,7 +186,7 @@ main(int argc, char **argv)
        cmd = add("ali -list", NULL);
        if ((n=printbcc()) && alisw) {
                if (!(in = popen(cmd, "r"))) {
-                       adios("popen", "unable to");
+                       adios(EX_IOERR, "popen", "unable to");
                }
                while (fgets(buf, sizeof buf, in)) {
                        fputs(buf, stdout);
@@ -165,6 +195,7 @@ main(int argc, char **argv)
        }
        free(cmd);
        naddrs += n;
+
        return naddrs ? 0 : 1;
 }
 
@@ -172,46 +203,34 @@ main(int argc, char **argv)
 static int
 process(char *file)
 {
-        int state, compnum;
-       char *cp = NULL;
-       char buf[BUFSIZ], name[NAMESZ];
+       enum state state;
+       struct field f = free_field;
+       int compnum;
        FILE *in;
 
 
        if ((in = fopen(file, "r")) == NULL) {
-               adios(file, "unable to open");
+               adios(EX_IOERR, 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);
+       for (compnum=1, state=FLD2;; compnum++) {
+               switch (state = m_getfld2(state, &f, in)) {
+               case FLD2:
+                       proc_hdr(f.name, f.value);
                        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:
+               case BODY2:
+               case FILEEOF2:
                        break;
 
-               case LENERR:
-               case FMTERR:
-                       adios(NULL, "message format error in component #%d",
+               case LENERR2:
+               case FMTERR2:
+               case IOERR2:
+                       adios(EX_DATAERR, NULL, "message format error in component #%d",
                                        compnum);
 
                default:
-                       adios(NULL, "getfld() returned %d", state);
+                       adios(EX_SOFTWARE, NULL, "getfld() returned %d", state);
                }
                break;
        }
@@ -240,12 +259,16 @@ proc_hdr(char *name, char *val)
                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);
        }
@@ -257,13 +280,16 @@ proc_hdr(char *name, char *val)
        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(NULL, "illegal address: %s", cp);
+                       adios(EX_DATAERR, NULL, "illegal address: %s", cp);
                }
                mp = mp->m_next;
                if (mp->m_type == BADHOST) {
@@ -300,6 +326,30 @@ print(void)
 ** Walk through the list of addresses and print the right ones.
 */
 static int
+printdcc(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 & HDCC) {
+                       if (!naddrs && (toccsw || bccsw)) {
+                               puts(dccsep);
+                       }
+                       naddrs++;
+                       printone(mp);
+               }
+       }
+       return naddrs;
+}
+
+/*
+** Walk through the list of addresses and print the right ones.
+*/
+static int
 printbcc(void)
 {
        int naddrs = 0;
@@ -310,8 +360,8 @@ printbcc(void)
                        continue;
                }
                if (mp->m_type & HBCC) {
-                       if (!naddrs && toccsw) {
-                               puts(separator);
+                       if (!naddrs && (toccsw || dccsw)) {
+                               puts(bccsep);
                        }
                        naddrs++;
                        printone(mp);