refile: Never change the current folder
[mmh] / uip / repl.c
index a5864c1..e3028fa 100644 (file)
@@ -16,6 +16,7 @@
 #include <ctype.h>
 #include <sys/stat.h>
 #include <locale.h>
+#include <sysexits.h>
 
 static struct swit switches[] = {
 #define GROUPSW  0
@@ -144,14 +145,14 @@ main(int argc, char **argv)
        FILE *in;
        int buildsw = 0;
 
-       filter = getcpy(etcpath(mhlreply));
-
        setlocale(LC_ALL, "");
        invo_name = mhbasename(argv[0]);
 
        /* read user profile/context */
        context_read();
 
+       filter = mh_xstrdup(etcpath(mhlreply));
+
        arguments = getarguments(invo_name, argc, argv, 1);
        argp = arguments;
 
@@ -160,17 +161,17 @@ main(int argc, char **argv)
                        switch (smatch(++cp, switches)) {
                        case AMBIGSW:
                                ambigsw(cp, switches);
-                               exit(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);
-                               exit(0);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
                        case VERSIONSW:
                                print_version(invo_name);
-                               exit(0);
+                               exit(argc == 2 ? EX_OK : EX_USAGE);
 
                        case GROUPSW:
                                groupreply++;
@@ -188,27 +189,27 @@ 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]);
                                continue;
 
                        case WHATSW:
                                if (!(whatnowproc = *argp++) ||
                                                *whatnowproc == '-')
-                                       adios(NULL, "missing argument to %s",
+                                       adios(EX_USAGE, NULL, "missing argument to %s",
                                                        argp[-2]);
                                continue;
 
@@ -218,23 +219,23 @@ main(int argc, char **argv)
 
                        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));
+                               file = mh_xstrdup(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));
+                               filter = mh_xstrdup(etcpath(cp));
                                continue;
                        case NFILTSW:
                                filter = NULL;
@@ -258,12 +259,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));
+                               folder = mh_xstrdup(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;
                }
@@ -276,10 +277,10 @@ main(int argc, char **argv)
        if (ccme == -1)
                ccme = groupreply;
 
-       cwd = getcpy(pwd());
+       cwd = mh_xstrdup(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");
 
        strncpy(drft, buildsw ? toabsdir("reply") : m_draft(seq_beyond),
                        sizeof(drft));
@@ -306,24 +307,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))
-                       /* sysexits.h EX_USAGE */
-                       exit(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  */
@@ -331,10 +331,10 @@ main(int argc, char **argv)
                context_save();  /* save the context file   */
        }
 
-       msg = file ? file : getcpy(m_name(mp->lowsel));
+       msg = file ? file : mh_xstrdup(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) {
@@ -348,10 +348,9 @@ main(int argc, char **argv)
        fclose(in);
 
        if (buildsw)
-               exit(0);
+               exit(EX_OK);
        what_now(ed, NOUSE, drft, msg, 0, mp, anot ? "Replied" : NULL, cwd);
-       /* sysexits.h EX_SOFTWARE */
-       return 1;
+       return EX_OSERR;
 }
 
 static void
@@ -360,9 +359,9 @@ docc(char *cp, int ccflag)
        switch (smatch(cp, ccswitches)) {
        case AMBIGSW:
                ambigsw(cp, ccswitches);
-               exit(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;
@@ -389,12 +388,12 @@ static void
 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;
+       int state, i;
+       struct comp *cptr;
+       char *tmpbuf;
+       char **nxtbuf;
+       char **ap;
+       struct comp **savecomp;
        int char_read = 0, format_len, mask;
        char name[NAMESZ], *scanl;
        unsigned char *cp;
@@ -402,7 +401,7 @@ replout(FILE *inb, char *drft, struct msgs *mp,
 
        mask = umask(~m_gmprot());
        if ((out = fopen(drft, "w")) == NULL)
-               adios(drft, "unable to create");
+               adios(EX_CANTCREAT, drft, "unable to create");
 
        umask(mask);
 
@@ -413,17 +412,13 @@ replout(FILE *inb, 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");
+       nxtbuf = compbuffers = mh_xcalloc(ncomps, sizeof(char *));
+       savecomp = used_buf = mh_xcalloc(ncomps+1, sizeof(struct comp *));
        savecomp += ncomps + 1;
        *--savecomp = NULL;  /* point at zero'd end minus 1 */
 
        for (i = ncomps; i--; )
-               *nxtbuf++ = mh_xmalloc(SBUFSIZ);
+               *nxtbuf++ = mh_xcalloc(SBUFSIZ, sizeof(char));
 
        nxtbuf = compbuffers;  /* point at start */
        tmpbuf = *nxtbuf++;
@@ -450,7 +445,7 @@ replout(FILE *inb, char *drft, struct msgs *mp,
        if ((cp = getenv("USER"))) {
                FINDCOMP(cptr, "user");
                if (cptr)
-                       cptr->c_text = getcpy(cp);
+                       cptr->c_text = mh_xstrdup(cp);
        }
        if (!ccme)
                ismymbox(NULL);
@@ -514,7 +509,7 @@ replout(FILE *inb, char *drft, struct msgs *mp,
                        goto finished;
 
                default:
-                       adios(NULL, "m_getfld() returned %d", state);
+                       adios(EX_SOFTWARE, NULL, "m_getfld() returned %d", state);
                }
        }
 
@@ -528,7 +523,7 @@ finished:
        */
        FINDCOMP(cptr, "subject")
        if (cptr && (cp = cptr->c_text)) {
-               register char *sp = cp;
+               char *sp = cp;
 
                for (;;) {
                        while (isspace(*cp))
@@ -541,12 +536,12 @@ finished:
                }
                if (sp != cptr->c_text) {
                        cp = cptr->c_text;
-                       cptr->c_text = getcpy(sp);
-                       free(cp);
+                       cptr->c_text = mh_xstrdup(sp);
+                       mh_free0(&cp);
                }
        }
        i = format_len + char_read + 256;
-       scanl = mh_xmalloc((size_t) i + 2);
+       scanl = mh_xcalloc(i + 2, sizeof(char));
        dat[0] = 0;
        dat[1] = 0;
        dat[2] = 0;
@@ -563,14 +558,14 @@ 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) {
@@ -587,14 +582,14 @@ finished:
        }
 
        /* return dynamically allocated buffers */
-       free(scanl);
+       mh_free0(&scanl);
        for (nxtbuf = compbuffers, i = ncomps; (cptr = *savecomp++);
                        nxtbuf++, i--)
-               free(cptr->c_text);  /* if not nxtbuf, nxtbuf already freed */
+               mh_free0(&(cptr->c_text));  /* if not nxtbuf, nxtbuf already freed */
        while ( i-- > 0)
-               free(*nxtbuf++);  /* free unused nxtbufs */
-       free((char *) compbuffers);
-       free((char *) used_buf);
+               mh_free0(nxtbuf++);  /* free unused nxtbufs */
+       mh_free0(&compbuffers);
+       mh_free0(&used_buf);
 }
 
 static char *buf;  /* our current working buffer */
@@ -630,7 +625,7 @@ static unsigned int bufsiz=0;  /* current size of buf */
 ** returns a pointer to the concatenated address string.
 **
 ** We try to not do a lot of malloc/copy/free's (which is why we
-** don't call "getcpy") but still place no upper limit on the
+** don't call "mh_xstrdup") but still place no upper limit on the
 ** length of the result string.
 **
 ** This routine is an override for the equally named one in sbr/fmt_addr.c.
@@ -639,17 +634,17 @@ 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) {
-               buf = mh_xmalloc(BUFINCR);
+               buf = mh_xcalloc(BUFINCR, sizeof(char));
                last_dst = buf;  /* XXX */
                bufsiz = BUFINCR - 6;  /* leave some slop */
                bufend = buf + bufsiz;
@@ -711,7 +706,7 @@ static int
 insert(struct mailname *np)
 {
        char buffer[BUFSIZ];
-       register struct mailname *mp;
+       struct mailname *mp;
 
        if (np->m_mbox == NULL)
                return 0;
@@ -743,24 +738,45 @@ insert(struct mailname *np)
 static void
 replfilter(FILE *in, FILE *out, char *filter)
 {
-       int pid, n;
+       int pid, pid_show, n;
+       int mailpipe[2];
        char *errstr;
 
        if (filter == NULL)
                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()) {
+       if (pipe(mailpipe) == -1) {
+               adios(EX_OSERR, "pipe", "can't create pipe");
+       }
+
+       switch (pid_show = fork()) {
        case NOTOK:
-               adios("fork", "unable to");
+               adios(EX_OSERR, "fork", "unable to");
 
        case OK:
                dup2(fileno(in), fileno(stdin));
+               dup2(mailpipe[1], fileno(stdout));
+               for (n=3; n<OPEN_MAX; n++) {
+                       close(n);
+               }
+
+               execlp("show", "show", "-file", "-", NULL);
+
+               adios(EX_OSERR, "exec", "unable to");
+       }
+
+       switch (pid = fork()) {
+       case NOTOK:
+               adios(EX_OSERR, "fork", "unable to");
+
+       case OK:
+               dup2(mailpipe[0], fileno(stdin));
                dup2(fileno(out), fileno(stdout));
                for (n=3; n<OPEN_MAX; n++) {
                        close(n);
@@ -771,13 +787,15 @@ 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"))
-                       /* sysexits.h EX_SOFTWARE */
-                       exit(1);
+               if (pidXwait(-1, "show | mhl"))
+                       exit(EX_SOFTWARE);
                fseek(out, 0L, SEEK_END);
                break;
        }
+
+       close(mailpipe[0]);
+       close(mailpipe[1]);
 }