add free_field as standard for struct field
[mmh] / uip / repl.c
index 07ec48c..bbc3cfe 100644 (file)
 #include <h/fmt_scan.h>
 #include <sys/file.h>  /* L_SET */
 #include <errno.h>
-
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <sysexits.h>
 
 static struct swit switches[] = {
 #define GROUPSW  0
        { "group", 0 },
 #define NGROUPSW  1
-       { "nogroup", 0 },
+       { "nogroup", 2 },
 #define ANNOSW  2
        { "annotate", 0 },
 #define NANNOSW  3
-       { "noannotate", 0 },
+       { "noannotate", 2 },
 #define CCSW  4
        { "cc all|to|cc|me", 0 },
 #define NCCSW  5
-       { "nocc type", 0 },
+       { "nocc type", 2 },
 #define EDITRSW  6
        { "editor editor", 0 },
-#define NEDITSW  7
-       { "noedit", 0 },
-#define FILTSW  8
+#define FILTSW  7
        { "filter filterfile", 0 },
-#define NFILTSW  9
-       { "nofilter", 0 },
-#define FORMSW  10
+#define NFILTSW  8
+       { "nofilter", 2 },
+#define FORMSW  9
        { "form formfile", 0 },
-#define MIMESW  11
+#define MIMESW  10
        { "mime", 0 },
-#define NMIMESW  12
-       { "nomime", 0 },
-#define QURYSW  13
+#define NMIMESW  11
+       { "nomime", 2 },
+#define QURYSW  12
        { "query", 0 },
-#define NQURYSW  14
-       { "noquery", 0 },
-#define WHATSW  15
+#define NQURYSW  13
+       { "noquery", 2 },
+#define WHATSW  14
        { "whatnowproc program", 0 },
-#define NWHATSW  16
-       { "nowhatnowproc", 0 },
-#define VERSIONSW  17
-       { "version", 0 },
-#define HELPSW  18
+#define VERSIONSW  15
+       { "Version", 0 },
+#define HELPSW  16
        { "help", 0 },
-#define FILESW  19
+#define FILESW  17
        { "file file", 4 },  /* interface from msh */
-
-#ifdef MHE
-#define BILDSW  20
+#define BILDSW  18
        { "build", 5 },  /* interface from mhe */
-#endif
-
        { NULL, 0 }
 };
 
@@ -76,15 +72,6 @@ static struct swit ccswitches[] = {
        { NULL, 0 }
 };
 
-/*
-** Buffer size for content part of header fields.
-** We want this to be large enough so that we don't
-** do a lot of extra FLDPLUS calls on m_getfld but
-** small enough so that we don't snarf the entire
-** message body when we're not going to use any of it.
-*/
-#define SBUFSIZ 256
-
 static short ccto = -1;
 static short cccc = -1;
 static short ccme = -1;
@@ -101,13 +88,11 @@ static int dftype=0;
 static char *badaddrs = NULL;
 static char *dfhost = NULL;
 
-static struct mailname mq = { NULL };
+static struct mailname mq;
 
 static struct format *fmt;
 
 static int ncomps = 0;  /* # of interesting components */
-static char **compbuffers = NULL;  /* buffers for component text */
-static struct comp **used_buf = NULL;  /* stack for comp that use buffers */
 
 static int dat[5];  /* aux. data for format routine */
 
@@ -133,7 +118,7 @@ static char *addrcomps[] = {
 static void docc(char *, int);
 static int insert(struct mailname *);
 static void replfilter(FILE *, FILE *, char *);
-static void replout(FILE *, char *, char *, struct msgs *, int,
+static void replout(FILE *, char *, struct msgs *, int,
                char *, char *);
 
 
@@ -141,23 +126,17 @@ int
 main(int argc, char **argv)
 {
        int anot = 0;
-       int nedit = 0, nwhat = 0;
        char *cp, *cwd, *maildir, *file = NULL;
        char *folder = NULL, *msg = NULL;
        char *ed = NULL, drft[BUFSIZ], buf[BUFSIZ];
        char **argp, **arguments;
        struct msgs *mp = NULL;
        FILE *in;
-
-#ifdef MHE
        int buildsw = 0;
-#endif /* MHE */
 
        filter = getcpy(etcpath(mhlreply));
 
-#ifdef LOCALE
        setlocale(LC_ALL, "");
-#endif
        invo_name = mhbasename(argv[0]);
 
        /* read user profile/context */
@@ -171,17 +150,17 @@ 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: [+folder] [msg] [switches]", invo_name);
                                print_help(buf, switches, 1);
-                               done(0);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
                        case VERSIONSW:
                                print_version(invo_name);
-                               done(1);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
 
                        case GROUPSW:
                                groupreply++;
@@ -199,59 +178,51 @@ main(int argc, char **argv)
 
                        case CCSW:
                                if (!(cp = *argp++) || *cp == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                docc(cp, 1);
                                continue;
                        case NCCSW:
                                if (!(cp = *argp++) || *cp == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                docc(cp, 0);
                                continue;
 
                        case EDITRSW:
                                if (!(ed = *argp++) || *ed == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
-                               nedit = 0;
-                               continue;
-                       case NEDITSW:
-                               nedit++;
                                continue;
 
                        case WHATSW:
                                if (!(whatnowproc = *argp++) ||
                                                *whatnowproc == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
-                               nwhat = 0;
                                continue;
-#ifdef MHE
+
                        case BILDSW:
-                               buildsw++;  /* fall... */
-#endif /* MHE */
-                       case NWHATSW:
-                               nwhat++;
+                               buildsw++;
                                continue;
 
                        case FILESW:
                                if (file)
-                                       adios(NULL, "only one file at a time!");
+                                       adios(EX_USAGE, NULL, "only one file at a time!");
                                if (!(cp = *argp++) || *cp == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                file = getcpy(expanddir(cp));
                                continue;
                        case FORMSW:
                                if (!(form = *argp++) || *form == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                continue;
 
                        case FILTSW:
                                if (!(cp = *argp++) || *cp == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                filter = getcpy(etcpath(cp));
                                continue;
@@ -277,12 +248,12 @@ main(int argc, char **argv)
                }
                if (*cp == '+' || *cp == '@') {
                        if (folder)
-                               adios(NULL, "only one folder at a time!");
+                               adios(EX_USAGE, NULL, "only one folder at a time!");
                        else
                                folder = getcpy(expandfol(cp));
                } else {
                        if (msg)
-                               adios(NULL, "only one message at a time!");
+                               adios(EX_USAGE, NULL, "only one message at a time!");
                        else
                                msg = cp;
                }
@@ -298,14 +269,16 @@ main(int argc, char **argv)
        cwd = getcpy(pwd());
 
        if (file && (msg || folder))
-               adios(NULL, "can't mix files and folders/msgs");
+               adios(EX_USAGE, NULL, "can't mix files and folders/msgs");
 
-#ifdef MHE
-       strncpy(drft, buildsw ? toabsdir("reply")
-               : m_draft(seq_beyond), sizeof(drft));
-#else
-       strncpy(drft, m_draft(seq_beyond), sizeof(drft));
-#endif /* MHE */
+       strncpy(drft, buildsw ? toabsdir("reply") : m_draft(seq_beyond),
+                       sizeof(drft));
+       /*
+       ** FIXME: (concerning MHE support (buildsw) only)
+       ** There's no check if the draft already exists. mmh has removed
+       ** this case by having the draft folder. I won't add code only to
+       ** handle this legacy issue for MHE. -- meillo@marmaro.de 2012-05
+       */
 
        if (file) {
                /*
@@ -323,23 +296,23 @@ main(int argc, char **argv)
                maildir = toabsdir(folder);
 
                if (chdir(maildir) == NOTOK)
-                       adios(maildir, "unable to change directory to");
+                       adios(EX_OSERR, maildir, "unable to change directory to");
 
                /* read folder and create message structure */
                if (!(mp = folder_read(folder)))
-                       adios(NULL, "unable to read folder %s", folder);
+                       adios(EX_IOERR, NULL, "unable to read folder %s", folder);
 
                /* check for empty folder */
                if (mp->nummsg == 0)
-                       adios(NULL, "no messages in %s", folder);
+                       adios(EX_DATAERR, NULL, "no messages in %s", folder);
 
                /* parse the message range/sequence/name and set SELECTED */
                if (!m_convert(mp, msg))
-                       done(1);
+                       exit(EX_SOFTWARE);
                seq_setprev(mp);  /* set the previous-sequence */
 
                if (mp->numsel > 1)
-                       adios(NULL, "only one message at a time!");
+                       adios(EX_USAGE, NULL, "only one message at a time!");
 
                context_replace(curfolder, folder); /* update current folder */
                seq_setcur(mp, mp->lowsel);  /* update current message  */
@@ -350,7 +323,7 @@ main(int argc, char **argv)
        msg = file ? file : getcpy(m_name(mp->lowsel));
 
        if ((in = fopen(msg, "r")) == NULL)
-               adios(msg, "unable to open");
+               adios(EX_IOERR, msg, "unable to open");
 
        /* find form (components) file */
        if (!form) {
@@ -360,15 +333,13 @@ main(int argc, char **argv)
                        form = etcpath(replcomps);
        }
 
-       replout(in, msg, drft, mp, mime, form, filter);
+       replout(in, drft, mp, mime, form, filter);
        fclose(in);
 
-       if (nwhat)
-               done(0);
-       what_now(ed, nedit, NOUSE, drft, msg, 0, mp, anot ? "Replied" : NULL,
-                       cwd);
-       done(1);
-       return 1;
+       if (buildsw)
+               exit(EX_OK);
+       what_now(ed, NOUSE, drft, msg, 0, mp, anot ? "Replied" : NULL, cwd);
+       return EX_OSERR;
 }
 
 static void
@@ -377,9 +348,9 @@ docc(char *cp, int ccflag)
        switch (smatch(cp, ccswitches)) {
        case AMBIGSW:
                ambigsw(cp, ccswitches);
-               done(1);
+               exit(EX_USAGE);
        case UNKWNSW:
-               adios(NULL, "-%scc %s unknown", ccflag ? "" : "no", cp);
+               adios(EX_USAGE, NULL, "-%scc %s unknown", ccflag ? "" : "no", cp);
 
        case CTOSW:
                ccto = ccflag;
@@ -403,23 +374,22 @@ docc(char *cp, int ccflag)
 
 
 static void
-replout(FILE *inb, char *msg, char *drft, struct msgs *mp,
+replout(FILE *inb, char *drft, struct msgs *mp,
        int mime, char *form, char *filter)
 {
-       register int state, i;
-       register struct comp *cptr;
-       register char *tmpbuf;
-       register char **nxtbuf;
-       register char **ap;
-       register struct comp **savecomp;
+       enum state state;
+       struct field f = free_field;
+       int i;
+       struct comp *cptr;
+       char **ap;
        int char_read = 0, format_len, mask;
-       char name[NAMESZ], *scanl;
+       char *scanl;
        unsigned char *cp;
        FILE *out;
 
        mask = umask(~m_gmprot());
        if ((out = fopen(drft, "w")) == NULL)
-               adios(drft, "unable to create");
+               adios(EX_CANTCREAT, drft, "unable to create");
 
        umask(mask);
 
@@ -430,21 +400,6 @@ replout(FILE *inb, char *msg, char *drft, struct msgs *mp,
        /* compile format string */
        ncomps = fmt_compile(cp, &fmt) + 1;
 
-       if (!(nxtbuf = compbuffers = (char **)
-                       calloc((size_t) ncomps, sizeof(char *))))
-               adios(NULL, "unable to allocate component buffers");
-       if (!(savecomp = used_buf = (struct comp **)
-                       calloc((size_t) (ncomps+1), sizeof(struct comp *))))
-               adios(NULL, "unable to allocate component buffer stack");
-       savecomp += ncomps + 1;
-       *--savecomp = NULL;  /* point at zero'd end minus 1 */
-
-       for (i = ncomps; i--; )
-               *nxtbuf++ = mh_xmalloc(SBUFSIZ);
-
-       nxtbuf = compbuffers;  /* point at start */
-       tmpbuf = *nxtbuf++;
-
        for (ap = addrcomps; *ap; ap++) {
                FINDCOMP(cptr, *ap);
                if (cptr)
@@ -475,11 +430,10 @@ replout(FILE *inb, char *msg, char *drft, struct msgs *mp,
        /*
        ** pick any interesting stuff out of msg "inb"
        */
-       for (state = FLD;;) {
-               state = m_getfld(state, name, tmpbuf, SBUFSIZ, inb);
+       for (state = FLD2;;) {
+               state = m_getfld2(state, &f, inb);
                switch (state) {
-               case FLD:
-               case FLDPLUS:
+               case FLD2:
                        /*
                        ** if we're interested in this component, save
                        ** a pointer to the component text, then start
@@ -487,51 +441,45 @@ replout(FILE *inb, char *msg, char *drft, struct msgs *mp,
                        ** temp buffer (buffer switching saves an extra
                        ** copy of the component text).
                        */
-                       if ((cptr = wantcomp[CHASH(name)]))
+                       if ((cptr = wantcomp[CHASH(f.name)])) {
                                do {
-                                       if (!mh_strcasecmp(name, cptr->c_name)) {
-                                               char_read += msg_count;
-                                               if (! cptr->c_text) {
-                                                       i = strlen(cptr->c_text = tmpbuf) - 1;
-                                                       if (tmpbuf[i] == '\n')
-                                                               tmpbuf[i] = '\0';
-                                                       *--savecomp = cptr;
-                                                       tmpbuf = *nxtbuf++;
-                                               } else {
-                                                       i = strlen(cp = cptr->c_text) - 1;
-                                                       if (cp[i] == '\n') {
-                                                               if (cptr->c_type & CT_ADDR) {
-                                                                       cp[i] = '\0';
-                                                                       cp = add(",\n\t", cp);
-                                                               } else {
-                                                                       cp = add("\t", cp);
-                                                               }
-                                                       }
-                                                       cptr->c_text = add(tmpbuf, cp);
+                                       if (mh_strcasecmp(f.name, cptr->c_name)!=0) {
+                                               continue;
+                                       }
+                                       char_read += strlen(f.value);
+                                       if (!cptr->c_text) {
+                                               cptr->c_text = getcpy(f.value);
+                                               i = strlen(cptr->c_text) - 1;
+                                               if (cptr->c_text[i] == '\n') {
+                                                       cptr->c_text[i] = '\0';
                                                }
-                                               while (state == FLDPLUS) {
-                                                       state = m_getfld(state, name, tmpbuf,
-                                                                                         SBUFSIZ, inb);
-                                                       cptr->c_text = add(tmpbuf, cptr->c_text);
-                                                       char_read += msg_count;
+                                       } else {
+                                               cp = cptr->c_text;
+                                               i = strlen(cp) - 1;
+                                               if (cp[i] == '\n') {
+                                                       if (cptr->c_type & CT_ADDR) {
+                                                               cp[i] = '\0';
+                                                               cp = add(",\n\t", cp);
+                                                       } else {
+                                                               cp = add("\t", cp);
+                                                       }
                                                }
-                                               break;
+                                               cptr->c_text = add(f.value, cp);
                                        }
+                                       break;
                                } while ((cptr = cptr->c_next));
-
-                       while (state == FLDPLUS)
-                               state = m_getfld(state, name, tmpbuf,
-                                               SBUFSIZ, inb);
+                       }
                        break;
 
-               case LENERR:
-               case FMTERR:
-               case BODY:
-               case FILEEOF:
+               case LENERR2:
+               case FMTERR2:
+               case IOERR2:
+               case BODY2:
+               case FILEEOF2:
                        goto finished;
 
                default:
-                       adios(NULL, "m_getfld() returned %d", state);
+                       adios(EX_SOFTWARE, NULL, "m_getfld() returned %d", state);
                }
        }
 
@@ -545,7 +493,7 @@ finished:
        */
        FINDCOMP(cptr, "subject")
        if (cptr && (cp = cptr->c_text)) {
-               register char *sp = cp;
+               char *sp = cp;
 
                for (;;) {
                        while (isspace(*cp))
@@ -580,38 +528,31 @@ finished:
        if (filter) {
                fflush(out);
                if (ferror(out))
-                       adios(drft, "error writing");
+                       adios(EX_IOERR, drft, "error writing");
 
                replfilter(inb, out, filter);
        }
 
        fflush(out);
        if (ferror(out))
-               adios(drft, "error writing");
+               adios(EX_IOERR, drft, "error writing");
        fclose(out);
 
        if (mime && mp) {
                /* add an attachment header */
                char buffer[BUFSIZ];
 
-               snprintf(buffer, sizeof buffer, "anno -append -nodate '%s' "
-                               "-comp '%s' -text '+%s %s'",
-                               drft,
-                               attach_hdr, mp->foldpath, m_name(mp->lowsel));
-               if (system(buffer) != 0) {
+               snprintf(buffer, sizeof buffer, "+%s %s",
+                               mp->foldpath, m_name(mp->lowsel));
+               if (execprogl("anno", "anno", "-append", "-nodate",
+                               drft, "-comp", attach_hdr, "-text", buffer,
+                               (char *)NULL) != 0) {
                        advise(NULL, "unable to add attachment header");
                }
        }
 
        /* return dynamically allocated buffers */
        free(scanl);
-       for (nxtbuf = compbuffers, i = ncomps; (cptr = *savecomp++);
-                       nxtbuf++, i--)
-               free(cptr->c_text);  /* if not nxtbuf, nxtbuf already freed */
-       while ( i-- > 0)
-               free(*nxtbuf++);  /* free unused nxtbufs */
-       free((char *) compbuffers);
-       free((char *) used_buf);
 }
 
 static char *buf;  /* our current working buffer */
@@ -656,13 +597,13 @@ static unsigned int bufsiz=0;  /* current size of buf */
 char *
 formataddr(char *orig, char *str)
 {
-       register int len;
+       int len;
        char baddr[BUFSIZ], error[BUFSIZ];
-       register int isgroup;
-       register char *dst;
-       register char *cp;
-       register char *sp;
-       register struct mailname *mp = NULL;
+       int isgroup;
+       char *dst;
+       char *cp;
+       char *sp;
+       struct mailname *mp = NULL;
 
        /* if we don't have a buffer yet, get one */
        if (bufsiz == 0) {
@@ -728,7 +669,7 @@ static int
 insert(struct mailname *np)
 {
        char buffer[BUFSIZ];
-       register struct mailname *mp;
+       struct mailname *mp;
 
        if (np->m_mbox == NULL)
                return 0;
@@ -767,14 +708,14 @@ replfilter(FILE *in, FILE *out, char *filter)
                return;
 
        if (access(filter, R_OK) == NOTOK)
-               adios(filter, "unable to read");
+               adios(EX_IOERR, filter, "unable to read");
 
        rewind(in);
        lseek(fileno(in), (off_t) 0, SEEK_SET);
 
        switch (pid = fork()) {
        case NOTOK:
-               adios("fork", "unable to");
+               adios(EX_OSERR, "fork", "unable to");
 
        case OK:
                dup2(fileno(in), fileno(stdin));
@@ -788,11 +729,11 @@ replfilter(FILE *in, FILE *out, char *filter)
                write(2, "unable to exec mhl: ", 20);
                write(2, errstr, strlen(errstr));
                write(2, "\n", 1);
-               _exit(-1);
+               _exit(EX_OSERR);
 
        default:
                if (pidXwait(pid, "mhl"))
-                       done(1);
+                       exit(EX_SOFTWARE);
                fseek(out, 0L, SEEK_END);
                break;
        }