]> diplodocus.org Git - nmh/blobdiff - uip/mhbuildsbr.c
Add basic support for the STLS command in POP
[nmh] / uip / mhbuildsbr.c
index fc90dc0151d331531deba92376868f291668f018..c7b969c7bd235526fe92d0cb23a8039d05f373d5 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * mhbuildsbr.c -- routines to expand/translate MIME composition files
+/* mhbuildsbr.c -- routines to expand/translate MIME composition files
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  * streamlining and removal of unneeded code.
  */
 
-#include <h/mh.h>
+#include "h/mh.h"
+#include "sbr/m_gmprot.h"
+#include "sbr/m_getfld.h"
+#include "sbr/concat.h"
+#include "sbr/r1bindex.h"
+#include "sbr/encode_rfc2047.h"
+#include "sbr/copyip.h"
+#include "sbr/cpydata.h"
+#include "sbr/trimcpy.h"
+#include "sbr/uprf.h"
+#include "sbr/check_charset.h"
+#include "sbr/getcpy.h"
+#include "sbr/m_convert.h"
+#include "sbr/getfolder.h"
+#include "sbr/folder_read.h"
+#include "sbr/folder_free.h"
+#include "sbr/context_find.h"
+#include "sbr/brkstring.h"
+#include "sbr/pidstatus.h"
+#include "sbr/path.h"
+#include "sbr/error.h"
 #include <fcntl.h>
-#include <h/md5.h>
-#include <h/mts.h>
-#include <h/tws.h>
-#include <h/mime.h>
-#include <h/mhparse.h>
-#include <h/utils.h>
+#include "h/md5.h"
+#include "h/mts.h"
+#include "h/tws.h"
+#include "h/fmt_scan.h"
+#include "h/mime.h"
+#include "h/mhparse.h"
+#include "h/done.h"
+#include "h/utils.h"
+#include "h/mhcachesbr.h"
+#include "mhmisc.h"
+#include "sbr/m_mktemp.h"
+#include "sbr/message_id.h"
+#include "sbr/mime_type.h"
+#include "mhfree.h"
+#include "mhshowsbr.h"
 
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 
 extern int debugsw;
 
-extern int listsw;
-extern int rfc934sw;
-extern int contentidsw;
-
-/* cache policies */
-extern int rcachesw;   /* mhcachesbr.c */
-extern int wcachesw;   /* mhcachesbr.c */
+extern bool listsw;
+extern bool rfc934sw;
+extern bool contentidsw;
 
 static char prefix[] = "----- =_aaaaaaaaaa";
 
@@ -54,24 +77,6 @@ typedef struct convert_list {
     struct convert_list *next;
 } convert_list;
 
-/*
- * Maximum size of URL token in message/external-body
- */
-
-#define MAXURLTOKEN 40
-
-
-/* mhmisc.c */
-void content_error (char *, CT, char *, ...);
-
-/* mhcachesbr.c */
-int find_cache (CT, int, int *, char *, char *, int);
-
-/* mhfree.c */
-extern CT *cts;
-void freects_done (int) NORETURN;
-void free_ctinfo (CT);
-void free_encoding (CT, int);
 
 /*
  * static prototypes
@@ -97,12 +102,14 @@ static int extract_headers (CT, char *, FILE **);
 static unsigned char directives_stack[32];
 static unsigned int directives_index;
 
-static int do_direct(void)
+static int
+do_direct(void)
 {
     return directives_stack[directives_index];
 }
 
-static void directive_onoff(int onoff)
+static void
+directive_onoff(int onoff)
 {
     if (directives_index >= sizeof(directives_stack) - 1) {
        fprintf(stderr, "mhbuild: #on/off overflow, continuing\n");
@@ -111,13 +118,15 @@ static void directive_onoff(int onoff)
     directives_stack[++directives_index] = onoff;
 }
 
-static void directive_init(int onoff)
+static void
+directive_init(int onoff)
 {
     directives_index = 0;
     directives_stack[0] = onoff;
 }
 
-static void directive_pop(void)
+static void
+directive_pop(void)
 {
     if (directives_index > 0)
        directives_index--;
@@ -139,14 +148,14 @@ build_mime (char *infile, int autobuild, int dist, int directives,
            int header_encoding, size_t maxunencoded, int verbose)
 {
     int        compnum, state;
-    char buf[BUFSIZ], name[NAMESZ];
+    char buf[NMH_BUFSIZ], name[NAMESZ];
     char *cp, *np, *vp;
     struct multipart *m;
     struct part **pp;
     CT ct;
     FILE *in;
     HF hp;
-    m_getfld_state_t gstate = 0;
+    m_getfld_state_t gstate;
     struct attach_list *attach_head = NULL, *attach_tail = NULL, *at_entry;
     convert_list *convert_head = NULL, *convert_tail = NULL, *convert;
 
@@ -175,10 +184,11 @@ build_mime (char *infile, int autobuild, int dist, int directives,
      * draft into the linked list of header fields for
      * the new MIME message.
      */
-    m_getfld_track_filepos (&gstate, in);
+    gstate = m_getfld_state_init(in);
+    m_getfld_track_filepos2(&gstate);
     for (compnum = 1;;) {
        int bufsz = sizeof buf;
-       switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
+       switch (state = m_getfld2(&gstate, name, buf, &bufsz)) {
        case FLD:
        case FLDPLUS:
            compnum++;
@@ -191,26 +201,26 @@ build_mime (char *infile, int autobuild, int dist, int directives,
                    free (ct);
                    return NULL;
                }
-                adios (NULL, "draft shouldn't contain %s: field", name);
+                die("draft shouldn't contain %s: field", name);
            }
 
            /* ignore any Content-Type fields in the header */
            if (!strcasecmp (name, TYPE_FIELD)) {
                while (state == FLDPLUS) {
                    bufsz = sizeof buf;
-                   state = m_getfld (&gstate, name, buf, &bufsz, in);
+                   state = m_getfld2(&gstate, name, buf, &bufsz);
                }
                goto finish_field;
            }
 
            /* get copies of the buffers */
-           np = add (name, NULL);
-           vp = add (buf, NULL);
+           np = mh_xstrdup(name);
+           vp = mh_xstrdup(buf);
 
            /* if necessary, get rest of field */
            while (state == FLDPLUS) {
                bufsz = sizeof buf;
-               state = m_getfld (&gstate, name, buf, &bufsz, in);
+               state = m_getfld2(&gstate, name, buf, &bufsz);
                vp = add (buf, vp);     /* add to previous value */
            }
 
@@ -254,14 +264,14 @@ build_mime (char *infile, int autobuild, int dist, int directives,
                    attach_head = attach_tail = entry;
                }
            } else if (strncasecmp(MHBUILD_FILE_PSEUDOHEADER, np,
-                                   strlen (MHBUILD_FILE_PSEUDOHEADER)) == 0) {
+                                   LEN(MHBUILD_FILE_PSEUDOHEADER)) == 0) {
                 /* E.g.,
                  * Nmh-mhbuild-file-text/calendar: /home/user/Mail/inbox/9
                  */
-                char *type = np + strlen (MHBUILD_FILE_PSEUDOHEADER);
+                char *type = np + LEN(MHBUILD_FILE_PSEUDOHEADER);
                 char *filename = vp;
 
-                /* vp should begin with a space because m_getfld()
+                /* vp should begin with a space because m_getfld2()
                    includes the space after the colon in buf. */
                 while (isspace((unsigned char) *filename)) { ++filename; }
                 /* Trim trailing newline and any other whitespace. */
@@ -273,7 +283,7 @@ build_mime (char *infile, int autobuild, int dist, int directives,
                 if (convert) {
                     if (convert->filename  &&
                         strcasecmp (convert->filename, filename)) {
-                        adios (NULL, "Multiple %s headers with different files"
+                        die("Multiple %s headers with different files"
                                " not allowed", type);
                     } else {
                         convert->filename = mh_xstrdup(filename);
@@ -294,14 +304,14 @@ build_mime (char *infile, int autobuild, int dist, int directives,
                 free (vp);
                 free (np);
             } else if (strncasecmp(MHBUILD_ARGS_PSEUDOHEADER, np,
-                                   strlen (MHBUILD_ARGS_PSEUDOHEADER)) == 0) {
+                                   LEN(MHBUILD_ARGS_PSEUDOHEADER)) == 0) {
                 /* E.g.,
                  * Nmh-mhbuild-args-text/calendar: -reply accept
                  */
-                char *type = np + strlen (MHBUILD_ARGS_PSEUDOHEADER);
+                char *type = np + LEN(MHBUILD_ARGS_PSEUDOHEADER);
                 char *argstring = vp;
 
-                /* vp should begin with a space because m_getfld()
+                /* vp should begin with a space because m_getfld2()
                    includes the space after the colon in buf. */
                 while (isspace((unsigned char) *argstring)) { ++argstring; }
                 /* Trim trailing newline and any other whitespace. */
@@ -313,7 +323,7 @@ build_mime (char *infile, int autobuild, int dist, int directives,
                 if (convert) {
                     if (convert->argstring  &&
                         strcasecmp (convert->argstring, argstring)) {
-                        adios (NULL, "Multiple %s headers with different "
+                        die("Multiple %s headers with different "
                                "argstrings not allowed", type);
                     } else {
                         convert->argstring = mh_xstrdup(argstring);
@@ -343,16 +353,16 @@ finish_field:
 
        case BODY:
            fseek (in, (long) (-strlen (buf)), SEEK_CUR);
-           /* fall through */
+           break;
        case FILEEOF:
            break;
 
        case LENERR:
        case FMTERR:
-           adios (NULL, "message format error in component #%d", compnum);
+           die("message format error in component #%d", compnum);
 
        default:
-           adios (NULL, "getfld() returned %d", state);
+           die("getfld() returned %d", state);
        }
        break;
     }
@@ -366,7 +376,7 @@ finish_field:
 
         for (hp = ct->c_first_hf; hp != NULL; hp = hp->next) {
             if (encode_rfc2047(hp->name, &hp->value, header_encoding, NULL)) {
-                adios(NULL, "Unable to encode header \"%s\"", hp->name);
+                die("Unable to encode header \"%s\"", hp->name);
             }
         }
     }
@@ -377,13 +387,13 @@ finish_field:
      */
 
     if (! dist) {
-       np = add (VRSN_FIELD, NULL);
+       np = mh_xstrdup(VRSN_FIELD);
        vp = concat (" ", VRSN_VALUE, "\n", NULL);
        add_header (ct, np, vp);
     }
 
     /*
-     * We initally assume we will find multiple contents in the
+     * We initially assume we will find multiple contents in the
      * draft.  So create a multipart/mixed content to hold everything.
      * We can remove this later, if it is not needed.
      */
@@ -405,7 +415,7 @@ finish_field:
        CT p;
 
        if (user_content (in, buf, &p, infile) == DONE) {
-           admonish (NULL, "ignoring spurious #end");
+           inform("ignoring spurious #end, continuing...");
            continue;
        }
        if (!p)
@@ -460,7 +470,7 @@ finish_field:
         CT *ctp;
         convert_list *next;
 
-        done = freects_done;
+        set_done(freects_done);
 
         /* In case there are multiple calls that land here, prevent leak. */
         for (ctp = cts; ctp && *ctp; ++ctp) { free_content (*ctp); }
@@ -469,7 +479,7 @@ finish_field:
         /* Extract the type part (as a CT) from filename. */
         cts = mh_xcalloc(2, sizeof *cts);
         if (! (cts[0] = parse_mime (convert_head->filename))) {
-            adios (NULL, "failed to parse %s", convert_head->filename);
+            die("failed to parse %s", convert_head->filename);
         }
 
         expand_pseudoheaders (cts[0], m, infile, convert_head);
@@ -557,7 +567,7 @@ finish_field:
     compose_content (ct, verbose);
 
     if ((cp = strchr(prefix, 'a')) == NULL)
-       adios (NULL, "internal error(4)");
+       die("internal error(4)");
 
     /*
      * If using EAI, force 8-bit charset.
@@ -576,9 +586,8 @@ finish_field:
            (*cp)++;
         } else {
            if (*++cp == 0)
-               adios (NULL, "giving up trying to find a unique delimiter string");
-           else
-               (*cp)++;
+               die("giving up trying to find a unique delimiter string");
+            (*cp)++;
        }
     }
 
@@ -602,7 +611,7 @@ init_decoded_content (CT ct, const char *filename)
     ct->c_ceclosefnx = close_encoding;
     ct->c_cesizefnx  = NULL;           /* since unencoded */
     ct->c_encoding = CE_7BIT;          /* Seems like a reasonable default */
-    ct->c_file = add(filename, NULL);
+    ct->c_file = mh_xstrdup(FENDNULL(filename));
 
     return OK;
 }
@@ -612,23 +621,26 @@ static char *
 fgetstr (char *s, int n, FILE *stream)
 {
     char *cp, *ep;
-    int o_n = n;
 
+    ep = s + n;
     while(1) {
-       for (ep = (cp = s) + o_n; cp < ep; ) {
-           int i;
+       for (cp = s; cp < ep;) {
+           int len;
 
            if (!fgets (cp, n, stream))
-               return (cp != s ? s : NULL);
+                return cp == s ? NULL : s; /* "\\\nEOF" ignored. */
 
-           if (cp == s && *cp != '#')
-               return s;
+           if (! do_direct()  ||  (cp == s && *cp != '#'))
+               return s; /* Plaintext line. */
 
-           cp += (i = strlen (cp)) - 1;
-           if (i <= 1 || *cp-- != '\n' || *cp != '\\')
+           len = strlen(cp);
+           if (len <= 1)
+               break; /* Can't contain "\\\n". */
+           cp += len - 1; /* Just before NUL. */
+           if (*cp-- != '\n' || *cp != '\\')
                break;
-           *cp = '\0';
-           n -= (i - 2);
+           *cp = '\0'; /* Erase the trailing "\\\n". */
+           n -= (len - 2);
        }
 
        if (strcmp(s, "#on\n") == 0) {
@@ -638,11 +650,9 @@ fgetstr (char *s, int n, FILE *stream)
        } else if (strcmp(s, "#pop\n") == 0) {
            directive_pop();
        } else {
-           break;
+           return s;
        }
     }
-
-    return s;
 }
 
 
@@ -656,7 +666,7 @@ user_content (FILE *in, char *buf, CT *ctp, const char *infilename)
 {
     int        extrnal, vrsn;
     char *cp, **ap;
-    char buffer[BUFSIZ];
+    char buffer[NMH_BUFSIZ];
     struct multipart *m;
     struct part **pp;
     struct stat st;
@@ -691,7 +701,7 @@ user_content (FILE *in, char *buf, CT *ctp, const char *infilename)
      */
     if (!do_direct() || buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
        int headers;
-       int inlineD;
+       bool inlineD;
        long pos;
        char content[BUFSIZ];
        FILE *out;
@@ -703,15 +713,15 @@ user_content (FILE *in, char *buf, CT *ctp, const char *infilename)
        }
 
        /* use a temp file to collect the plain text lines */
-       ce->ce_file = add (cp, NULL);
+       ce->ce_file = mh_xstrdup(cp);
        ce->ce_unlink = 1;
 
        if (do_direct() && (buf[0] == '#' && buf[1] == '<')) {
            strncpy (content, buf + 2, sizeof(content));
-           inlineD = 1;
+           inlineD = true;
            goto rock_and_roll;
        }
-        inlineD = 0;
+        inlineD = false;
 
        /* the directive is implicit */
        strncpy (content, "text/plain", sizeof(content));
@@ -721,13 +731,13 @@ user_content (FILE *in, char *buf, CT *ctp, const char *infilename)
            int i;
 
            if (headers >= 0 && do_direct() && uprf (buffer, DESCR_FIELD)
-               && buffer[i = strlen (DESCR_FIELD)] == ':') {
+               && buffer[i = LEN(DESCR_FIELD)] == ':') {
                headers = 1;
 
 again_descr:
                ct->c_descr = add (buffer + i + 1, ct->c_descr);
                if (!fgetstr (buffer, sizeof(buffer) - 1, in))
-                   adios (NULL, "end-of-file after %s: field in plaintext", DESCR_FIELD);
+                   die("end-of-file after %s: field in plaintext", DESCR_FIELD);
                switch (buffer[0]) {
                case ' ':
                case '\t':
@@ -735,7 +745,7 @@ again_descr:
                    goto again_descr;
 
                case '#':
-                   adios (NULL, "#-directive after %s: field in plaintext", DESCR_FIELD);
+                   die("#-directive after %s: field in plaintext", DESCR_FIELD);
                    /* NOTREACHED */
 
                default:
@@ -744,13 +754,13 @@ again_descr:
            }
 
            if (headers >= 0 && do_direct() && uprf (buffer, DISPO_FIELD)
-               && buffer[i = strlen (DISPO_FIELD)] == ':') {
+               && buffer[i = LEN(DISPO_FIELD)] == ':') {
                headers = 1;
 
 again_dispo:
                ct->c_dispo = add (buffer + i + 1, ct->c_dispo);
                if (!fgetstr (buffer, sizeof(buffer) - 1, in))
-                   adios (NULL, "end-of-file after %s: field in plaintext", DISPO_FIELD);
+                   die("end-of-file after %s: field in plaintext", DISPO_FIELD);
                switch (buffer[0]) {
                case ' ':
                case '\t':
@@ -758,7 +768,7 @@ again_dispo:
                    goto again_dispo;
 
                case '#':
-                   adios (NULL, "#-directive after %s: field in plaintext", DISPO_FIELD);
+                   die("#-directive after %s: field in plaintext", DISPO_FIELD);
                    /* NOTREACHED */
 
                default:
@@ -808,9 +818,9 @@ rock_and_roll:
                ct->c_encoding = CE_7BIT;
                goto call_init;
            }
-           /* else fall... */
+           /* FALLTHRU */
        case CT_MULTIPART:
-           adios (NULL, "it doesn't make sense to define an in-line %s content",
+           die("it doesn't make sense to define an in-line %s content",
                   ct->c_type == CT_MESSAGE ? "message" : "multipart");
            /* NOTREACHED */
 
@@ -852,24 +862,23 @@ call_init:
      */
     if (s2i->si_key) {
        if (!ci->ci_subtype)
-           adios (NULL, "missing subtype in \"#%s\"", ci->ci_type);
+           die("missing subtype in \"#%s\"", ci->ci_type);
 
        switch (ct->c_type = s2i->si_val) {
        case CT_MULTIPART:
-           adios (NULL, "use \"#begin ... #end\" instead of \"#%s/%s\"",
+           die("use \"#begin ... #end\" instead of \"#%s/%s\"",
                   ci->ci_type, ci->ci_subtype);
            /* NOTREACHED */
 
        case CT_MESSAGE:
            if (!strcasecmp (ci->ci_subtype, "partial"))
-               adios (NULL, "sorry, \"#%s/%s\" isn't supported",
+               die("sorry, \"#%s/%s\" isn't supported",
                       ci->ci_type, ci->ci_subtype);
            if (!strcasecmp (ci->ci_subtype, "external-body"))
-               adios (NULL, "use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"",
+               die("use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"",
                       ci->ci_type, ci->ci_subtype);
 use_forw:
-           adios (NULL,
-                  "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"",
+           die(                   "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"",
                   ci->ci_type, ci->ci_subtype);
            /* NOTREACHED */
 
@@ -887,7 +896,7 @@ use_forw:
            CT p;
 
            if (!ci->ci_magic)
-               adios (NULL, "need external information for \"#@%s/%s\"",
+               die("need external information for \"#@%s/%s\"",
                       ci->ci_type, ci->ci_subtype);
            p = ct;
 
@@ -929,8 +938,8 @@ use_forw:
                for (cp = ci->ci_magic + 1; isspace ((unsigned char) *cp); cp++)
                    continue;
                if (!*cp)
-                   adios (NULL, "empty pipe command for #%s directive", ci->ci_type);
-               cp = add (cp, NULL);
+                   die("empty pipe command for #%s directive", ci->ci_type);
+               cp = mh_xstrdup(cp);
                free (ci->ci_magic);
                ci->ci_magic = cp;
            } else {
@@ -954,12 +963,12 @@ use_forw:
            content_error (NULL, ct, "don't know how to compose content");
            done (1);
        }
-       ci->ci_magic = add (cp, NULL);
+       ci->ci_magic = mh_xstrdup(cp);
        return OK;
     }
 
     if (extrnal)
-       adios (NULL, "external definition not allowed for \"#%s\"", ci->ci_type);
+       die("external definition not allowed for \"#%s\"", ci->ci_type);
 
     /*
      * Message directive
@@ -984,18 +993,17 @@ use_forw:
            cp = *ap;
            if (*cp == '+' || *cp == '@') {
                if (folder)
-                   adios (NULL, "only one folder per #forw directive");
-               else
-                   folder = pluspath (cp);
+                   die("only one folder per #forw directive");
+                folder = pluspath (cp);
            }
        }
 
        /* else, use the current folder */
        if (!folder)
-           folder = add (getfolder (1), NULL);
+           folder = mh_xstrdup(getfolder(1));
 
        if (!(mp = folder_read (folder, 0)))
-           adios (NULL, "unable to read folder %s", folder);
+           die("unable to read folder %s", folder);
        for (ap = arguments; *ap; ap++) {
            cp = *ap;
            if (*cp != '+' && *cp != '@')
@@ -1037,7 +1045,7 @@ use_forw:
                    p->c_subtype = MESSAGE_RFC822;
 
                    snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum);
-                   pe->ce_file = add (buffer, NULL);
+                   pe->ce_file = mh_xstrdup(buffer);
                    if (listsw && stat (pe->ce_file, &st) != NOTOK)
                        p->c_end = (long) st.st_size;
 
@@ -1056,7 +1064,7 @@ use_forw:
 
            msgnum = mp->lowsel;
            snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum);
-           ce->ce_file = add (buffer, NULL);
+           ce->ce_file = mh_xstrdup(buffer);
            if (listsw && stat (ce->ce_file, &st) != NOTOK)
                ct->c_end = (long) st.st_size;
        }
@@ -1111,7 +1119,7 @@ use_forw:
 
            if (user_content (in, buffer, &p, infilename) == DONE) {
                if (!m->mp_parts)
-                   adios (NULL, "empty \"#begin ... #end\" sequence");
+                   die("empty \"#begin ... #end\" sequence");
                return OK;
            }
            if (!p)
@@ -1122,14 +1130,14 @@ use_forw:
            pp = &part->mp_next;
            part->mp_part = p;
        }
-       admonish (NULL, "premature end-of-file, missing #end");
+       inform("premature end-of-file, missing #end, continuing...");
        return OK;
     }
 
     /*
      * Unknown directive
      */
-    adios (NULL, "unknown directive \"#%s\"", ci->ci_type);
+    die("unknown directive \"#%s\"", ci->ci_type);
     return NOTOK;      /* NOT REACHED */
 }
 
@@ -1185,7 +1193,7 @@ compose_content (CT ct, int verbose)
            CT p = part->mp_part;
 
            sprintf (pp, "%d", partnum);
-           p->c_partno = add (partnam, NULL);
+           p->c_partno = mh_xstrdup(partnam);
            if (compose_content (p, verbose) == NOTOK)
                return NOTOK;
        }
@@ -1197,13 +1205,13 @@ compose_content (CT ct, int verbose)
         * subparts with the rfc934 compatibility mode flag.
         */
        if (rfc934sw && ct->c_subtype == MULTI_DIGEST) {
-           int is934 = 1;
+           bool is934 = true;
 
            for (part = m->mp_parts; part; part = part->mp_next) {
                CT p = part->mp_part;
 
                if (p->c_subtype != MESSAGE_RFC822) {
-                   is934 = 0;
+                   is934 = false;
                    break;
                }
            }
@@ -1219,7 +1227,7 @@ compose_content (CT ct, int verbose)
        if (listsw) {
            ct->c_end = (partnum = strlen (prefix) + 2) + 2;
            if (ct->c_rfc934)
-               ct->c_end += 1;
+               ct->c_end++;
 
            for (part = m->mp_parts; part; part = part->mp_next)
                ct->c_end += part->mp_part->c_end + partnum;
@@ -1237,7 +1245,8 @@ compose_content (CT ct, int verbose)
     default:
        if (!ce->ce_file) {
            pid_t child_id;
-           int i, xstdout, len, buflen;
+           bool xstdout;
+            int len, buflen;
            char *bp, *cp;
            char *vec[4], buffer[BUFSIZ];
            FILE *out;
@@ -1245,16 +1254,16 @@ compose_content (CT ct, int verbose)
             char *tfile = NULL;
 
            if (!(cp = ci->ci_magic))
-               adios (NULL, "internal error(5)");
+               die("internal error(5)");
 
            if ((tfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) {
                adios("mhbuildsbr", "unable to create temporary file in %s",
                      get_temp_dir());
            }
-           ce->ce_file = add (tfile, NULL);
+           ce->ce_file = mh_xstrdup(tfile);
            ce->ce_unlink = 1;
 
-           xstdout = 0;
+           xstdout = false;
 
            /* Get buffer ready to go */
            bp = buffer;
@@ -1286,8 +1295,8 @@ compose_content (CT ct, int verbose)
 
                    case 'F':
                        /* %f, and stdout is not-redirected */
-                       xstdout = 1;
-                       /* and fall... */
+                       xstdout = true;
+                       /* FALLTHRU */
 
                    case 'f':
                        /*
@@ -1337,8 +1346,7 @@ raw:
            if ((out = fopen (ce->ce_file, "w")) == NULL)
                adios (ce->ce_file, "unable to open for writing");
 
-           for (i = 0; (child_id = fork()) == NOTOK && i > 5; i++)
-               sleep (5);
+           child_id = fork();
            switch (child_id) {
            case NOTOK:
                adios ("fork", "unable to fork");
@@ -1351,7 +1359,7 @@ raw:
                execvp ("/bin/sh", vec);
                fprintf (stderr, "unable to exec ");
                perror ("/bin/sh");
-               _exit (-1);
+               _exit(1);
                /* NOTREACHED */
 
            default:
@@ -1393,12 +1401,12 @@ static int
 scan_content (CT ct, size_t maxunencoded)
 {
     int prefix_len;
-    int check8bit = 0, contains8bit = 0;  /* check if contains 8bit data */
-    int checknul = 0, containsnul = 0;  /* check if contains NULs */
-    int checklinelen = 0, linelen = 0;  /* check for long lines */
-    int checkllinelen = 0; /* check for extra-long lines */
-    int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary   */
-    int checklinespace = 0, linespace = 0;  /* check if any line ends with space          */
+    bool check8bit = false, contains8bit = false;  /* check if contains 8bit data */
+    bool checknul = false, containsnul = false;  /* check if contains NULs */
+    bool checklinelen = false, linelen = false;  /* check for long lines */
+    bool checkllinelen = false; /* check for extra-long lines */
+    bool checkboundary = false, boundaryclash = false; /* check if clashes with multipart boundary   */
+    bool checklinespace = false, linespace = false;  /* check if any line ends with space          */
     char *cp = NULL;
     char *bufp = NULL;
     size_t buflen;
@@ -1446,18 +1454,18 @@ scan_content (CT ct, size_t maxunencoded)
     if (ct->c_type == CT_TEXT) {
        t = (struct text *) ct->c_ctparams;
        if (t->tx_charset == CHARSET_UNSPECIFIED) {
-           checknul = 1;
+           checknul = true;
        }
-       check8bit = 1;
+       check8bit = true;
     }
 
     switch (ct->c_reqencoding) {
     case CE_8BIT:
-       checkllinelen = 1;
-       checkboundary = 1;
+       checkllinelen = true;
+       checkboundary = true;
        break;
     case CE_QUOTED:
-       checkboundary = 1;
+       checkboundary = true;
        break;
     case CE_BASE64:
        break;
@@ -1465,34 +1473,34 @@ scan_content (CT ct, size_t maxunencoded)
        /* Use the default rules based on content-type */
        switch (ct->c_type) {
        case CT_TEXT:
-           checkboundary = 1;
-           checklinelen = 1;
+           checkboundary = true;
+           checklinelen = true;
            if (ct->c_subtype == TEXT_PLAIN) {
-               checklinespace = 0;
+               checklinespace = false;
            } else {
-               checklinespace = 1;
+               checklinespace = true;
            }
        break;
 
        case CT_APPLICATION:
-           check8bit = 1;
-           checknul = 1;
-           checklinelen = 1;
-           checklinespace = 1;
-           checkboundary = 1;
+           check8bit = true;
+           checknul = true;
+           checklinelen = true;
+           checklinespace = true;
+           checkboundary = true;
        break;
 
        case CT_MESSAGE:
-           checklinelen = 0;
-           checklinespace = 0;
+           checklinelen = false;
+           checklinespace = false;
 
            /* don't check anything for message/external */
            if (ct->c_subtype == MESSAGE_EXTERNAL) {
-               checkboundary = 0;
-               check8bit = 0;
+               checkboundary = false;
+               check8bit = false;
            } else {
-               checkboundary = 1;
-               check8bit = 1;
+               checkboundary = true;
+               check8bit = true;
            }
            break;
 
@@ -1504,10 +1512,10 @@ scan_content (CT ct, size_t maxunencoded)
             * since we are forcing use of base64, unless
             * the content-type was specified by a mhbuild directive.
             */
-           check8bit = 0;
-           checklinelen = 0;
-           checklinespace = 0;
-           checkboundary = 0;
+           check8bit = false;
+           checklinelen = false;
+           checklinespace = false;
+           checkboundary = false;
            break;
        }
     }
@@ -1528,12 +1536,12 @@ scan_content (CT ct, size_t maxunencoded)
            for (cp = bufp; (check8bit || checknul) &&
                                        cp < bufp + gotlen; cp++) {
                if (!isascii ((unsigned char) *cp)) {
-                   contains8bit = 1;
-                   check8bit = 0;      /* no need to keep checking */
+                   contains8bit = true;
+                   check8bit = false;  /* no need to keep checking */
                }
                if (!*cp) {
-                   containsnul = 1;
-                   checknul = 0;       /* no need to keep checking */
+                   containsnul = true;
+                   checknul = false;   /* no need to keep checking */
                }
            }
 
@@ -1541,8 +1549,8 @@ scan_content (CT ct, size_t maxunencoded)
             * Check line length.
             */
            if (checklinelen && ((size_t)gotlen > maxunencoded + 1)) {
-               linelen = 1;
-               checklinelen = 0;       /* no need to keep checking */
+               linelen = true;
+               checklinelen = false;   /* no need to keep checking */
            }
 
            /*
@@ -1553,7 +1561,7 @@ scan_content (CT ct, size_t maxunencoded)
 
            if (checkllinelen && !linelen &&
                                        (gotlen > MAXLONGLINE + 1)) {
-               adios(NULL, "Line in content exceeds maximum line limit (%d)",
+               die("Line in content exceeds maximum line limit (%d)",
                      MAXLONGLINE);
            }
 
@@ -1562,8 +1570,8 @@ scan_content (CT ct, size_t maxunencoded)
             */
            if (checklinespace && (cp = bufp + gotlen - 2) > bufp &&
                        isspace ((unsigned char) *cp)) {
-               linespace = 1;
-               checklinespace = 0;     /* no need to keep checking */
+               linespace = true;
+               checklinespace = false; /* no need to keep checking */
            }
 
            /*
@@ -1577,8 +1585,8 @@ scan_content (CT ct, size_t maxunencoded)
                *++cp = '\0';
                if (!strncmp(bufp + 2, prefix, prefix_len) &&
                            isdigit((unsigned char) bufp[2 + prefix_len])) {
-                   boundaryclash = 1;
-                   checkboundary = 0;  /* no need to keep checking */
+                   boundaryclash = true;
+                   checkboundary = false;      /* no need to keep checking */
                }
            }
        }
@@ -1637,7 +1645,7 @@ scan_content (CT ct, size_t maxunencoded)
         }
     }
 
-    return (boundaryclash ? NOTOK : OK);
+    return boundaryclash ? NOTOK : OK;
 }
 
 
@@ -1678,11 +1686,11 @@ build_headers (CT ct, int header_encoding)
     /*
      * output the content type and subtype
      */
-    np = add (TYPE_FIELD, NULL);
+    np = mh_xstrdup(TYPE_FIELD);
     vp = concat (" ", ci->ci_type, "/", ci->ci_subtype, NULL);
 
     /* keep track of length of line */
-    len = strlen (TYPE_FIELD) + strlen (ci->ci_type)
+    len = LEN(TYPE_FIELD) + strlen (ci->ci_type)
                + strlen (ci->ci_subtype) + 3;
 
     extbody = ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_EXTERNAL;
@@ -1697,7 +1705,7 @@ build_headers (CT ct, int header_encoding)
        char *s = output_params(len, ci->ci_first_pm, &len, mailbody);
 
        if (!s)
-           adios(NULL, "Internal error: failed outputting Content-Type "
+           die("Internal error: failed outputting Content-Type "
                "parameters");
 
        vp = add (s, vp);
@@ -1724,10 +1732,12 @@ build_headers (CT ct, int header_encoding)
     add_header (ct, np, vp);
 
     /*
-     * output the Content-ID, unless disabled by -nocontentid
+     * output the Content-ID, unless disabled by -nocontentid.  Note that
+     * RFC 2045 always requires a Content-ID header for message/external-body
+     * entities.
      */
-    if (contentidsw && ct->c_id) {
-       np = add (ID_FIELD, NULL);
+    if ((contentidsw || ct->c_ctexbody) && ct->c_id) {
+       np = mh_xstrdup(ID_FIELD);
        vp = concat (" ", ct->c_id, NULL);
        add_header (ct, np, vp);
     }
@@ -1735,11 +1745,11 @@ build_headers (CT ct, int header_encoding)
      * output the Content-Description
      */
     if (ct->c_descr) {
-       np = add (DESCR_FIELD, NULL);
+       np = mh_xstrdup(DESCR_FIELD);
        vp = concat (" ", ct->c_descr, NULL);
        if (header_encoding != CE_8BIT) {
            if (encode_rfc2047(DESCR_FIELD, &vp, header_encoding, NULL)) {
-               adios(NULL, "Unable to encode %s header", DESCR_FIELD);
+               die("Unable to encode %s header", DESCR_FIELD);
            }
        }
        add_header (ct, np, vp);
@@ -1750,16 +1760,16 @@ build_headers (CT ct, int header_encoding)
      * set, then we need to build it.
      */
     if (ct->c_dispo) {
-       np = add (DISPO_FIELD, NULL);
+       np = mh_xstrdup(DISPO_FIELD);
        vp = concat (" ", ct->c_dispo, NULL);
        add_header (ct, np, vp);
     } else if (ct->c_dispo_type) {
        vp = concat (" ", ct->c_dispo_type, NULL);
-       len = strlen(DISPO_FIELD) + strlen(vp) + 1;
+       len = LEN(DISPO_FIELD) + strlen(vp) + 1;
        np = output_params(len, ct->c_dispo_first, NULL, 0);
        vp = add(np, vp);
        vp = add("\n", vp);
-        mh_xfree(np);
+        free(np);
        add_header (ct, mh_xstrdup(DISPO_FIELD), vp);
     }
 
@@ -1776,8 +1786,8 @@ skip_headers:
      * output the Content-MD5
      */
     if (checksw) {
-       np = add (MD5_FIELD, NULL);
-       vp = calculate_digest (ct, (ct->c_encoding == CE_QUOTED) ? 1 : 0);
+       np = mh_xstrdup(MD5_FIELD);
+        vp = calculate_digest (ct, ct->c_encoding == CE_QUOTED);
        add_header (ct, np, vp);
     }
 
@@ -1795,40 +1805,40 @@ skip_headers:
        break;
 
     case CE_8BIT:
-       np = add (ENCODING_FIELD, NULL);
+       np = mh_xstrdup(ENCODING_FIELD);
        vp = concat (" ", "8bit", "\n", NULL);
        add_header (ct, np, vp);
        break;
 
     case CE_QUOTED:
        if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART)
-           adios (NULL, "internal error, invalid encoding");
+           die("internal error, invalid encoding");
 
-       np = add (ENCODING_FIELD, NULL);
+       np = mh_xstrdup(ENCODING_FIELD);
        vp = concat (" ", "quoted-printable", "\n", NULL);
        add_header (ct, np, vp);
        break;
 
     case CE_BASE64:
        if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART)
-           adios (NULL, "internal error, invalid encoding");
+           die("internal error, invalid encoding");
 
-       np = add (ENCODING_FIELD, NULL);
+       np = mh_xstrdup(ENCODING_FIELD);
        vp = concat (" ", "base64", "\n", NULL);
        add_header (ct, np, vp);
        break;
 
     case CE_BINARY:
        if (ct->c_type == CT_MESSAGE)
-           adios (NULL, "internal error, invalid encoding");
+           die("internal error, invalid encoding");
 
-       np = add (ENCODING_FIELD, NULL);
+       np = mh_xstrdup(ENCODING_FIELD);
        vp = concat (" ", "binary", "\n", NULL);
        add_header (ct, np, vp);
        break;
 
     default:
-       adios (NULL, "unknown transfer encoding in content");
+       die("unknown transfer encoding in content");
        break;
     }
 
@@ -1927,7 +1937,7 @@ calculate_digest (CT ct, int asciiP)
        unsigned char *ep;
 
        fprintf (stderr, "MD5 digest=");
-       for (ep = (dp = digest) + sizeof(digest) / sizeof(digest[0]);
+       for (ep = (dp = digest) + sizeof digest;
                 dp < ep; dp++)
            fprintf (stderr, "%02x", *dp & 0xff);
        fprintf (stderr, "\n");
@@ -1935,7 +1945,7 @@ calculate_digest (CT ct, int asciiP)
 
     /* encode the digest using base64 */
     for (dp = digest, op = (char *) outbuf,
-                               cc = sizeof(digest) / sizeof(digest[0]);
+                               cc = sizeof digest;
                cc > 0; cc -= 3, op += 4) {
        unsigned long bits;
        char *bp;
@@ -1977,12 +1987,12 @@ setup_attach_content(CT ct, char *filename)
     PM pm;
 
     if (! (type = mime_type(filename))) {
-       adios(NULL, "Unable to determine MIME type of \"%s\"", filename);
+       die("Unable to determine MIME type of \"%s\"", filename);
     }
 
     /*
      * Parse the Content-Type.  get_ctinfo() parses MIME parameters, but
-     * since we're just feeding it a MIME type we have to add those ourself.
+     * since we're just feeding it a MIME type we have to add those ourselves.
      * Map that to a valid content-type label and call any initialization
      * function.
      */
@@ -2004,17 +2014,17 @@ setup_attach_content(CT ct, char *filename)
 
     switch (ct->c_type = s2i->si_val) {
     case CT_MULTIPART:
-       adios (NULL, "multipart types must be specified by mhbuild directives");
+       die("multipart types must be specified by mhbuild directives");
        /* NOTREACHED */
 
     case CT_MESSAGE:
        if (strcasecmp(ct->c_ctinfo.ci_subtype, "partial") == 0)
-           adios(NULL, "Sorry, %s/%s isn't supported", ct->c_ctinfo.ci_type,
+           die("Sorry, %s/%s isn't supported", ct->c_ctinfo.ci_type,
                ct->c_ctinfo.ci_subtype);
        if (strcasecmp(ct->c_ctinfo.ci_subtype, "external-body") == 0)
-           adios(NULL, "external-body messages must be specified "
+           die("external-body messages must be specified "
                "by mhbuild directives");
-       /* Fall through */
+       /* FALLTHRU */
 
     default:
        /*
@@ -2032,7 +2042,7 @@ setup_attach_content(CT ct, char *filename)
 
     for (pm = ct->c_ctinfo.ci_first_pm; pm; pm = pm->pm_next) {
        if (strcasecmp(pm->pm_name, "name") == 0) {
-            mh_xfree(pm->pm_value);
+            free(pm->pm_value);
            pm->pm_value = mh_xstrdup(simplename);
            break;
        }
@@ -2059,20 +2069,21 @@ setup_attach_content(CT ct, char *filename)
  * 'attachment'.
  */
 void
-set_disposition (CT ct) {
+set_disposition (CT ct)
+{
     if (ct->c_dispo_type == NULL) {
         char *cp = context_find_by_type ("disposition", ct->c_ctinfo.ci_type,
                                          ct->c_ctinfo.ci_subtype);
 
         if (cp  &&  strcasecmp (cp, "attachment")  &&
             strcasecmp (cp, "inline")) {
-            admonish (NULL, "configuration problem: %s-disposition-%s%s%s "
-                      "specifies '%s' but only 'attachment' and 'inline' are "
-                      "allowed", invo_name,
-                      ct->c_ctinfo.ci_type,
-                      ct->c_ctinfo.ci_subtype ? "/" : "",
-                      ct->c_ctinfo.ci_subtype ? ct->c_ctinfo.ci_subtype : "",
-                      cp);
+            inform("configuration problem: %s-disposition-%s%s%s specifies "
+               "'%s' but only 'attachment' and 'inline' are allowed, "
+               "continuing...", invo_name,
+               ct->c_ctinfo.ci_type,
+               ct->c_ctinfo.ci_subtype ? "/" : "",
+               FENDNULL(ct->c_ctinfo.ci_subtype),
+               cp);
         }
 
         if (!cp)
@@ -2083,13 +2094,14 @@ set_disposition (CT ct) {
 
 /*
  * Set text content charset if it was unspecified.  contains8bit
- * selctions:
+ * selections:
  * 0: content does not contain 8-bit characters
  * 1: content contains 8-bit characters
  * -1: ignore content and use user's locale to determine charset
  */
 void
-set_charset (CT ct, int contains8bit) {
+set_charset (CT ct, int contains8bit)
+{
     if (ct->c_type == CT_TEXT) {
         struct text *t;
 
@@ -2108,7 +2120,7 @@ set_charset (CT ct, int contains8bit) {
 
             if (contains8bit == 1  &&
                 strcasecmp (eightbitcharset, "US-ASCII") == 0) {
-                adios (NULL, "Text content contains 8 bit characters, but "
+                die("Text content contains 8 bit characters, but "
                        "character set is US-ASCII");
             }
 
@@ -2128,7 +2140,8 @@ set_charset (CT ct, int contains8bit) {
  */
 void
 expand_pseudoheaders (CT ct, struct multipart *m, const char *infile,
-                      const convert_list *convert_head) {
+                      const convert_list *convert_head)
+{
     /* text_plain_ct is used to concatenate all of the text/plain
        replies into one part, instead of having each one in a separate
        part. */
@@ -2140,7 +2153,7 @@ expand_pseudoheaders (CT ct, struct multipart *m, const char *infile,
         struct part *part;
 
         if (ct->c_subtype == MULTI_ALTERNATE) {
-            int matched = 0;
+            bool matched = false;
 
             /* The parts are in descending priority order (defined by
                RFC 2046 Sec. 5.1.4) because they were reversed by
@@ -2163,7 +2176,7 @@ expand_pseudoheaders (CT ct, struct multipart *m, const char *infile,
                             expand_pseudoheader (part->mp_part, &text_plain_ct,
                                                  m, infile,
                                                  c->type, c->argstring);
-                            matched = 1;
+                            matched = true;
                             break;
                         }
                     }
@@ -2204,7 +2217,8 @@ expand_pseudoheaders (CT ct, struct multipart *m, const char *infile,
 void
 expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
                      const char *infile, const char *type,
-                     const char *argstring) {
+                     const char *argstring)
+{
     char *reply_file;
     FILE *reply_fp = NULL;
     char *convert, *type_p, *subtype_p;
@@ -2214,7 +2228,6 @@ expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
     struct str2init *s2i;
     CT reply_ct;
     struct part *part;
-    int eightbit = 0;
     int status;
 
     type_p = getcpy (type);
@@ -2229,15 +2242,13 @@ expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
     free (type_p);
 
     if (! (convert)) {
-        /* No mhbuild-convert- entry in mhn.defaults or profile
-           for type. */
+        /* No mhbuild-convert- entry in mhn.defaults or profile for type. */
         return;
     }
     /* reply_file is used to pass the output of the convert. */
     reply_file = getcpy (m_mktemp2 (NULL, invo_name, NULL, NULL));
     convert_command =
-        concat (convert, " ", argstring ? argstring : "", " >", reply_file,
-                NULL);
+        concat (convert, " ", FENDNULL(argstring), " >", reply_file, NULL);
 
     /* Convert here . . . */
     ct->c_storeproc = mh_xstrdup(convert_command);
@@ -2245,7 +2256,7 @@ expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
 
     if ((status = show_content_aux (ct, 0, convert_command, NULL, NULL)) !=
         OK) {
-        admonish (NULL, "store of %s content failed", type);
+        inform("store of %s content failed, continuing...", type);
     }
     free (convert_command);
 
@@ -2254,26 +2265,12 @@ expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
     init_decoded_content (reply_ct, infile);
 
     if (extract_headers (reply_ct, reply_file, &reply_fp) == NOTOK) {
-        free (reply_file);
-        admonish (NULL,
-                  "failed to extract headers from convert output in %s",
-                  reply_file);
+        inform("failed to extract headers from convert output in %s, "
+           "continuing...", reply_file);
+        free(reply_file);
         return;
     }
 
-    /* For text content only, see if it is 8-bit text. */
-    if (reply_ct->c_type == CT_TEXT) {
-        int fd;
-
-        if ((fd = open (reply_file, O_RDONLY)) == NOTOK  ||
-            scan_input (fd, &eightbit) == NOTOK) {
-            free (reply_file);
-            admonish (NULL, "failed to read %s", reply_file);
-            return;
-        } 
-        (void) close (fd);
-    }
-
     /* This sets reply_ct->c_ctparams, and reply_ct->c_termproc if the
        charset can't be handled natively. */
     for (s2i = str2cts; s2i->si_key; s2i++) {
@@ -2286,45 +2283,22 @@ expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
         (*reply_ct->c_ctinitfnx)(reply_ct);
     }
 
-    if ((cp =
-         get_param (reply_ct->c_ctinfo.ci_first_pm, "charset", '?', 1))) {
+    if ((cp = get_param (reply_ct->c_ctinfo.ci_first_pm, "charset", '?', 1))) {
         /* The reply Content-Type had the charset. */
         charset = cp;
     } else {
         set_charset (reply_ct, -1);
         charset = get_param (reply_ct->c_ctinfo.ci_first_pm, "charset", '?', 1);
-        if (reply_ct->c_reqencoding == CE_UNKNOWN  &&
-            reply_ct->c_type == CT_TEXT) {
-            /* Assume that 8bit is sufficient (for text).  In other words,
-               don't allow it to be encoded as quoted printable if lines
-               are too long.  This also sidesteps the check for whether
-               it needs to be encoded as binary; instead, it relies on
-               the applicable mhbuild-convert-text directive to ensure
-               that the resultant text is not binary. */
-            reply_ct->c_reqencoding = eightbit  ?  CE_8BIT  :  CE_7BIT;
-        }
     }
 
     /* Concatenate text/plain parts. */
-    if (reply_ct->c_type == CT_TEXT  &&
-        reply_ct->c_subtype == TEXT_PLAIN) {
+    if (reply_ct->c_type == CT_TEXT  &&  reply_ct->c_subtype == TEXT_PLAIN) {
         if (! *text_plain_ct  &&  m->mp_parts  &&  m->mp_parts->mp_part  &&
             m->mp_parts->mp_part->c_type == CT_TEXT  &&
             m->mp_parts->mp_part->c_subtype == TEXT_PLAIN) {
             *text_plain_ct = m->mp_parts->mp_part;
-            /* Make sure that the charset is set in the text/plain
-               part. */
+            /* Make sure that the charset is set in the text/plain part. */
             set_charset (*text_plain_ct, -1);
-            if ((*text_plain_ct)->c_reqencoding == CE_UNKNOWN) {
-                /* Assume that 8bit is sufficient (for text).  In other words,
-                   don't allow it to be encoded as quoted printable if lines
-                   are too long.  This also sidesteps the check for whether
-                   it needs to be encoded as binary; instead, it relies on
-                   the applicable mhbuild-convert-text directive to ensure
-                   that the resultant text is not binary. */
-                (*text_plain_ct)->c_reqencoding =
-                    eightbit  ?  CE_8BIT  :  CE_7BIT;
-            }
         }
 
         if (*text_plain_ct) {
@@ -2393,9 +2367,10 @@ expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m,
 
 /* Extract any Content-Type header from beginning of convert output. */
 int
-extract_headers (CT ct, char *reply_file, FILE **reply_fp) {
+extract_headers (CT ct, char *reply_file, FILE **reply_fp)
+{
     char *buffer = NULL, *cp, *end_of_header;
-    int found_header = 0;
+    bool found_header = false;
     struct stat statbuf;
 
     /* Read the convert reply from the file to memory. */
@@ -2415,14 +2390,14 @@ extract_headers (CT ct, char *reply_file, FILE **reply_fp) {
     buffer[statbuf.st_size] = '\0';
 
     /* Look for a header in the convert reply. */
-    if (strncasecmp (buffer, TYPE_FIELD, strlen (TYPE_FIELD)) == 0  &&
-        buffer[strlen (TYPE_FIELD)] == ':') {
+    if (strncasecmp (buffer, TYPE_FIELD, LEN(TYPE_FIELD)) == 0  &&
+        buffer[LEN(TYPE_FIELD)] == ':') {
         if ((end_of_header = strstr (buffer, "\r\n\r\n"))) {
             end_of_header += 2;
-            found_header = 1;
+            found_header = true;
         } else if ((end_of_header = strstr (buffer, "\n\n"))) {
             ++end_of_header;
-            found_header = 1;
+            found_header = true;
         }
     }
 
@@ -2430,28 +2405,29 @@ extract_headers (CT ct, char *reply_file, FILE **reply_fp) {
         CT tmp_ct;
         char *tmp_file;
         FILE *tmp_f;
-        size_t n;
+        size_t n, written;
 
         /* Truncate buffer to just the C-T. */
         *end_of_header = '\0';
         n = strlen (buffer);
 
         if (get_ctinfo (buffer + 14, ct, 0) != OK) {
-            admonish (NULL, "unable to get content info for reply");
+            inform("unable to get content info for reply, continuing...");
             goto failed_to_extract_ct;
         }
 
         /* Hack.  Use parse_mime() to detect the type/subtype of the
            reply, which we'll use below. */
         tmp_file = getcpy (m_mktemp2 (NULL, invo_name, NULL, NULL));
-        if ((tmp_f = fopen (tmp_file, "w"))  &&
-            fwrite (buffer, 1, n, tmp_f) == n) {
-            fclose (tmp_f);
-        } else {
+        tmp_f = fopen(tmp_file, "w");
+        if (!tmp_f)
+            goto failed_to_extract_ct;
+        written = fwrite(buffer, 1, n, tmp_f);
+        fclose(tmp_f);
+        if (written != n)
             goto failed_to_extract_ct;
-        }
-        tmp_ct = parse_mime (tmp_file);
 
+        tmp_ct = parse_mime (tmp_file);
         if (tmp_ct) {
             /* The type and subtype were detected from the reply
                using parse_mime() above. */
@@ -2483,7 +2459,7 @@ extract_headers (CT ct, char *reply_file, FILE **reply_fp) {
         ct->c_subtype = TEXT_PLAIN;
         if (get_ctinfo ("text/plain", ct, 0) == NOTOK) {
             /* This never should fail, but just in case. */
-            adios (NULL, "unable to get content info for reply");
+            die("unable to get content info for reply");
         }
     }