more constness.
[apps/madmutt.git] / sendlib.c
index d5a6093..7c8ab2b 100644 (file)
--- a/sendlib.c
+++ b/sendlib.c
 #endif
 
 #include "mutt.h"
+#include "ascii.h"
+#include "handler.h"
+#include "recvattach.h"
 #include "mutt_curses.h"
 #include "rfc2047.h"
 #include "rfc2231.h"
 #include "mx.h"
 #include "mime.h"
-#include "mailbox.h"
 #include "copy.h"
 #include "pager.h"
 #include "charset.h"
@@ -29,6 +31,7 @@
 #include "lib/mem.h"
 #include "lib/str.h"
 #include "lib/intl.h"
+#include "lib/debug.h"
 
 #include <string.h>
 #include <stdlib.h>
 
 extern char RFC822Specials[];
 
-static struct sysexits {
-  int v;
-  const char *str;
-} sysexits_h[] = {
-#ifdef EX_USAGE
-  {
-  0xff & EX_USAGE, "Bad usage."},
-#endif
-#ifdef EX_DATAERR
-  {
-  0xff & EX_DATAERR, "Data format error."},
-#endif
-#ifdef EX_NOINPUT
-  {
-  0xff & EX_NOINPUT, "Cannot open input."},
-#endif
-#ifdef EX_NOUSER
-  {
-  0xff & EX_NOUSER, "User unknown."},
-#endif
-#ifdef EX_NOHOST
-  {
-  0xff & EX_NOHOST, "Host unknown."},
-#endif
-#ifdef EX_UNAVAILABLE
-  {
-  0xff & EX_UNAVAILABLE, "Service unavailable."},
-#endif
-#ifdef EX_SOFTWARE
-  {
-  0xff & EX_SOFTWARE, "Internal error."},
-#endif
-#ifdef EX_OSERR
-  {
-  0xff & EX_OSERR, "Operating system error."},
-#endif
-#ifdef EX_OSFILE
-  {
-  0xff & EX_OSFILE, "System file missing."},
-#endif
-#ifdef EX_CANTCREAT
-  {
-  0xff & EX_CANTCREAT, "Can't create output."},
-#endif
-#ifdef EX_IOERR
-  {
-  0xff & EX_IOERR, "I/O error."},
-#endif
-#ifdef EX_TEMPFAIL
-  {
-  0xff & EX_TEMPFAIL, "Deferred."},
-#endif
-#ifdef EX_PROTOCOL
-  {
-  0xff & EX_PROTOCOL, "Remote protocol error."},
-#endif
-#ifdef EX_NOPERM
-  {
-  0xff & EX_NOPERM, "Insufficient permission."},
-#endif
-#ifdef EX_CONFIG
-  {
-  0xff & EX_NOPERM, "Local configuration error."},
-#endif
-  {
-  S_ERR, "Exec error."}, {
-  -1, NULL}
-};
-
-
-
 #define DISPOSITION(X) X==DISPATTACH?"attachment":"inline"
 
 const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t";
@@ -187,11 +119,11 @@ static void encode_quoted (FGETCONV * fc, FILE * fout, int istext)
     }
 
     /* Escape lines that begin with/only contain "the message separator". */
-    if (linelen == 4 && !mutt_strncmp ("From", line, 4)) {
+    if (linelen == 4 && !str_ncmp ("From", line, 4)) {
       strfcpy (line, "=46rom", sizeof (line));
       linelen = 6;
     }
-    else if (linelen == 4 && !mutt_strncmp ("from", line, 4)) {
+    else if (linelen == 4 && !str_ncmp ("from", line, 4)) {
       strfcpy (line, "=66rom", sizeof (line));
       linelen = 6;
     }
@@ -362,7 +294,7 @@ int mutt_write_mime_header (BODY * a, FILE * f)
   fprintf (f, "Content-Type: %s/%s", TYPE (a), a->subtype);
 
   if (a->parameter) {
-    len = 25 + mutt_strlen (a->subtype);        /* approximate len. of content-type */
+    len = 25 + str_len (a->subtype);        /* approximate len. of content-type */
 
     for (p = a->parameter; p; p = p->next) {
       char *tmp;
@@ -373,7 +305,7 @@ int mutt_write_mime_header (BODY * a, FILE * f)
       fputc (';', f);
 
       buffer[0] = 0;
-      tmp = safe_strdup (p->value);
+      tmp = str_dup (p->value);
       encode = rfc2231_encode_string (&tmp);
       rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
 
@@ -386,9 +318,9 @@ int mutt_write_mime_header (BODY * a, FILE * f)
           && !strcmp (buffer, tmp))
         snprintf (buffer, sizeof (buffer), "\"%s\"", tmp);
 
-      FREE (&tmp);
+      mem_free (&tmp);
 
-      tmplen = mutt_strlen (buffer) + mutt_strlen (p->attribute) + 1;
+      tmplen = str_len (buffer) + str_len (p->attribute) + 1;
 
       if (len + tmplen + 2 > 76) {
         fputs ("\n\t", f);
@@ -425,10 +357,10 @@ int mutt_write_mime_header (BODY * a, FILE * f)
         t = fn;
 
       buffer[0] = 0;
-      tmp = safe_strdup (t);
+      tmp = str_dup (t);
       encode = rfc2231_encode_string (&tmp);
       rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
-      FREE (&tmp);
+      mem_free (&tmp);
       fprintf (f, "; filename%s=%s", encode ? "*" : "", buffer);
     }
   }
@@ -457,9 +389,7 @@ int mutt_write_mime_body (BODY * a, FILE * f)
   if (a->type == TYPEMULTIPART) {
     /* First, find the boundary to use */
     if (!(p = mutt_get_parameter ("boundary", a->parameter))) {
-      dprint (1,
-              (debugfile,
-               "mutt_write_mime_body(): no boundary parameter found!\n"));
+      debug_print (1, ("no boundary parameter found!\n"));
       mutt_error _("No boundary parameter found! [report this error]");
 
       return (-1);
@@ -481,15 +411,13 @@ int mutt_write_mime_body (BODY * a, FILE * f)
   /* This is pretty gross, but it's the best solution for now... */
   if ((WithCrypto & APPLICATION_PGP)
       && a->type == TYPEAPPLICATION
-      && mutt_strcmp (a->subtype, "pgp-encrypted") == 0) {
+      && str_cmp (a->subtype, "pgp-encrypted") == 0) {
     fputs ("Version: 1\n", f);
     return 0;
   }
 
   if ((fpin = fopen (a->filename, "r")) == NULL) {
-    dprint (1,
-            (debugfile, "write_mime_body: %s no longer exists!\n",
-             a->filename));
+    debug_print (1, ("%s no longer exists!\n", a->filename));
     mutt_error (_("%s no longer exists!"), a->filename);
     return -1;
   }
@@ -676,7 +604,7 @@ static size_t convert_file_to (FILE * file, const char *fromcode,
 #ifdef HAVE_ICONV
   iconv_t cd1, *cd;
   char bufi[256], bufu[512], bufo[4 * sizeof (bufi)];
-  ICONV_CONST char *ib, *ub;
+  const char *ib, *ub;
   char *ob;
   size_t ibl, obl, ubl, ubl1, n, ret;
   int i;
@@ -688,10 +616,10 @@ static size_t convert_file_to (FILE * file, const char *fromcode,
   if (cd1 == (iconv_t) (-1))
     return -1;
 
-  cd = safe_calloc (ncodes, sizeof (iconv_t));
-  score = safe_calloc (ncodes, sizeof (size_t));
-  states = safe_calloc (ncodes, sizeof (CONTENT_STATE));
-  infos = safe_calloc (ncodes, sizeof (CONTENT));
+  cd = mem_calloc (ncodes, sizeof (iconv_t));
+  score = mem_calloc (ncodes, sizeof (size_t));
+  states = mem_calloc (ncodes, sizeof (CONTENT_STATE));
+  infos = mem_calloc (ncodes, sizeof (CONTENT));
 
   for (i = 0; i < ncodes; i++)
     if (ascii_strcasecmp (tocodes[i], "UTF-8"))
@@ -711,7 +639,7 @@ static size_t convert_file_to (FILE * file, const char *fromcode,
     /* Convert to UTF-8 */
     ib = bufi;
     ob = bufu, obl = sizeof (bufu);
-    n = iconv (cd1, ibl ? &ib : 0, &ibl, &ob, &obl);
+    n = my_iconv(cd1, ibl ? &ib : 0, &ibl, &ob, &obl);
     assert (n == (size_t) (-1) || !n || ICONV_NONTRANS);
     if (n == (size_t) (-1) &&
         ((errno != EINVAL && errno != E2BIG) || ib == bufi)) {
@@ -727,7 +655,7 @@ static size_t convert_file_to (FILE * file, const char *fromcode,
       if (cd[i] != (iconv_t) (-1) && score[i] != (size_t) (-1)) {
         ub = bufu, ubl = ubl1;
         ob = bufo, obl = sizeof (bufo);
-        n = iconv (cd[i], (ibl || ubl) ? &ub : 0, &ubl, &ob, &obl);
+        n = my_iconv(cd[i], (ibl || ubl) ? &ub : 0, &ubl, &ob, &obl);
         if (n == (size_t) (-1)) {
           assert (errno == E2BIG ||
                   (BUGGY_ICONV && (errno == EILSEQ || errno == ENOENT)));
@@ -781,10 +709,10 @@ static size_t convert_file_to (FILE * file, const char *fromcode,
       iconv_close (cd[i]);
 
   iconv_close (cd1);
-  FREE (&cd);
-  FREE (&infos);
-  FREE (&score);
-  FREE (&states);
+  mem_free (&cd);
+  mem_free (&infos);
+  mem_free (&score);
+  mem_free (&states);
 
   return ret;
 #else
@@ -823,11 +751,11 @@ static size_t convert_file_from_to (FILE * file,
   }
 
   /* Copy them */
-  tcode = safe_malloc (ncodes * sizeof (char *));
+  tcode = mem_malloc (ncodes * sizeof (char *));
   for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++) {
     if ((c1 = strchr (c, ':')) == c)
       continue;
-    tcode[i] = mutt_substrdup (c, c1);
+    tcode[i] = str_substrdup (c, c1);
   }
 
   ret = (size_t) (-1);
@@ -836,7 +764,7 @@ static size_t convert_file_from_to (FILE * file,
     for (c = fromcodes; c; c = c1 ? c1 + 1 : 0) {
       if ((c1 = strchr (c, ':')) == c)
         continue;
-      fcode = mutt_substrdup (c, c1);
+      fcode = str_substrdup (c, c1);
 
       ret = convert_file_to (file, fcode, ncodes, (const char **) tcode,
                              &cn, info);
@@ -846,7 +774,7 @@ static size_t convert_file_from_to (FILE * file,
         tcode[cn] = 0;
         break;
       }
-      FREE (&fcode);
+      mem_free (&fcode);
     }
   }
   else {
@@ -861,9 +789,9 @@ static size_t convert_file_from_to (FILE * file,
 
   /* Free memory */
   for (i = 0; i < ncodes; i++)
-    FREE (&tcode[i]);
+    mem_free (&tcode[i]);
 
-  FREE (tcode);
+  mem_free (tcode);
 
   return ret;
 }
@@ -877,7 +805,7 @@ CONTENT *mutt_get_content_info (const char *fname, BODY * b)
   CONTENT *info;
   CONTENT_STATE state;
   FILE *fp = NULL;
-  char *fromcode;
+  char *fromcode = NULL;
   char *tocode;
   char buffer[100];
   char chsbuf[STRING];
@@ -899,12 +827,11 @@ CONTENT *mutt_get_content_info (const char *fname, BODY * b)
   }
 
   if ((fp = fopen (fname, "r")) == NULL) {
-    dprint (1, (debugfile, "mutt_get_content_info: %s: %s (errno %d).\n",
-                fname, strerror (errno), errno));
+    debug_print (1, ("%s: %s (errno %d).\n", fname, strerror (errno), errno));
     return (NULL);
   }
 
-  info = safe_calloc (1, sizeof (CONTENT));
+  info = mem_calloc (1, sizeof (CONTENT));
   memset (&state, 0, sizeof (state));
 
   if (b != NULL && b->type == TYPETEXT && (!b->noconv && !b->force_charset)) {
@@ -919,7 +846,7 @@ CONTENT *mutt_get_content_info (const char *fname, BODY * b)
         mutt_set_parameter ("charset", chsbuf, &b->parameter);
       }
       b->file_charset = fromcode;
-      FREE (&tocode);
+      mem_free (&tocode);
       safe_fclose (&fp);
       return info;
     }
@@ -963,9 +890,9 @@ int mutt_lookup_mime_type (BODY * att, const char *path)
   type = TYPEOTHER;
   cur_sze = 0;
 
-  szf = mutt_strlen (path);
+  szf = str_len (path);
 
-  for (count = 0; count < 3; count++) {
+  for (count = 0; count < 4; count++) {
     /*
      * can't use strtok() because we use it in an inner loop below, so use
      * a switch statement here instead.
@@ -975,16 +902,16 @@ int mutt_lookup_mime_type (BODY * att, const char *path)
       snprintf (buf, sizeof (buf), "%s/.mime.types", NONULL (Homedir));
       break;
     case 1:
-      strfcpy (buf, SYSCONFDIR "/mime.types", sizeof (buf));
+      strfcpy (buf, SYSCONFDIR "/muttng-mime.types", sizeof (buf));
       break;
     case 2:
       strfcpy (buf, PKGDATADIR "/mime.types", sizeof (buf));
       break;
+    case 3:
+      strfcpy (buf, SYSCONFDIR "/mime.types", sizeof (buf));
+      break;
     default:
-      dprint (1,
-              (debugfile,
-               "mutt_lookup_mime_type: Internal error, count = %d.\n",
-               count));
+      debug_print (1, ("Internal error, count = %d.\n", count));
       goto bye;                 /* shouldn't happen */
     }
 
@@ -1006,9 +933,9 @@ int mutt_lookup_mime_type (BODY * att, const char *path)
 
         /* cycle through the file extensions */
         while ((p = strtok (p, " \t\n"))) {
-          sze = mutt_strlen (p);
+          sze = str_len (p);
           if ((sze > cur_sze) && (szf >= sze) &&
-              (mutt_strcasecmp (path + szf - sze, p) == 0
+              (str_casecmp (path + szf - sze, p) == 0
                || ascii_strcasecmp (path + szf - sze, p) == 0) && (szf == sze
                                                                    || path[szf
                                                                            -
@@ -1026,7 +953,7 @@ int mutt_lookup_mime_type (BODY * att, const char *path)
 
             for (q = p; *q && !ISSPACE (*q); q++);
 
-            mutt_substrcpy (subtype, p, q, sizeof (subtype));
+            str_substrcpy (subtype, p, q, sizeof (subtype));
 
             if ((type = mutt_check_mime_type (ct)) == TYPEOTHER)
               strfcpy (xtype, ct, sizeof (xtype));
@@ -1044,8 +971,8 @@ bye:
 
   if (type != TYPEOTHER || *xtype != '\0') {
     att->type = type;
-    mutt_str_replace (&att->subtype, subtype);
-    mutt_str_replace (&att->xtype, xtype);
+    str_replace (&att->subtype, subtype);
+    str_replace (&att->xtype, xtype);
   }
 
   return (type);
@@ -1080,7 +1007,7 @@ void mutt_message_to_7bit (BODY * a, FILE * fp)
     goto cleanup;
   }
 
-  fseek (fpin, a->offset, 0);
+  fseeko (fpin, a->offset, 0);
   a->parts = mutt_parse_messageRFC822 (fpin, a);
 
   transform_to_7bit (a->parts, fpin);
@@ -1088,13 +1015,13 @@ void mutt_message_to_7bit (BODY * a, FILE * fp)
   mutt_copy_hdr (fpin, fpout, a->offset, a->offset + a->length,
                  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
 
-  fputs ("Mime-Version: 1.0\n", fpout);
+  fputs ("MIME-Version: 1.0\n", fpout);
   mutt_write_mime_header (a->parts, fpout);
   fputc ('\n', fpout);
   mutt_write_mime_body (a->parts, fpout);
 
 cleanup:
-  FREE (&line);
+  mem_free (&line);
 
   if (fpin && !fp)
     fclose (fpin);
@@ -1107,7 +1034,7 @@ cleanup:
   a->d_filename = a->filename;
   if (a->filename && a->unlink)
     unlink (a->filename);
-  a->filename = safe_strdup (temp);
+  a->filename = str_dup (temp);
   a->unlink = 1;
   if (stat (a->filename, &sb) == -1) {
     mutt_perror ("stat");
@@ -1148,7 +1075,7 @@ static void transform_to_7bit (BODY * a, FILE * fpin)
       mutt_decode_attachment (a, &s);
       fclose (s.fpout);
       a->d_filename = a->filename;
-      a->filename = safe_strdup (buff);
+      a->filename = str_dup (buff);
       a->unlink = 1;
       if (stat (a->filename, &sb) == -1) {
         mutt_perror ("stat");
@@ -1258,7 +1185,7 @@ void mutt_update_encoding (BODY * a)
   mutt_set_encoding (a, info);
   mutt_stamp_attachment (a);
 
-  FREE (&a->content);
+  mem_free (&a->content);
   a->content = info;
 
 }
@@ -1285,8 +1212,8 @@ BODY *mutt_make_message_attach (CONTEXT * ctx, HEADER * hdr, int attach_msg)
 
   body = mutt_new_body ();
   body->type = TYPEMESSAGE;
-  body->subtype = safe_strdup ("rfc822");
-  body->filename = safe_strdup (buffer);
+  body->subtype = str_dup ("rfc822");
+  body->filename = str_dup (buffer);
   body->unlink = 1;
   body->use_disp = 0;
   body->disposition = DISPINLINE;
@@ -1352,7 +1279,7 @@ BODY *mutt_make_file_attach (const char *path)
   CONTENT *info;
 
   att = mutt_new_body ();
-  att->filename = safe_strdup (path);
+  att->filename = str_dup (path);
 
   /* Attempt to determine the appropriate content-type based on the filename
    * suffix.
@@ -1364,8 +1291,8 @@ BODY *mutt_make_file_attach (const char *path)
        mutt_lookup_mime_type (buf, sizeof (buf), xbuf, sizeof (xbuf),
                               path)) != TYPEOTHER || *xbuf != '\0') {
     att->type = n;
-    att->subtype = safe_strdup (buf);
-    att->xtype = safe_strdup (xbuf);
+    att->subtype = str_dup (buf);
+    att->xtype = str_dup (xbuf);
   }
 
 #else
@@ -1387,11 +1314,11 @@ BODY *mutt_make_file_attach (const char *path)
        * chars if this is really a binary file...
        */
       att->type = TYPETEXT;
-      att->subtype = safe_strdup ("plain");
+      att->subtype = str_dup ("plain");
     }
     else {
       att->type = TYPEAPPLICATION;
-      att->subtype = safe_strdup ("octet-stream");
+      att->subtype = str_dup ("octet-stream");
     }
   }
 
@@ -1419,7 +1346,7 @@ BODY *mutt_make_multipart (BODY * b)
 
   new = mutt_new_body ();
   new->type = TYPEMULTIPART;
-  new->subtype = safe_strdup ("mixed");
+  new->subtype = str_dup ("mixed");
   new->encoding = get_toplevel_encoding (b);
   mutt_generate_boundary (&new->parameter);
   new->use_disp = 0;
@@ -1473,7 +1400,7 @@ void mutt_write_address_list (ADDRESS * adr, FILE * fp, int linelen,
     adr->next = NULL;
     buf[0] = 0;
     rfc822_write_address (buf, sizeof (buf), adr, display);
-    len = mutt_strlen (buf);
+    len = str_len (buf);
     if (count && linelen + len > 74) {
       fputs ("\n\t", fp);
       linelen = len + 8;        /* tab is usually about 8 spaces... */
@@ -1512,7 +1439,7 @@ void mutt_write_references (LIST * r, FILE * f)
 
   for (; (TrimRef == 0 || refcnt < TrimRef) && r; r = r->next) {
     if (refcnt == refmax)
-      safe_realloc (&ref, (refmax += REF_INC) * sizeof (LIST *));
+      mem_realloc (&ref, (refmax += REF_INC) * sizeof (LIST *));
     ref[refcnt++] = r;
   }
 
@@ -1521,7 +1448,7 @@ void mutt_write_references (LIST * r, FILE * f)
     fputs (ref[refcnt]->data, f);
   }
 
-  FREE (&ref);
+  mem_free (&ref);
 }
 
 /* Note: all RFC2047 encoding should be done outside of this routine, except
@@ -1547,6 +1474,7 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
   char *p;
   LIST *tmp = env->userhdrs;
   int has_agent = 0;            /* user defined user-agent header field exists */
+  list2_t* hdrs = list_from_str (EditorHeaders, " ");
 
 #ifdef USE_NNTP
   if (!option (OPTNEWSSEND))
@@ -1554,6 +1482,8 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
     if (mode == 0 && !privacy)
       fputs (mutt_make_date (buffer, sizeof (buffer)), fp);
 
+#define EDIT_HEADER(x) (mode != 1 || option(OPTXMAILTO) || (mode == 1 && list_lookup(hdrs,(list_lookup_t*) ascii_strcasecmp,x) >= 0))
+
   /* OPTUSEFROM is not consulted here so that we can still write a From:
    * field if the user sets it with the `my_hdr' command
    */
@@ -1571,7 +1501,8 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
 #ifdef USE_NNTP
     if (!option (OPTNEWSSEND))
 #endif
-      fputs ("To: \n", fp);
+      if (EDIT_HEADER("To:"))
+        fputs ("To:\n", fp);
 
   if (env->cc) {
     fputs ("Cc: ", fp);
@@ -1581,7 +1512,8 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
 #ifdef USE_NNTP
     if (!option (OPTNEWSSEND))
 #endif
-      fputs ("Cc: \n", fp);
+      if (EDIT_HEADER("Cc:"))
+        fputs ("Cc:\n", fp);
 
   if (env->bcc) {
     if (mode != 0 || option (OPTWRITEBCC)) {
@@ -1593,29 +1525,31 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
 #ifdef USE_NNTP
     if (!option (OPTNEWSSEND))
 #endif
-      fputs ("Bcc: \n", fp);
+      if (EDIT_HEADER("Bcc:"))
+        fputs ("Bcc:\n", fp);
 
 #ifdef USE_NNTP
   if (env->newsgroups)
     fprintf (fp, "Newsgroups: %s\n", env->newsgroups);
-  else if (mode == 1 && option (OPTNEWSSEND))
-    fputs ("Newsgroups: \n", fp);
+  else if (mode == 1 && option (OPTNEWSSEND) && EDIT_HEADER("Newsgroups:"))
+    fputs ("Newsgroups:\n", fp);
 
   if (env->followup_to)
     fprintf (fp, "Followup-To: %s\n", env->followup_to);
-  else if (mode == 1 && option (OPTNEWSSEND))
-    fputs ("Followup-To: \n", fp);
+  else if (mode == 1 && option (OPTNEWSSEND) && EDIT_HEADER("Followup-To:"))
+    fputs ("Followup-To:\n", fp);
 
   if (env->x_comment_to)
     fprintf (fp, "X-Comment-To: %s\n", env->x_comment_to);
-  else if (mode == 1 && option (OPTNEWSSEND) && option (OPTXCOMMENTTO))
-    fputs ("X-Comment-To: \n", fp);
+  else if (mode == 1 && option (OPTNEWSSEND) && option (OPTXCOMMENTTO) &&
+           EDIT_HEADER("X-Comment-To:"))
+    fputs ("X-Comment-To:\n", fp);
 #endif
 
   if (env->subject)
     fprintf (fp, "Subject: %s\n", env->subject);
-  else if (mode == 1)
-    fputs ("Subject: \n", fp);
+  else if (mode == 1 && EDIT_HEADER("Subject:"))
+    fputs ("Subject:\n", fp);
 
   /* save message id if the user has set it */
   if (env->message_id && !privacy)
@@ -1625,8 +1559,8 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
     fputs ("Reply-To: ", fp);
     mutt_write_address_list (env->reply_to, fp, 10, 0);
   }
-  else if (mode > 0)
-    fputs ("Reply-To: \n", fp);
+  else if (mode > 0 && EDIT_HEADER("Reply-To:"))
+    fputs ("Reply-To:\n", fp);
 
   if (env->mail_followup_to)
 #ifdef USE_NNTP
@@ -1645,7 +1579,7 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
     }
 
     /* Add the MIME headers */
-    fputs ("Mime-Version: 1.0\n", fp);
+    fputs ("MIME-Version: 1.0\n", fp);
     mutt_write_mime_header (attach, fp);
   }
 
@@ -1655,6 +1589,8 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
     fputc ('\n', fp);
   }
 
+#undef EDIT_HEADER
+
   /* Add any user defined headers */
   for (; tmp; tmp = tmp->next) {
     if ((p = strchr (tmp->data, ':'))) {
@@ -1676,24 +1612,20 @@ int mutt_write_rfc822_header (FILE * fp, ENVELOPE * env, BODY * attach,
   }
 
   if (mode == 0 && !privacy && option (OPTXMAILER) && !has_agent) {
-    struct utsname un;
-    char *os;
+    const char *os;
 
     if (OperatingSystem != NULL) {
       os = OperatingSystem;
-    }
-    else {
-      if (uname (&un) == -1) {
-        os = "UNIX";
-      }
-      else {
-        os = un.sysname;
-      }
+    } else {
+      struct utsname un;
+      os = (uname(&un) == -1) ? "UNIX" : un.sysname;
     }
     /* Add a vanity header */
-    fprintf (fp, "User-Agent: mutt-ng %s (%s)\n", MUTT_VERSION, os);
+    fprintf (fp, "User-Agent: %s (%s)\n", mutt_make_version (0), os);
   }
 
+  list_del (&hdrs, (list_del_t*) _mem_free);
+
   return (ferror (fp) == 0 ? 0 : -1);
 }
 
@@ -1710,18 +1642,18 @@ static void encode_headers (LIST * h)
     i = p - h->data;
     ++p;
     SKIPWS (p);
-    tmp = safe_strdup (p);
+    tmp = str_dup (p);
 
     if (!tmp)
       continue;
 
     rfc2047_encode_string (&tmp);
-    safe_realloc (&h->data,
-                  mutt_strlen (h->data) + 2 + mutt_strlen (tmp) + 1);
+    mem_realloc (&h->data,
+                  str_len (h->data) + 2 + str_len (tmp) + 1);
 
     sprintf (h->data + i, ": %s", NONULL (tmp));        /* __SPRINTF_CHECKED__ */
 
-    FREE (&tmp);
+    mem_free (&tmp);
   }
 }
 
@@ -1775,62 +1707,62 @@ static void mutt_gen_localpart (char *buf, unsigned int len, char *fmt)
         return;
       case 'd':
         snprintf (tmp, sizeof (tmp), "%02d", tm->tm_mday);
-        safe_strncat (buf, len, tmp, 2);
+        str_ncat (buf, len, tmp, 2);
         break;
       case 'h':
         snprintf (tmp, sizeof (tmp), "%02d", tm->tm_hour);
-        safe_strncat (buf, len, tmp, 2);
+        str_ncat (buf, len, tmp, 2);
         break;
       case 'm':
         snprintf (tmp, sizeof (tmp), "%02d", tm->tm_mon + 1);
-        safe_strncat (buf, len, tmp, 2);
+        str_ncat (buf, len, tmp, 2);
         break;
       case 'M':
         snprintf (tmp, sizeof (tmp), "%02d", tm->tm_min);
-        safe_strncat (buf, len, tmp, 2);
+        str_ncat (buf, len, tmp, 2);
         break;
       case 'O':
         snprintf (tmp, sizeof (tmp), "%lo", (unsigned long) now);
-        safe_strncat (buf, len, tmp, mutt_strlen (tmp));
+        str_ncat (buf, len, tmp, str_len (tmp));
         break;
       case 'p':
         snprintf (tmp, sizeof (tmp), "%u", (unsigned int) getpid ());
-        safe_strncat (buf, len, tmp, mutt_strlen (tmp));
+        str_ncat (buf, len, tmp, str_len (tmp));
         break;
       case 'P':
         snprintf (tmp, sizeof (tmp), "%c", MsgIdPfx);
         MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
-        safe_strncat (buf, len, tmp, 1);
+        str_ncat (buf, len, tmp, 1);
         break;
       case 'r':
         snprintf (tmp, sizeof (tmp), "%u", (unsigned int) rand ());
-        safe_strncat (buf, len, tmp, mutt_strlen (tmp));
+        str_ncat (buf, len, tmp, str_len (tmp));
         break;
       case 'R':
         snprintf (tmp, sizeof (tmp), "%x", (unsigned int) rand ());
-        safe_strncat (buf, len, tmp, mutt_strlen (tmp));
+        str_ncat (buf, len, tmp, str_len (tmp));
         break;
       case 's':
         snprintf (tmp, sizeof (tmp), "%02d", tm->tm_sec);
-        safe_strncat (buf, len, tmp, 2);
+        str_ncat (buf, len, tmp, 2);
         break;
       case 'T':
         snprintf (tmp, sizeof (tmp), "%u", (unsigned int) now);
-        safe_strncat (buf, len, tmp, mutt_strlen (tmp));
+        str_ncat (buf, len, tmp, str_len (tmp));
         break;
       case 'X':
         snprintf (tmp, sizeof (tmp), "%x", (unsigned int) now);
-        safe_strncat (buf, len, tmp, mutt_strlen (tmp));
+        str_ncat (buf, len, tmp, str_len (tmp));
         break;
       case 'Y':
         snprintf (tmp, sizeof (tmp), "%04d", tm->tm_year + 1900);       /* this will break in the year 10000 ;-) */
-        safe_strncat (buf, len, tmp, 4);
+        str_ncat (buf, len, tmp, 4);
         break;
       case '%':
-        safe_strncat (buf, len, "%", 1);
+        str_ncat (buf, len, "%", 1);
         break;
       default:
-        safe_strncat (buf, len, ".", 1);        /* invalid formats are replaced by '.' */
+        str_ncat (buf, len, ".", 1);        /* invalid formats are replaced by '.' */
       }                         /* switch */
       ++fmt;
     }
@@ -1838,7 +1770,7 @@ static void mutt_gen_localpart (char *buf, unsigned int len, char *fmt)
       char c;
 
       c = mutt_normalized_char (*fmt);  /* @todo: filter out invalid characters */
-      safe_strncat (buf, len, &c, 1);
+      str_ncat (buf, len, &c, 1);
     }
   }
 }
@@ -1848,21 +1780,17 @@ char *mutt_gen_msgid (void)
   char buf[SHORT_STRING];
   char localpart[SHORT_STRING];
   unsigned int localpart_length;
-  time_t now;
-  struct tm *tm;
   const char *fqdn;
 
-  now = time (NULL);
-  tm = gmtime (&now);
   if (!(fqdn = mutt_fqdn (0)))
     fqdn = NONULL (Hostname);
 
-  localpart_length = sizeof (buf) - mutt_strlen (fqdn) - 4;  /* the 4 characters are '<', '@', '>' and '\0' */
+  localpart_length = sizeof (buf) - str_len (fqdn) - 4;  /* the 4 characters are '<', '@', '>' and '\0' */
 
   mutt_gen_localpart (localpart, localpart_length, MsgIdFormat);
 
   snprintf (buf, sizeof (buf), "<%s@%s>", localpart, fqdn);
-  return (safe_strdup (buf));
+  return (str_dup (buf));
 }
 
 static RETSIGTYPE alarm_handler (int sig)
@@ -1895,7 +1823,7 @@ send_msg (const char *path, char **args, const char *msg, char **tempfile)
     char tmp[_POSIX_PATH_MAX];
 
     mutt_mktemp (tmp);
-    *tempfile = safe_strdup (tmp);
+    *tempfile = str_dup (tmp);
   }
 
   if ((pid = fork ()) == 0) {
@@ -1952,7 +1880,7 @@ send_msg (const char *path, char **args, const char *msg, char **tempfile)
     }
     else if (pid == -1) {
       unlink (msg);
-      FREE (tempfile);
+      mem_free (tempfile);
       _exit (S_ERR);
     }
 
@@ -1980,14 +1908,14 @@ send_msg (const char *path, char **args, const char *msg, char **tempfile)
       st = WIFEXITED (st) ? WEXITSTATUS (st) : S_ERR;
       if (SendmailWait && st == (0xff & EX_OK)) {
         unlink (*tempfile);     /* no longer needed */
-        FREE (tempfile);
+        mem_free (tempfile);
       }
     }
     else {
       st = (SendmailWait > 0 && errno == EINTR && SigAlrm) ? S_BKG : S_ERR;
       if (SendmailWait > 0) {
         unlink (*tempfile);
-        FREE (tempfile);
+        mem_free (tempfile);
       }
     }
 
@@ -1998,7 +1926,7 @@ send_msg (const char *path, char **args, const char *msg, char **tempfile)
     if (kill (ppid, 0) == -1 && errno == ESRCH) {
       /* the parent is already dead */
       unlink (*tempfile);
-      FREE (tempfile);
+      mem_free (tempfile);
     }
 
     _exit (st);
@@ -2023,35 +1951,23 @@ static char **add_args (char **args, size_t * argslen, size_t * argsmax,
     /* weed out group mailboxes, since those are for display only */
     if (addr->mailbox && !addr->group) {
       if (*argslen == *argsmax)
-        safe_realloc (&args, (*argsmax += 5) * sizeof (char *));
+        mem_realloc (&args, (*argsmax += 5) * sizeof (char *));
       args[(*argslen)++] = addr->mailbox;
     }
   }
   return (args);
 }
 
-static char **add_option (char **args, size_t * argslen, size_t * argsmax,
-                          char *s)
-{
-  if (*argslen == *argsmax)
-    safe_realloc (&args, (*argsmax += 5) * sizeof (char *));
-  args[(*argslen)++] = s;
-  return (args);
-}
-
-static const char *strsysexit (int e)
+static char **add_option(const char **args, size_t * argslen, size_t * argsmax,
+                         const char *s)
 {
-  int i;
-
-  for (i = 0; sysexits_h[i].str; i++) {
-    if (e == sysexits_h[i].v)
-      break;
-  }
-
-  return sysexits_h[i].str;
+    if (*argslen == *argsmax) {
+        mem_realloc(&args, (*argsmax += 5) * sizeof (char *));
+    }
+    args[(*argslen)++] = s;
+    return (args);
 }
 
-
 static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
                                  ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,     /* recips */
                                  const char *msg,       /* file containing message */
@@ -2074,22 +1990,22 @@ static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
       return i;
     }
 
-    s = safe_strdup (cmd);
+    s = str_dup (cmd);
   }
   else
 #endif
-    s = safe_strdup (Sendmail);
+    s = str_dup (Sendmail);
 
   ps = s;
   i = 0;
   while ((ps = strtok (ps, " "))) {
     if (argslen == argsmax)
-      safe_realloc (&args, sizeof (char *) * (argsmax += 5));
+      mem_realloc (&args, sizeof (char *) * (argsmax += 5));
 
     if (i)
       args[argslen++] = ps;
     else {
-      path = safe_strdup (ps);
+      path = str_dup (ps);
       ps = strrchr (ps, '/');
       if (ps)
         ps++;
@@ -2107,9 +2023,16 @@ static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
     if (eightbit && option (OPTUSE8BITMIME))
       args = add_option (args, &argslen, &argsmax, "-B8BITMIME");
 
-    if (option (OPTENVFROM) && from && !from->next) {
-      args = add_option (args, &argslen, &argsmax, "-f");
-      args = add_args (args, &argslen, &argsmax, from);
+    if (option (OPTENVFROM)) {
+      ADDRESS *f = NULL;
+      if (EnvFrom)
+        f = EnvFrom;
+      else if (from && !from->next)
+        f = from;
+      if (f) {
+        args = add_option (args, &argslen, &argsmax, "-f");
+        args = add_args (args, &argslen, &argsmax, f);
+      }
     }
     if (DsnNotify) {
       args = add_option (args, &argslen, &argsmax, "-N");
@@ -2128,15 +2051,15 @@ static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
 #endif
 
   if (argslen == argsmax)
-    safe_realloc (&args, sizeof (char *) * (++argsmax));
+    mem_realloc (&args, sizeof (char *) * (++argsmax));
 
   args[argslen++] = NULL;
 
   if ((i = send_msg (path, args, msg, &childout)) != (EX_OK & 0xff)) {
     if (i != S_BKG) {
-      const char *e = strsysexit (i);
+      const char *e = mutt_strsysexit (i);
 
-      e = strsysexit (i);
+      e = mutt_strsysexit (i);
       mutt_error (_("Error sending message, child exited %d (%s)."), i,
                   NONULL (e));
       if (childout) {
@@ -2151,10 +2074,10 @@ static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
   else
     unlink (childout);
 
-  FREE (&childout);
-  FREE (&path);
-  FREE (&s);
-  FREE (&args);
+  mem_free (&childout);
+  mem_free (&path);
+  mem_free (&s);
+  mem_free (&args);
 
   if (i == (EX_OK & 0xff))
     i = 0;
@@ -2171,8 +2094,11 @@ int mutt_invoke_mta (ADDRESS * from,    /* the sender */
                      int eightbit)
 {                               /* message contains 8bit chars */
 #ifdef USE_LIBESMTP
-  if (SmtpHost)
-    return mutt_invoke_libesmtp (from, to, cc, bcc, msg, eightbit);
+#ifdef USE_NNTP
+  if (!option (OPTNEWSSEND))
+#endif
+    if (SmtpHost)
+      return mutt_libesmtp_invoke (from, to, cc, bcc, msg, eightbit);
 #endif
 
   return mutt_invoke_sendmail (from, to, cc, bcc, msg, eightbit);
@@ -2182,9 +2108,9 @@ int mutt_invoke_mta (ADDRESS * from,    /* the sender */
    string. */
 char *mutt_append_string (char *a, const char *b)
 {
-  size_t la = mutt_strlen (a);
+  size_t la = str_len (a);
 
-  safe_realloc (&a, la + mutt_strlen (b) + 1);
+  mem_realloc (&a, la + str_len (b) + 1);
   strcpy (a + la, b);           /* __STRCPY_CHECKED__ */
   return (a);
 }
@@ -2212,14 +2138,14 @@ char *mutt_quote_string (const char *s)
   char *r, *pr;
   size_t rlen;
 
-  rlen = mutt_strlen (s) + 3;
-  pr = r = (char *) safe_malloc (rlen);
+  rlen = str_len (s) + 3;
+  pr = r = (char *) mem_malloc (rlen);
   *pr++ = '"';
   while (*s) {
     if (INVALID_CHAR (*s)) {
       size_t o = pr - r;
 
-      safe_realloc (&r, ++rlen);
+      mem_realloc (&r, ++rlen);
       pr = r + o;
       *pr++ = '\\';
     }
@@ -2249,12 +2175,12 @@ void mutt_prepare_envelope (ENVELOPE * env, int final)
       rfc822_cat (buffer, sizeof (buffer), "undisclosed-recipients",
                   RFC822Specials);
 
-      env->to->mailbox = safe_strdup (buffer);
+      env->to->mailbox = str_dup (buffer);
     }
 
     mutt_set_followup_to (env);
 
-    if (!env->message_id)
+    if (!env->message_id && MsgIdFormat && *MsgIdFormat)
       env->message_id = mutt_gen_msgid ();
   }
 
@@ -2326,10 +2252,11 @@ static int _mutt_bounce_message (FILE * fp, HEADER * h, ADDRESS * to,
     if (!option (OPTBOUNCEDELIVERED))
       ch_flags |= CH_WEED_DELIVERED;
 
-    fseek (fp, h->offset, 0);
+    fseeko (fp, h->offset, 0);
     fprintf (f, "Resent-From: %s", resent_from);
     fprintf (f, "\nResent-%s", mutt_make_date (date, sizeof (date)));
-    fprintf (f, "Resent-Message-ID: %s\n", mutt_gen_msgid ());
+    if (MsgIdFormat && *MsgIdFormat)
+      fprintf (f, "Resent-Message-ID: %s\n", mutt_gen_msgid ());
     fputs ("Resent-To: ", f);
     mutt_write_address_list (to, f, 11, 0);
     mutt_copy_header (fp, h, f, ch_flags, NULL);
@@ -2398,8 +2325,7 @@ ADDRESS *mutt_remove_duplicates (ADDRESS * addr)
     }
 
     if (dup) {
-      dprint (2, (debugfile, "mutt_remove_duplicates: Removing %s\n",
-                  addr->mailbox));
+      debug_print (2, ("Removing %s\n", addr->mailbox));
 
       *last = addr->next;
 
@@ -2444,10 +2370,7 @@ int mutt_write_fcc (const char *path, HEADER * hdr, const char *msgid,
     set_noconv_flags (hdr->content, 1);
 
   if (mx_open_mailbox (path, M_APPEND | M_QUIET, &f) == NULL) {
-    dprint (1,
-            (debugfile,
-             "mutt_write_fcc(): unable to open mailbox %s in append-mode, aborting.\n",
-             path));
+    debug_print (1, ("unable to open mailbox %s in append-mode, aborting.\n", path));
     return (-1);
   }
 
@@ -2554,16 +2477,15 @@ int mutt_write_fcc (const char *path, HEADER * hdr, const char *msgid,
      * this will happen, and it can cause problems parsing the mailbox   
      * later.
      */
-    fseek (tempfp, -1, 2);
+    fseeko (tempfp, -1, 2);
     if (fgetc (tempfp) != '\n') {
-      fseek (tempfp, 0, 2);
+      fseeko (tempfp, 0, 2);
       fputc ('\n', tempfp);
     }
 
     fflush (tempfp);
     if (ferror (tempfp)) {
-      dprint (1,
-              (debugfile, "mutt_write_fcc(): %s: write failed.\n", tempfile));
+      debug_print (1, ("%s: write failed.\n", tempfile));
       fclose (tempfp);
       unlink (tempfile);
       mx_commit_message (msg, &f);      /* XXX - really? */
@@ -2576,7 +2498,7 @@ int mutt_write_fcc (const char *path, HEADER * hdr, const char *msgid,
     rewind (tempfp);
     while (fgets (sasha, sizeof (sasha), tempfp) != NULL)
       lines++;
-    fprintf (msg->fp, "Content-Length: %ld\n", (long) ftell (tempfp));
+    fprintf (msg->fp, "Content-Length: %zd\n", ftello (tempfp));
     fprintf (msg->fp, "Lines: %d\n\n", lines);
 
     /* copy the body and clean up */