]> diplodocus.org Git - nmh/blobdiff - uip/inc.c
Fixed inc(1) and %(me) to not obey Local-Mailbox profile component.
[nmh] / uip / inc.c
index 20d4088bce22c295e3f8058bd8b2cae447b5238f..c34d28ae9fd1c121d04ecf5aff3631c15e40987f 100644 (file)
--- a/uip/inc.c
+++ b/uip/inc.c
  */
 #endif
 
  */
 #endif
 
-#include <h/mh.h>
-#include <h/utils.h>
+#include "h/mh.h"
+#include "sbr/fmt_new.h"
+#include "sbr/dtime.h"
+#include "scansbr.h"
+#include "sbr/m_name.h"
+#include "sbr/m_gmprot.h"
+#include "sbr/getarguments.h"
+#include "sbr/concat.h"
+#include "sbr/seq_setunseen.h"
+#include "sbr/seq_setcur.h"
+#include "sbr/seq_save.h"
+#include "sbr/smatch.h"
+#include "sbr/getfolder.h"
+#include "sbr/ext_hook.h"
+#include "sbr/folder_read.h"
+#include "sbr/folder_realloc.h"
+#include "sbr/folder_free.h"
+#include "sbr/context_save.h"
+#include "sbr/context_replace.h"
+#include "sbr/context_find.h"
+#include "sbr/ambigsw.h"
+#include "sbr/path.h"
+#include "sbr/print_version.h"
+#include "sbr/print_help.h"
+#include "sbr/error.h"
+#include "h/utils.h"
 #include <fcntl.h>
 #include <fcntl.h>
-#include <h/dropsbr.h>
-#include <h/popsbr.h>
-#include <h/fmt_scan.h>
-#include <h/scansbr.h>
-#include <h/signals.h>
-#include <h/tws.h>
-#include <h/mts.h>
-#include "../sbr/lock_file.h"
-#include "../sbr/m_maildir.h"
-#include "../sbr/m_mktemp.h"
+#include "h/dropsbr.h"
+#include "popsbr.h"
+#include "h/fmt_scan.h"
+#include "h/signals.h"
+#include "h/tws.h"
+#include "h/mts.h"
+#include "h/done.h"
+#include "sbr/lock_file.h"
+#include "sbr/m_maildir.h"
+#include "sbr/m_mktemp.h"
 
 #ifndef TLS_SUPPORT
 # define TLSminc(a) (a)
 
 #ifndef TLS_SUPPORT
 # define TLSminc(a) (a)
@@ -72,6 +96,7 @@
     X("sasl", 0, SASLSW) \
     X("nosasl", 0, NOSASLSW) \
     X("saslmech", 0, SASLMECHSW) \
     X("sasl", 0, SASLSW) \
     X("nosasl", 0, NOSASLSW) \
     X("saslmech", 0, SASLMECHSW) \
+    X("tls", TLSminc(-3), TLSSW) \
     X("initialtls", TLSminc(-10), INITTLSSW) \
     X("notls", TLSminc(-5), NOTLSSW) \
     X("certverify", TLSminc(-10), CERTVERSW) \
     X("initialtls", TLSminc(-10), INITTLSSW) \
     X("notls", TLSminc(-5), NOTLSSW) \
     X("certverify", TLSminc(-10), CERTVERSW) \
@@ -98,14 +123,14 @@ static struct Maildir_entry {
        time_t mtime;
 } *Maildir = NULL;
 static int num_maildir_entries = 0;
        time_t mtime;
 } *Maildir = NULL;
 static int num_maildir_entries = 0;
-static int snoop = 0;
+static bool snoop;
 
 
-extern char response[];
-
-static long start;
-static long stop;
+typedef struct {
+    FILE *mailout;
+    long written;
+} pop_closure;
 
 
-static FILE *pf = NULL;
+extern char response[];
 
 /* This is an attempt to simplify things by putting all the
  * privilege ops into macros.
 
 /* This is an attempt to simplify things by putting all the
  * privilege ops into macros.
@@ -149,17 +174,18 @@ static gid_t return_gid;
 #endif /* not MAILGROUP */
 
 /* these variables have to be globals so that done() can correctly clean up the lockfile */
 #endif /* not MAILGROUP */
 
 /* these variables have to be globals so that done() can correctly clean up the lockfile */
-static int locked = 0;
+static bool locked;
 static char *newmail;
 static FILE *in;
 
 /*
  * prototypes
  */
 static char *newmail;
 static FILE *in;
 
 /*
  * prototypes
  */
+static int maildir_srt(const void *va, const void *vb) PURE;
 static void inc_done(int) NORETURN;
 static int pop_action(void *closure, char *);
 
 static void inc_done(int) NORETURN;
 static int pop_action(void *closure, char *);
 
-int
+static int
 maildir_srt(const void *va, const void *vb)
 {
     const struct Maildir_entry *a = va, *b = vb;
 maildir_srt(const void *va, const void *vb)
 {
     const struct Maildir_entry *a = va, *b = vb;
@@ -179,7 +205,9 @@ main (int argc, char **argv)
     bool noisy;
     int width = -1;
     int hghnum = 0, msgnum = 0;
     bool noisy;
     int width = -1;
     int hghnum = 0, msgnum = 0;
-    bool sasl, tls, noverify;
+    FILE *pf = NULL;
+    bool sasl, noverify;
+    int tls = 0;
     int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */
     char *cp, *maildir = NULL, *folder = NULL;
     char *format = NULL, *form = NULL;
     int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */
     char *cp, *maildir = NULL, *folder = NULL;
     char *format = NULL, *form = NULL;
@@ -191,10 +219,11 @@ main (int argc, char **argv)
     FILE *aud = NULL;
     char b[PATH_MAX + 1];
     char *maildir_copy = NULL; /* copy of mail directory because the static gets overwritten */
     FILE *aud = NULL;
     char b[PATH_MAX + 1];
     char *maildir_copy = NULL; /* copy of mail directory because the static gets overwritten */
+    charstring_t scanl = NULL;
 
     int nmsgs, nbytes;
     char *MAILHOST_env_variable;
 
     int nmsgs, nbytes;
     char *MAILHOST_env_variable;
-    done=inc_done;
+    set_done(inc_done);
 
 /* absolutely the first thing we do is save our privileges,
  * and drop them if we can.
 
 /* absolutely the first thing we do is save our privileges,
  * and drop them if we can.
@@ -202,7 +231,7 @@ main (int argc, char **argv)
     SAVEGROUPPRIVS();
     TRYDROPGROUPPRIVS();
 
     SAVEGROUPPRIVS();
     TRYDROPGROUPPRIVS();
 
-    if (nmh_init(argv[0], 1)) { return 1; }
+    if (nmh_init(argv[0], true, true)) { return 1; }
 
     mts_init ();
     arguments = getarguments (invo_name, argc, argv, 1);
 
     mts_init ();
     arguments = getarguments (invo_name, argc, argv, 1);
@@ -224,7 +253,7 @@ main (int argc, char **argv)
     if (pophost && *pophost)
        host = pophost;
 
     if (pophost && *pophost)
        host = pophost;
 
-    sasl = tls = false;
+    sasl = false;
     chgflag = noisy = noverify = true;
     while ((cp = *argp++)) {
        if (*cp == '-') {
     chgflag = noisy = noverify = true;
     while ((cp = *argp++)) {
        if (*cp == '-') {
@@ -233,7 +262,7 @@ main (int argc, char **argv)
                ambigsw (cp, switches);
                done (1);
            case UNKWNSW:
                ambigsw (cp, switches);
                done (1);
            case UNKWNSW:
-               adios (NULL, "-%s unknown", cp);
+               die("-%s unknown", cp);
 
            case HELPSW:
                snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name);
 
            case HELPSW:
                snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name);
@@ -245,8 +274,8 @@ main (int argc, char **argv)
 
            case AUDSW:
                if (!(cp = *argp++) || *cp == '-')
 
            case AUDSW:
                if (!(cp = *argp++) || *cp == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
-               audfile = getcpy (m_maildir (cp));
+                   die("missing argument to %s", argp[-2]);
+               audfile = mh_xstrdup(m_maildir(cp));
                continue;
            case NAUDSW:
                audfile = NULL;
                continue;
            case NAUDSW:
                audfile = NULL;
@@ -275,7 +304,7 @@ main (int argc, char **argv)
 
            case FILESW:
                if (!(cp = *argp++) || *cp == '-')
 
            case FILESW:
                if (!(cp = *argp++) || *cp == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                from = path (cp, TFILE);
 
                /*
                from = path (cp, TFILE);
 
                /*
@@ -295,38 +324,38 @@ main (int argc, char **argv)
 
            case FORMSW:
                if (!(form = *argp++) || *form == '-')
 
            case FORMSW:
                if (!(form = *argp++) || *form == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                format = NULL;
                continue;
            case FMTSW:
                if (!(format = *argp++) || *format == '-')
                format = NULL;
                continue;
            case FMTSW:
                if (!(format = *argp++) || *format == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                form = NULL;
                continue;
 
            case WIDTHSW:
                if (!(cp = *argp++) || *cp == '-')
                form = NULL;
                continue;
 
            case WIDTHSW:
                if (!(cp = *argp++) || *cp == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                width = atoi (cp);
                continue;
 
            case HOSTSW:
                if (!(host = *argp++) || *host == '-')
                width = atoi (cp);
                continue;
 
            case HOSTSW:
                if (!(host = *argp++) || *host == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                continue;
 
            case PORTSW:
                if (!(port = *argp++) || *port == '-')
                continue;
 
            case PORTSW:
                if (!(port = *argp++) || *port == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                continue;
 
            case USERSW:
                if (!(user = *argp++) || *user == '-')
                continue;
 
            case USERSW:
                if (!(user = *argp++) || *user == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                continue;
 
            case SNOOPSW:
                continue;
 
            case SNOOPSW:
-               snoop++;
+               snoop = true;
                continue;
        
            case SASLSW:
                continue;
        
            case SASLSW:
@@ -338,15 +367,19 @@ main (int argc, char **argv)
        
            case SASLMECHSW:
                if (!(saslmech = *argp++) || *saslmech == '-')
        
            case SASLMECHSW:
                if (!(saslmech = *argp++) || *saslmech == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
+               continue;
+
+           case TLSSW:
+               tls = 1;
                continue;
 
            case INITTLSSW:
                continue;
 
            case INITTLSSW:
-                tls = true;
+                tls = 2;
                continue;
 
            case NOTLSSW:
                continue;
 
            case NOTLSSW:
-                tls = false;
+                tls = 0;
                continue;
 
            case CERTVERSW:
                continue;
 
            case CERTVERSW:
@@ -360,25 +393,24 @@ main (int argc, char **argv)
            case AUTHSERVICESW:
 #ifdef OAUTH_SUPPORT
                 if (!(auth_svc = *argp++) || *auth_svc == '-')
            case AUTHSERVICESW:
 #ifdef OAUTH_SUPPORT
                 if (!(auth_svc = *argp++) || *auth_svc == '-')
-                    adios (NULL, "missing argument to %s", argp[-2]);
+                    die("missing argument to %s", argp[-2]);
 #else
 #else
-                adios (NULL, "not built with OAuth support");
+                die("not built with OAuth support");
 #endif
                 continue;
 
            case PROXYSW:
                if (!(proxy = *argp++) || *proxy == '-')
 #endif
                 continue;
 
            case PROXYSW:
                if (!(proxy = *argp++) || *proxy == '-')
-                   adios (NULL, "missing argument to %s", argp[-2]);
+                   die("missing argument to %s", argp[-2]);
                continue;
            }
        }
        if (*cp == '+' || *cp == '@') {
            if (folder)
                continue;
            }
        }
        if (*cp == '+' || *cp == '@') {
            if (folder)
-               adios (NULL, "only one folder at a time!");
-           else
-               folder = pluspath (cp);
+               die("only one folder at a time!");
+            folder = pluspath (cp);
        } else {
        } else {
-           adios (NULL, "usage: %s [+folder] [switches]", invo_name);
+           die("usage: %s [+folder] [switches]", invo_name);
        }
     }
 
        }
     }
 
@@ -400,16 +432,18 @@ main (int argc, char **argv)
 
        if (auth_svc == NULL) {
            if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
 
        if (auth_svc == NULL) {
            if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
-               adios (NULL, "must specify -authservice with -saslmech xoauth2");
+               die("must specify -authservice with -saslmech xoauth2");
            }
        } else {
            if (user == NULL) {
            }
        } else {
            if (user == NULL) {
-               adios (NULL, "must specify -user with -saslmech xoauth2");
+               die("must specify -user with -saslmech xoauth2");
            }
        }
 
            }
        }
 
-       if (tls)
-           tlsflag |= P_INITTLS;
+       if (tls == 1)
+           tlsflag = P_STARTTLS;
+       else if (tls == 2)
+           tlsflag = P_INITTLS;
 
        if (noverify)
            tlsflag |= P_NOVERIFY;
 
        if (noverify)
            tlsflag |= P_NOVERIFY;
@@ -419,15 +453,15 @@ main (int argc, char **argv)
         */
        if (pop_init (host, port, user, proxy, snoop, sasl, saslmech,
                      tlsflag, auth_svc) == NOTOK)
         */
        if (pop_init (host, port, user, proxy, snoop, sasl, saslmech,
                      tlsflag, auth_svc) == NOTOK)
-           adios (NULL, "%s", response);
+           die("%s", response);
 
        /* Check if there are any messages */
        if (pop_stat (&nmsgs, &nbytes) == NOTOK)
 
        /* Check if there are any messages */
        if (pop_stat (&nmsgs, &nbytes) == NOTOK)
-           adios (NULL, "%s", response);
+           die("%s", response);
 
        if (nmsgs == 0) {
            pop_quit();
 
        if (nmsgs == 0) {
            pop_quit();
-           adios (NULL, "no mail to incorporate");
+           die("no mail to incorporate");
        }
 
     } else if (inc_type == INC_FILE) {
        }
 
     } else if (inc_type == INC_FILE) {
@@ -442,56 +476,56 @@ main (int argc, char **argv)
            newmail = concat (MAILDIR, "/", MAILFIL, NULL);
        }
        if (stat (newmail, &s1) == NOTOK || s1.st_size == 0)
            newmail = concat (MAILDIR, "/", MAILFIL, NULL);
        }
        if (stat (newmail, &s1) == NOTOK || s1.st_size == 0)
-           adios (NULL, "no mail to incorporate");
-       if (s1.st_mode & S_IFDIR) {
-           DIR *md;
-           struct dirent *de;
-           struct stat ms;
-           int i;
-           i = 0;
-           cp = concat (newmail, "/new", NULL);
-           if ((md = opendir(cp)) == NULL)
-               adios (NULL, "unable to open %s", cp);
-           while ((de = readdir (md)) != NULL) {
-               if (de->d_name[0] == '.')
-                   continue;
-               if (i >= num_maildir_entries) {
-                   if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL)
-                       adios(NULL, "not enough memory for %d messages", 2*i+16);
-                   num_maildir_entries = 2*i+16;
-               }
-               Maildir[i].filename = concat (cp, "/", de->d_name, NULL);
-               if (stat(Maildir[i].filename, &ms) != 0)
-                  adios (Maildir[i].filename, "couldn't get delivery time");
-               Maildir[i].mtime = ms.st_mtime;
-               i++;
-           }
-           free (cp);
-           closedir (md);
-           cp = concat (newmail, "/cur", NULL);
-           if ((md = opendir(cp)) == NULL)
-               adios (NULL, "unable to open %s", cp);
-           while ((de = readdir (md)) != NULL) {
-               if (de->d_name[0] == '.')
-                   continue;
-               if (i >= num_maildir_entries) {
-                   if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL)
-                       adios(NULL, "not enough memory for %d messages", 2*i+16);
-                   num_maildir_entries = 2*i+16;
-               }
-               Maildir[i].filename = concat (cp, "/", de->d_name, NULL);
-               if (stat(Maildir[i].filename, &ms) != 0)
-                  adios (Maildir[i].filename, "couldn't get delivery time");
-               Maildir[i].mtime = ms.st_mtime;
-               i++;
-           }
-           free (cp);
-           closedir (md);
-           if (i == 0)
-               adios (NULL, "no mail to incorporate");
-           num_maildir_entries = i;
-           qsort (Maildir, num_maildir_entries, sizeof(*Maildir), maildir_srt);
-       }
+           die("no mail to incorporate");
+       if (s1.st_mode & S_IFDIR) {
+           DIR *md;
+           struct dirent *de;
+           struct stat ms;
+           int i;
+           i = 0;
+           cp = concat (newmail, "/new", NULL);
+           if ((md = opendir(cp)) == NULL)
+               die("unable to open %s", cp);
+           while ((de = readdir (md)) != NULL) {
+               if (de->d_name[0] == '.')
+                   continue;
+               if (i >= num_maildir_entries) {
+                   if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL)
+                       die("not enough memory for %d messages", 2*i+16);
+                   num_maildir_entries = 2*i+16;
+               }
+               Maildir[i].filename = concat (cp, "/", de->d_name, NULL);
+               if (stat(Maildir[i].filename, &ms) != 0)
+                  adios (Maildir[i].filename, "couldn't get delivery time");
+               Maildir[i].mtime = ms.st_mtime;
+               i++;
+           }
+           free (cp);
+           closedir (md);
+           cp = concat (newmail, "/cur", NULL);
+           if ((md = opendir(cp)) == NULL)
+               die("unable to open %s", cp);
+           while ((de = readdir (md)) != NULL) {
+               if (de->d_name[0] == '.')
+                   continue;
+               if (i >= num_maildir_entries) {
+                   if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL)
+                       die("not enough memory for %d messages", 2*i+16);
+                   num_maildir_entries = 2*i+16;
+               }
+               Maildir[i].filename = concat (cp, "/", de->d_name, NULL);
+               if (stat(Maildir[i].filename, &ms) != 0)
+                  adios (Maildir[i].filename, "couldn't get delivery time");
+               Maildir[i].mtime = ms.st_mtime;
+               i++;
+           }
+           free (cp);
+           closedir (md);
+           if (i == 0)
+               die("no mail to incorporate");
+           num_maildir_entries = i;
+           qsort (Maildir, num_maildir_entries, sizeof(*Maildir), maildir_srt);
+       }
 
        cp = mh_xstrdup(newmail);
        newmail = cp;
 
        cp = mh_xstrdup(newmail);
        newmail = cp;
@@ -519,13 +553,13 @@ main (int argc, char **argv)
 
     /* read folder and create message structure */
     if (!(mp = folder_read (folder, 0)))
 
     /* read folder and create message structure */
     if (!(mp = folder_read (folder, 0)))
-       adios (NULL, "unable to read folder %s", folder);
+       die("unable to read folder %s", folder);
 
     if (inc_type == INC_FILE && Maildir == NULL) {
         /* Mail from a spool file. */
 
        if (access (newmail, W_OK) != NOTOK) {
 
     if (inc_type == INC_FILE && Maildir == NULL) {
         /* Mail from a spool file. */
 
        if (access (newmail, W_OK) != NOTOK) {
-           locked++;
+           locked = true;
            if (trnflag) {
                SIGNAL (SIGHUP, SIG_IGN);
                SIGNAL (SIGINT, SIG_IGN);
            if (trnflag) {
                SIGNAL (SIGHUP, SIG_IGN);
                SIGNAL (SIGINT, SIG_IGN);
@@ -537,7 +571,7 @@ main (int argc, char **argv)
             in = lkfopenspool (newmail, "r");
             DROPGROUPPRIVS();
             if (in == NULL)
             in = lkfopenspool (newmail, "r");
             DROPGROUPPRIVS();
             if (in == NULL)
-               adios (NULL, "unable to lock and fopen %s", newmail);
+               die("unable to lock and fopen %s", newmail);
            fstat (fileno(in), &s1);
        } else {
            trnflag = 0;
            fstat (fileno(in), &s1);
        } else {
            trnflag = 0;
@@ -555,14 +589,14 @@ main (int argc, char **argv)
            inform("Creating Receive-Audit: %s", audfile);
        if ((aud = fopen (audfile, "a")) == NULL)
            adios (audfile, "unable to append to");
            inform("Creating Receive-Audit: %s", audfile);
        if ((aud = fopen (audfile, "a")) == NULL)
            adios (audfile, "unable to append to");
-       else if (i == NOTOK)
+       if (i == NOTOK)
            chmod (audfile, m_gmprot ());
 
        if (from)
            fprintf (aud, "<<inc>> %s -ms %s\n", dtimenow(0), from);
        else {
            if (host)
            chmod (audfile, m_gmprot ());
 
        if (from)
            fprintf (aud, "<<inc>> %s -ms %s\n", dtimenow(0), from);
        else {
            if (host)
-               fprintf (aud, "<<inc>> %s -host %s -user %s\n", dtimenow(0),
+               fprintf (aud, "<<inc>> %s -host %s -user %s\n", dtimenow(0),
                         host, user);
            else
                fprintf (aud, "<<inc>> %s\n", dtimenow (0));
                         host, user);
            else
                fprintf (aud, "<<inc>> %s\n", dtimenow (0));
@@ -584,27 +618,28 @@ main (int argc, char **argv)
     if (inc_type == INC_POP) {
         /* Mail from a POP server. */
        int i;
     if (inc_type == INC_POP) {
         /* Mail from a POP server. */
        int i;
+        pop_closure pc;
 
         hghnum = msgnum = mp->hghmsg;
        for (i = 1; i <= nmsgs; i++) {
 
         hghnum = msgnum = mp->hghmsg;
        for (i = 1; i <= nmsgs; i++) {
-           charstring_t scanl = NULL;
 
            msgnum++;
             cp = mh_xstrdup(m_name (msgnum));
             if ((pf = fopen (cp, "w+")) == NULL)
                 adios (cp, "unable to write");
             chmod (cp, m_gmprot ());
 
            msgnum++;
             cp = mh_xstrdup(m_name (msgnum));
             if ((pf = fopen (cp, "w+")) == NULL)
                 adios (cp, "unable to write");
             chmod (cp, m_gmprot ());
-            start = stop = 0L;
 
 
-            if (pop_retr(i, pop_action, NULL) == NOTOK)
-                adios (NULL, "%s", response);
+            pc.written = 0;
+            pc.mailout = pf;
+            if (pop_retr(i, pop_action, &pc) == NOTOK)
+                die("%s", response);
 
             if (fflush (pf))
                 adios (cp, "write error on");
             fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
 
             if (fflush (pf))
                 adios (cp, "write error on");
             fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
-                             1, NULL, stop - start, noisy, &scanl)) {
+                             1, NULL, pc.written, noisy, &scanl)) {
            case SCNEOF:
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
            case SCNEOF:
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
@@ -620,7 +655,6 @@ main (int argc, char **argv)
                break;
 
            case SCNMSG:
                break;
 
            case SCNMSG:
-           case SCNENC:
            default:
                if (aud)
                    fputs (charstring_buffer (scanl), aud);
            default:
                if (aud)
                    fputs (charstring_buffer (scanl), aud);
@@ -628,7 +662,9 @@ main (int argc, char **argv)
                    fflush (stdout);
                break;
            }
                    fflush (stdout);
                break;
            }
-           charstring_free (scanl);
+
+           if (scanl)
+               charstring_clear (scanl);
 
             if (ferror(pf) || fclose (pf)) {
                 int e = errno;
 
             if (ferror(pf) || fclose (pf)) {
                 int e = errno;
@@ -640,13 +676,16 @@ main (int argc, char **argv)
             free (cp);
 
            if (trnflag && pop_dele (i) == NOTOK)
             free (cp);
 
            if (trnflag && pop_dele (i) == NOTOK)
-               adios (NULL, "%s", response);
+               die("%s", response);
 
            scan_finished();
        }
 
 
            scan_finished();
        }
 
+       charstring_free (scanl);
+       scanl = NULL;
+
        if (pop_quit () == NOTOK)
        if (pop_quit () == NOTOK)
-           adios (NULL, "%s", response);
+           die("%s", response);
 
     } else if (inc_type == INC_FILE && Maildir == NULL) {
         /* Mail from a spool file. */
 
     } else if (inc_type == INC_FILE && Maildir == NULL) {
         /* Mail from a spool file. */
@@ -654,8 +693,6 @@ main (int argc, char **argv)
        scan_detect_mbox_style (in);            /* the MAGIC invocation... */
        hghnum = msgnum = mp->hghmsg;
        for (;;) {
        scan_detect_mbox_style (in);            /* the MAGIC invocation... */
        hghnum = msgnum = mp->hghmsg;
        for (;;) {
-           charstring_t scanl = NULL;
-
            /* create scanline for new message */
            switch (incerr = scan (in, msgnum + 1, msgnum + 1, nfs, width,
                              msgnum == hghnum && chgflag, 1, NULL, 0L, noisy,
            /* create scanline for new message */
            switch (incerr = scan (in, msgnum + 1, msgnum + 1, nfs, width,
                              msgnum == hghnum && chgflag, 1, NULL, 0L, noisy,
@@ -679,7 +716,6 @@ main (int argc, char **argv)
                break;
 
            case SCNMSG:
                break;
 
            case SCNMSG:
-           case SCNENC:
                /*
                 *  Run the external program hook on the message.
                 */
                /*
                 *  Run the external program hook on the message.
                 */
@@ -692,16 +728,18 @@ main (int argc, char **argv)
                if (noisy)
                    fflush (stdout);
 
                if (noisy)
                    fflush (stdout);
 
+               charstring_clear (scanl);
                msgnum++;
                continue;
            }
                msgnum++;
                continue;
            }
-           charstring_free (scanl);
 
            /* If we get here there was some sort of error from scan(),
             * so stop processing anything more from the spool.
             */
            break;
        }
 
            /* If we get here there was some sort of error from scan(),
             * so stop processing anything more from the spool.
             */
            break;
        }
+       charstring_free (scanl);
+       scanl = NULL;
 
     } else {
         /* Mail from Maildir. */
 
     } else {
         /* Mail from Maildir. */
@@ -711,8 +749,6 @@ main (int argc, char **argv)
 
        hghnum = msgnum = mp->hghmsg;
        for (i = 0; i < num_maildir_entries; i++) {
 
        hghnum = msgnum = mp->hghmsg;
        for (i = 0; i < num_maildir_entries; i++) {
-           charstring_t scanl = NULL;
-
            msgnum++;
 
            sp = Maildir[i].filename;
            msgnum++;
 
            sp = Maildir[i].filename;
@@ -723,7 +759,7 @@ main (int argc, char **argv)
                size_t nrd;
 
                if ((sf = fopen (sp, "r")) == NULL)
                size_t nrd;
 
                if ((sf = fopen (sp, "r")) == NULL)
-                   adios (sp, "unable to read for copy");
+                   adios (sp, "unable to read for copy");
                if ((pf = fopen (cp, "w+")) == NULL)
                    adios (cp, "unable to write for copy");
                while ((nrd = fread(buf, 1, sizeof(buf), sf)) > 0)
                if ((pf = fopen (cp, "w+")) == NULL)
                    adios (cp, "unable to write for copy");
                while ((nrd = fread(buf, 1, sizeof(buf), sf)) > 0)
@@ -745,7 +781,7 @@ main (int argc, char **argv)
            fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
            fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
-                             1, NULL, stop - start, noisy, &scanl)) {
+                             1, NULL, 0, noisy, &scanl)) {
            case SCNEOF:
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
            case SCNEOF:
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
@@ -761,7 +797,6 @@ main (int argc, char **argv)
                break;
 
            case SCNMSG:
                break;
 
            case SCNMSG:
-           case SCNENC:
            default:
                /*
                 *  Run the external program hook on the message.
            default:
                /*
                 *  Run the external program hook on the message.
@@ -776,7 +811,7 @@ main (int argc, char **argv)
                    fflush (stdout);
                break;
            }
                    fflush (stdout);
                break;
            }
-           charstring_free (scanl);
+           charstring_clear (scanl);
 
            if (ferror(pf) || fclose (pf)) {
                int e = errno;
 
            if (ferror(pf) || fclose (pf)) {
                int e = errno;
@@ -794,6 +829,8 @@ main (int argc, char **argv)
            scan_finished();
        }
        free (Maildir); /* From now on Maildir is just a flag - don't dref! */
            scan_finished();
        }
        free (Maildir); /* From now on Maildir is just a flag - don't dref! */
+       charstring_free (scanl);
+       scanl = NULL;
     }
 
     scan_finished ();
     }
 
     scan_finished ();
@@ -806,7 +843,7 @@ main (int argc, char **argv)
        } else {
            fclose (in); in = NULL;
        }
        } else {
            fclose (in); in = NULL;
        }
-       adios (NULL, "failed");
+       die("failed");
     }
 
     if (aud)
     }
 
     if (aud)
@@ -837,7 +874,7 @@ main (int argc, char **argv)
     if (msgnum == hghnum) {
        inform("no messages incorporated, continuing...");
     } else {
     if (msgnum == hghnum) {
        inform("no messages incorporated, continuing...");
     } else {
-       /*
+       /*
         * Lock the sequence file now, and loop to set the right flags
         * in the folder structure
         */
         * Lock the sequence file now, and loop to set the right flags
         * in the folder structure
         */
@@ -904,7 +941,7 @@ skip:
 static void NORETURN
 inc_done (int status)
 {
 static void NORETURN
 inc_done (int status)
 {
-    done = exit;
+    set_done(exit);
     if (locked)
     {
         GETGROUPPRIVS();
     if (locked)
     {
         GETGROUPPRIVS();
@@ -917,12 +954,14 @@ inc_done (int status)
 static int
 pop_action(void *closure, char *s)
 {
 static int
 pop_action(void *closure, char *s)
 {
-    NMH_UNUSED(closure);
+    pop_closure *pc;
+    int n;
 
 
-    if (fputs(s, pf) == EOF || putc('\n', pf) == EOF)
+    pc = closure;
+    n = fprintf(pc->mailout, "%s\n", s);
+    if (n < 0)
         return NOTOK;
         return NOTOK;
-
-    stop += strlen(s) + 1; /* Count linefeed too. */
+    pc->written += n; /* Count linefeed too. */
 
     return OK;
 }
 
     return OK;
 }