commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-286-ga127864


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-286-ga127864
Date: Sat, 11 Dec 2010 21:11:36 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=a1278648c641baf2dd390e407f61d748ceeaa3d3

The branch, master has been updated
       via  a1278648c641baf2dd390e407f61d748ceeaa3d3 (commit)
       via  bd8b9b7977e8d1bc2cd09877b5050a758f1cc56f (commit)
       via  df07ce7dc7115193dac0b1f15a1dfa1d338e540d (commit)
       via  a52aac19b2a9f3c5b890160052376bed1a3b69f7 (commit)
       via  b8c5000a532587e60eb857aa1a36e2723eb2d34f (commit)
      from  5416e044b0995e3f49676152da15866fcf29d323 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a1278648c641baf2dd390e407f61d748ceeaa3d3
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 11 23:09:41 2010 +0200

    Minor fixes.
    
    * libmailutils/base/argcvjoin.c (mu_argcv_join): Fix a
    memory allocation error.
    * libmailutils/base/msgid.c (concat): Remove.
    (mu_rfc2822_references,mu_rfc2822_in_reply_to): Use mu_argcv_join
    to concatenate strings.

commit bd8b9b7977e8d1bc2cd09877b5050a758f1cc56f
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 11 21:05:57 2010 +0200

    mh,maildir: Minor fix.
    
    * libmailutils/base/amd.c (amd_envelope_date): Remove the
    trailing newline from the ctime output.

commit df07ce7dc7115193dac0b1f15a1dfa1d338e540d
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 11 20:15:17 2010 +0200

    mail: use mu_strout; remove util_error in favor of mu_error.

commit a52aac19b2a9f3c5b890160052376bed1a3b69f7
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 11 18:33:10 2010 +0200

    mail: rewrite using MU streams.
    
    * libmailutils/base/spawnvp.c (mu_spawnvp): Use fork and _exit,
    unconditionally.
    * libmailutils/stdstream/basestr.c (mu_stdstream_setup): Borrow
    descriptors 0, 1, 2.
    
    * mail/mail.h (compose_env) <filename, file, ofile>: Remove.
    <compstr>: New member.
    * mail/alias.c: Use MU streams instead of stdlib.
    * mail/alt.c: Likewise.
    * mail/copy.c: Likewise.
    * mail/decode.c: Likewise.
    * mail/echo.c: Likewise.
    * mail/envelope.c: Likewise.
    * mail/eq.c: Likewise.
    * mail/escape.c: Likewise.
    * mail/followup.c: Likewise.
    * mail/from.c: Likewise.
    * mail/inc.c: Likewise.
    * mail/mail.c: Likewise.
    * mail/mailline.c: Likewise.
    * mail/mailvar.c: Likewise.
    * mail/msgset.y: Likewise.
    * mail/print.c: Likewise.
    * mail/quit.c: Likewise.
    * mail/reply.c: Likewise.
    * mail/retain.c: Likewise.
    * mail/send.c: Likewise.
    * mail/setenv.c: Likewise.
    * mail/shell.c: Likewise.
    * mail/size.c: Likewise.
    * mail/source.c: Likewise.
    * mail/summary.c: Likewise.
    * mail/top.c: Likewise.
    * mail/unset.c: Likewise.
    * mail/util.c: Likewise.
    * mail/version.c: Likewise.
    * mail/write.c: Likewise.
    * mail/z.c: Likewise.

commit b8c5000a532587e60eb857aa1a36e2723eb2d34f
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 11 11:44:34 2010 +0200

    Minor change.
    
    * libmailutils/stream/stream.c (mu_stream_set_stat): Allow for 
statbuf==NULL.

-----------------------------------------------------------------------

Summary of changes:
 libmailutils/base/amd.c          |   15 +-
 libmailutils/base/argcvjoin.c    |    2 +-
 libmailutils/base/msgid.c        |   91 +++-----
 libmailutils/base/spawnvp.c      |    8 -
 libmailutils/stdstream/basestr.c |    6 +-
 libmailutils/stream/stream.c     |    7 +-
 mail/alias.c                     |    6 +-
 mail/alt.c                       |    6 +-
 mail/copy.c                      |    8 +-
 mail/decode.c                    |   97 ++++----
 mail/echo.c                      |  150 +++---------
 mail/envelope.c                  |    4 +-
 mail/eq.c                        |    7 +-
 mail/escape.c                    |  491 ++++++++++++++++++--------------------
 mail/file.c                      |    8 +-
 mail/folders.c                   |    2 +-
 mail/followup.c                  |    9 +-
 mail/from.c                      |    8 +-
 mail/if.c                        |   14 +-
 mail/inc.c                       |    4 +-
 mail/mail.c                      |   51 +++--
 mail/mail.h                      |   12 +-
 mail/mailline.c                  |   80 ++-----
 mail/mailvar.c                   |  110 +++++----
 mail/msgset.y                    |   24 +-
 mail/next.c                      |    6 +-
 mail/previous.c                  |    4 +-
 mail/print.c                     |   32 +--
 mail/quit.c                      |   10 +-
 mail/reply.c                     |   16 +-
 mail/retain.c                    |    5 +-
 mail/send.c                      |  253 +++++++++-----------
 mail/setenv.c                    |    2 +-
 mail/shell.c                     |  100 ++++-----
 mail/size.c                      |   10 +-
 mail/source.c                    |   44 ++--
 mail/struct.c                    |   15 +-
 mail/summary.c                   |   16 +-
 mail/top.c                       |   10 +-
 mail/unalias.c                   |    2 +-
 mail/unset.c                     |    2 +-
 mail/util.c                      |  103 +++++----
 mail/version.c                   |   10 +-
 mail/write.c                     |    8 +-
 mail/z.c                         |   12 +-
 45 files changed, 857 insertions(+), 1023 deletions(-)

diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c
index 9f95016..b41ff21 100644
--- a/libmailutils/base/amd.c
+++ b/libmailutils/base/amd.c
@@ -1885,7 +1885,9 @@ amd_envelope_date (mu_envelope_t envelope, char *buf, 
size_t len,
   mu_message_t msg = mu_envelope_get_owner (envelope);
   struct _amd_message *mhm = mu_message_get_owner (msg);
   mu_header_t hdr = NULL;
-  char *date;
+  const char *date;
+  char datebuf[25]; /* Buffer for the output of ctime (terminating nl being
+                      replaced by 0) */
   int status;
   
   if (mhm == NULL)
@@ -1893,8 +1895,8 @@ amd_envelope_date (mu_envelope_t envelope, char *buf, 
size_t len,
 
   if ((status = mu_message_get_header (msg, &hdr)) != 0)
     return status;
-  if (mu_header_aget_value (hdr, MU_HEADER_ENV_DATE, &date)
-      && mu_header_aget_value (hdr, MU_HEADER_DELIVERY_DATE, &date))
+  if (mu_header_sget_value (hdr, MU_HEADER_ENV_DATE, &date)
+      && mu_header_sget_value (hdr, MU_HEADER_DELIVERY_DATE, &date))
     return MU_ERR_NOENT;
   else
     {
@@ -1903,10 +1905,11 @@ amd_envelope_date (mu_envelope_t envelope, char *buf, 
size_t len,
       
       /* Convert to ctime format */
       rc = mu_parse_date (date, &t, NULL); /* FIXME: TZ info is lost */
-      free (date);
       if (rc)
        return MU_ERR_NOENT;
-      date = strdup (ctime (&t)); 
+      memcpy (datebuf, ctime (&t), sizeof (datebuf) - 1);
+      datebuf[sizeof (datebuf) - 1] = 0; /* Kill the terminating newline */
+      date = datebuf;
     }
 
   /* Format:  "sender date" */
@@ -1925,8 +1928,6 @@ amd_envelope_date (mu_envelope_t envelope, char *buf, 
size_t len,
   else
     len = strlen (date);
   
-  free (date);
-  
   if (psize)
     *psize = len;
   return 0;
diff --git a/libmailutils/base/argcvjoin.c b/libmailutils/base/argcvjoin.c
index a5877e8..aa8387c 100644
--- a/libmailutils/base/argcvjoin.c
+++ b/libmailutils/base/argcvjoin.c
@@ -72,7 +72,7 @@ mu_argcv_join (int argc, char **argv, char *delim, enum 
mu_argcv_escape esc,
       if (quote)
        len += 2;
       
-      buffer = realloc (buffer, len);
+      buffer = realloc (buffer, len + 1);
       if (buffer == NULL)
         return ENOMEM;
 
diff --git a/libmailutils/base/msgid.c b/libmailutils/base/msgid.c
index d7905b4..84f055b 100644
--- a/libmailutils/base/msgid.c
+++ b/libmailutils/base/msgid.c
@@ -32,6 +32,7 @@
 #include <mailutils/io.h>
 #include <mailutils/envelope.h>
 #include <mailutils/errno.h>
+#include <mailutils/argcv.h>
 
 #define ST_INIT  0
 #define ST_MSGID 1
@@ -82,27 +83,6 @@ get_msgid_header (mu_header_t hdr, const char *name, char 
**val)
   return strip_message_id (p, val);
 }
 
-static char *
-concat (const char *s1, const char *s2)
-{
-  int len = (s1 ? strlen (s1) : 0) + (s2 ? strlen (s2) : 0) + 2;
-  char *s = malloc (len);
-  if (s)
-    {
-      char *p = s;
-      
-      if (s1)
-       {
-         strcpy (p, s1);
-         p += strlen (s1);
-         *p++ = ' ';
-       }
-      if (s2)
-       strcpy (p, s2);
-    }
-  return s;
-}
-
 /* rfc2822:
    
    The "References:" field will contain the contents of the parent's
@@ -119,25 +99,30 @@ concat (const char *s1, const char *s2)
 int
 mu_rfc2822_references (mu_message_t msg, char **pstr)
 {
-  char *ref = NULL, *msgid = NULL;
+  char *argv[3] = { NULL, NULL, NULL };
   mu_header_t hdr;
   int rc;
   
   rc = mu_message_get_header (msg, &hdr);
   if (rc)
     return rc;
-  get_msgid_header (hdr, MU_HEADER_MESSAGE_ID, &msgid);
-  if (get_msgid_header (hdr, MU_HEADER_REFERENCES, &ref))
-    get_msgid_header (hdr, MU_HEADER_IN_REPLY_TO, &ref);
+  get_msgid_header (hdr, MU_HEADER_MESSAGE_ID, &argv[1]);
+  if (get_msgid_header (hdr, MU_HEADER_REFERENCES, &argv[0]))
+    get_msgid_header (hdr, MU_HEADER_IN_REPLY_TO, &argv[0]);
 
-  if (ref || msgid)
+  if (argv[0] && argv[1])
     {
-      *pstr = concat (ref, msgid);
-      free (ref);
-      free (msgid);
-      return 0;
+      rc = mu_argcv_join (2, argv, " ", mu_argcv_escape_no, pstr);
+      free (argv[0]);
+      free (argv[1]);
     }
-  return MU_ERR_FAILURE;
+  else if (argv[0])
+    *pstr = argv[0];
+  else if (argv[1])
+    *pstr = argv[1];
+  else
+    rc = MU_ERR_FAILURE;
+  return rc;
 }
 
 int
@@ -169,7 +154,6 @@ mu_rfc2822_msg_id (int subpart, char **pval)
   return 0;
 }
 
-#define DATEBUFSIZE 128
 #define COMMENT "Your message of "
 
 /*
@@ -184,47 +168,42 @@ mu_rfc2822_msg_id (int subpart, char **pval)
 int
 mu_rfc2822_in_reply_to (mu_message_t msg, char **pstr)
 {
-  const char *value = NULL;
-  char *s1 = NULL, *s2 = NULL;
+  const char *argv[] = { NULL, NULL, NULL, NULL, NULL };
   mu_header_t hdr;
   int rc;
+  int idx = 0;
   
   rc = mu_message_get_header (msg, &hdr);
   if (rc)
     return rc;
   
-  if (mu_header_sget_value (hdr, MU_HEADER_DATE, &value))
+  if (mu_header_sget_value (hdr, MU_HEADER_DATE, &argv[idx + 1]))
     {
       mu_envelope_t envelope = NULL;
       mu_message_get_envelope (msg, &envelope);
-      mu_envelope_sget_date (envelope, &value);
+      mu_envelope_sget_date (envelope, &argv[idx + 1]);
     }
 
-  if (value)
+  if (argv[idx + 1])
     {
-      s1 = malloc (sizeof (COMMENT) + strlen (value));
-      if (!s1)
-       return ENOMEM;
-      strcat (strcpy (s1, COMMENT), value);
+      argv[idx] = COMMENT;
+      idx = 2;
     }
-  
-  if (mu_header_sget_value (hdr, MU_HEADER_MESSAGE_ID, &value) == 0)
+    
+  if (mu_header_sget_value (hdr, MU_HEADER_MESSAGE_ID, &argv[idx]) == 0)
     {
-      s2 = malloc (strlen (value) + 3);
-      if (!s2)
+      if (idx > 1)
        {
-         free (s1);
-         return ENOMEM;
+         argv[idx + 1] = argv[idx];
+         argv[idx] = "\n\t";
+         idx++;
        }
-      strcat (strcpy (s2, "\n\t"), value);
+      idx++;
     }
 
-  if (s1 || s2)
-    {
-      *pstr = concat (s1, s2);
-      free (s1);
-      free (s2);
-      return 0;
-    }
-  return MU_ERR_FAILURE;
+  if (idx > 1)
+    rc = mu_argcv_join (idx, argv, "", mu_argcv_escape_no, pstr);
+  else
+    rc = MU_ERR_FAILURE;
+  return rc;
 }
diff --git a/libmailutils/base/spawnvp.c b/libmailutils/base/spawnvp.c
index 25d7059..eaec235 100644
--- a/libmailutils/base/spawnvp.c
+++ b/libmailutils/base/spawnvp.c
@@ -70,11 +70,7 @@ mu_spawnvp (const char *prog, char *av[], int *stat)
       return errno;
     }
 
-#ifdef HAVE_VFORK
-  pid = vfork ();
-#else
   pid = fork ();
-#endif
 
   if (pid < 0)
     {
@@ -88,11 +84,7 @@ mu_spawnvp (const char *prog, char *av[], int *stat)
       sigprocmask (SIG_SETMASK, &savemask, NULL);
 
       execvp (prog, av);
-#ifdef HAVE__EXIT      
       _exit (127);             /* exec error */
-#else
-      exit (127);
-#endif
     }
   else
     {                          /* parent */
diff --git a/libmailutils/stdstream/basestr.c b/libmailutils/stdstream/basestr.c
index a845927..b42d76f 100644
--- a/libmailutils/stdstream/basestr.c
+++ b/libmailutils/stdstream/basestr.c
@@ -46,7 +46,8 @@ mu_stdstream_setup ()
 {
   int rc;
   int fd;
-
+  int yes = 1;
+  
   /* If the streams are already open, close them */
   mu_stream_destroy (&mu_strin);
   mu_stream_destroy (&mu_strout);
@@ -90,6 +91,8 @@ mu_stdstream_setup ()
               MU_STDIN_FD, mu_strerror (rc));
       abort ();
     }
+  mu_stream_ioctl (mu_strin, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
+  
   rc = mu_stdio_stream_create (&mu_strout, MU_STDOUT_FD, 0);
   if (rc)
     {
@@ -97,6 +100,7 @@ mu_stdstream_setup ()
               MU_STDOUT_FD, mu_strerror (rc));
       abort ();
     }
+  mu_stream_ioctl (mu_strout, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
 
   if (mu_stdstream_strerr_create (&mu_strerr, MU_STRERR_STDERR, 0, 0,
                                  mu_program_name, NULL))
diff --git a/libmailutils/stream/stream.c b/libmailutils/stream/stream.c
index 45efe3b..7b6a3c7 100644
--- a/libmailutils/stream/stream.c
+++ b/libmailutils/stream/stream.c
@@ -1238,10 +1238,13 @@ mu_stream_set_stat (mu_stream_t stream, int statmask,
 {
   if (stream == NULL)
     return EINVAL;
+  if (!statbuf)
+    statmask = 0;
   stream->statmask = statmask;
   stream->statbuf = statbuf;
-  memset (stream->statbuf, 0,
-         _MU_STREAM_STAT_MAX * sizeof (stream->statbuf[0]));
+  if (stream->statbuf)
+    memset (stream->statbuf, 0,
+           _MU_STREAM_STAT_MAX * sizeof (stream->statbuf[0]));
   return 0;
 }
 
diff --git a/mail/alias.c b/mail/alias.c
index 7ff2085..908ee93 100644
--- a/mail/alias.c
+++ b/mail/alias.c
@@ -36,9 +36,9 @@ alias_free (void *data)
 static void
 alias_print_group (const char *name, alias_t al)
 {
-  fprintf (ofile, "%s    ", name);
+  mu_printf ("%s    ", name);
   util_slist_print (al->list, 0);
-  fprintf (ofile, "\n");
+  mu_printf ("\n");
 }
 
 static alias_t
@@ -75,7 +75,7 @@ alias_print (char *name)
       al = alias_lookup (name);
       if (!al)
        {
-         util_error (_("\"%s\": not a group"), name);
+         mu_error (_("\"%s\": not a group"), name);
          return;
        }
       alias_print_group (name, al);
diff --git a/mail/alt.c b/mail/alt.c
index c9545b3..3b16310 100644
--- a/mail/alt.c
+++ b/mail/alt.c
@@ -34,7 +34,7 @@ mail_alt (int argc, char **argv)
       if (alternate_names)
        {
          util_slist_print (alternate_names, 0);
-         fprintf (ofile, "\n");
+         mu_printf ("\n");
        }
     }
   else
@@ -60,7 +60,7 @@ mail_set_my_name (char *name)
       struct passwd *pw = getpwuid (getuid ());
       if (!pw)
        {
-         util_error (_("Cannot determine my username"));
+         mu_error (_("Cannot determine my username"));
          exit (1);
        }
       name = pw->pw_name;
@@ -69,7 +69,7 @@ mail_set_my_name (char *name)
   my_email = mu_get_user_email (name);
   if (!my_email)
     {
-      util_error(_("Cannot determine my email address: %s"),
+      mu_error(_("Cannot determine my email address: %s"),
                 mu_strerror (errno));
       exit (1);
     }
diff --git a/mail/copy.c b/mail/copy.c
index e1775be..a8cd8f7 100644
--- a/mail/copy.c
+++ b/mail/copy.c
@@ -64,7 +64,7 @@ mail_copy0 (int argc, char **argv, int mark)
 
   if ((status = mu_mailbox_create_default (&mbx, filename)) != 0)
     {
-      util_error (_("Cannot create mailbox %s: %s"), filename, 
+      mu_error (_("Cannot create mailbox %s: %s"), filename, 
                    mu_strerror (status));
       free (filename);
       msgset_free (msglist);
@@ -72,7 +72,7 @@ mail_copy0 (int argc, char **argv, int mark)
     }
   if ((status = mu_mailbox_open (mbx, MU_STREAM_WRITE | MU_STREAM_CREAT)) != 0)
     {
-      util_error (_("Cannot open mailbox %s: %s"), filename, 
+      mu_error (_("Cannot open mailbox %s: %s"), filename, 
                    mu_strerror (status));
       free (filename);
       msgset_free (msglist);
@@ -88,7 +88,7 @@ mail_copy0 (int argc, char **argv, int mark)
       status = mu_mailbox_append_message (mbx, msg);
       if (status)
        {
-         util_error (_("Cannot append message: %s"), mu_strerror (status));
+         mu_error (_("Cannot append message: %s"), mu_strerror (status));
          break;
        }
       
@@ -106,7 +106,7 @@ mail_copy0 (int argc, char **argv, int mark)
     }
 
   if (status == 0)
-    fprintf (ofile, "\"%s\" %3lu/%-5lu\n", filename,
+    mu_printf ("\"%s\" %3lu/%-5lu\n", filename,
             (unsigned long) total_lines, (unsigned long) total_size);
 
   mu_mailbox_close (mbx);
diff --git a/mail/decode.c b/mail/decode.c
index 699c464..a2b649f 100644
--- a/mail/decode.c
+++ b/mail/decode.c
@@ -29,7 +29,7 @@ struct decode_closure
   int select_hdr;
 };
 
-static int print_stream (mu_stream_t, FILE *);
+static int print_stream (mu_stream_t, mu_stream_t);
 static int display_message (mu_message_t, msgset_t *msgset, void *closure);
 static int display_submessage (struct mime_descend_closure *closure,
                               void *data);
@@ -81,7 +81,7 @@ display_message (mu_message_t mesg, msgset_t *msgset, void 
*arg)
 }
 
 static void
-display_headers (FILE *out, mu_message_t mesg, 
+display_headers (mu_stream_t out, mu_message_t mesg, 
                  const msgset_t *msgset MU_ARG_UNUSED,
                 int select_hdr)
 {
@@ -102,13 +102,13 @@ display_headers (FILE *out, mu_message_t mesg,
            continue;
          if (mail_header_is_visible (sptr))
            {
-             fprintf (out, "%s: ", sptr);
+             mu_stream_printf (out, "%s: ", sptr);
              if (mu_header_sget_field_value (hdr, i, &sptr))
                sptr = "";
-             fprintf (out, "%s\n", sptr);
+             mu_stream_printf (out, "%s\n", sptr);
            }
        }
-      fprintf (out, "\n");
+      mu_stream_printf (out, "\n");
     }
   else /* Print displays all headers.  */
     {
@@ -122,43 +122,50 @@ display_headers (FILE *out, mu_message_t mesg,
     }
 }
 
-size_t
-fprint_msgset (FILE *fp, const msgset_t *msgset)
+void
+format_msgset (mu_stream_t str, const msgset_t *msgset, size_t *count)
 {
   int i;
-  size_t n = 0;
-  
-  n = fprintf (fp, "%lu", (unsigned long) msgset->msg_part[0]);
+  mu_stream_stat_buffer stat;
+
+  if (count)
+    mu_stream_set_stat (str, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT),
+                       stat);
+  mu_stream_printf (str, "%lu", (unsigned long) msgset->msg_part[0]);
   for (i = 1; i < msgset->npart; i++)
-    n += fprintf (fp, "[%lu", (unsigned long) msgset->msg_part[i]);
+    mu_stream_printf (str, "[%lu", (unsigned long) msgset->msg_part[i]);
   for (i = 1; i < msgset->npart; i++)
-    n += fprintf (fp, "]");
-  return n;
+    mu_stream_printf (str, "]");
+  if (count)
+    {
+      *count = stat[MU_STREAM_STAT_OUT];
+      mu_stream_set_stat (str, 0, NULL);
+    }
 }
 
 static void
-display_part_header (FILE *out, const msgset_t *msgset,
+display_part_header (mu_stream_t str, const msgset_t *msgset,
                     const char *type, const char *encoding)
 {
   int size = util_screen_columns () - 3;
   unsigned int i;
 
-  fputc ('+', out);
+  mu_stream_printf (str, "+");
   for (i = 0; (int)i <= size; i++)
-    fputc ('-', out);
-  fputc ('+', out);
-  fputc ('\n', out);
-  fprintf (out, "%s", _("| Message="));
-  fprint_msgset (out, msgset);
-  fprintf (out, "\n");
-
-  fprintf (out, _("| Type=%s\n"), type);
-  fprintf (out, _("| Encoding=%s\n"), encoding);
-  fputc ('+', out);
-  for (i = 0; (int)i <= size; i++)
-    fputc ('-', out);
-  fputc ('+', out);
-  fputc ('\n', out);
+    mu_stream_printf (str, "-");
+  mu_stream_printf (str, "+");
+  mu_stream_printf (str, "\n");
+  mu_stream_printf (str, "%s", _("| Message="));
+  format_msgset (str, msgset, NULL);
+  mu_stream_printf (str, "\n");
+
+  mu_stream_printf (str, _("| Type=%s\n"), type);
+  mu_stream_printf (str, _("| Encoding=%s\n"), encoding);
+  mu_stream_printf (str, "+");
+  for (i = 0; i <= size; i++)
+    mu_stream_printf (str, "-");
+  mu_stream_printf (str, "+");
+  mu_stream_printf (str, "\n");
 }
 
 int
@@ -268,7 +275,8 @@ display_submessage (struct mime_descend_closure *closure, 
void *data)
       else
        stream = b_stream;
       
-      display_part_header (ofile, closure->msgset,
+      display_part_header (mu_strout,
+                          closure->msgset,
                           closure->type, closure->encoding);
       
       /* If `metamail' is set to true, enable internal mailcap
@@ -290,22 +298,17 @@ display_submessage (struct mime_descend_closure *closure, 
void *data)
       if (builtin_display)
        {
          size_t lines = 0;
-         int pagelines = util_get_crt ();
-         FILE *out;
+         mu_stream_t str;
          
          mu_message_lines (closure->message, &lines);
-         if (pagelines && lines > pagelines)
-           out = popen (getenv ("PAGER"), "w");
-         else
-           out = ofile;
+         str = open_pager (lines);
          
-         display_headers (out, closure->message, closure->msgset,
+         display_headers (str, closure->message, closure->msgset,
                           closure->hints & MDHINT_SELECTED_HEADERS);
          
-         print_stream (stream, out);
-         
-         if (out != ofile)
-           pclose (out);
+         print_stream (stream, str);
+
+         mu_stream_unref (str);
        }
       mu_stream_destroy (&stream);
     }
@@ -315,7 +318,7 @@ display_submessage (struct mime_descend_closure *closure, 
void *data)
 
 /* FIXME: Try to use mu_stream_copy instead */
 static int
-print_stream (mu_stream_t stream, FILE *out)
+print_stream (mu_stream_t stream, mu_stream_t out)
 {
   char buffer[512];
   size_t n = 0;
@@ -325,11 +328,11 @@ print_stream (mu_stream_t stream, FILE *out)
     {
       if (ml_got_interrupt())
        {
-         util_error(_("\nInterrupt"));
+         mu_error(_("\nInterrupt"));
          break;
        }
       buffer[n] = '\0';
-      fprintf (out, "%s", buffer);
+      mu_stream_printf (out, "%s", buffer);
     }
   return 0;
 }
@@ -365,12 +368,12 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg)
   sigemptyset (&ignore.sa_mask);
   if (sigaction (SIGINT, &ignore, &saveintr) < 0)
     {
-      util_error ("sigaction: %s", strerror (errno));
+      mu_error ("sigaction: %s", strerror (errno));
       return;
     }      
   if (sigaction (SIGQUIT, &ignore, &savequit) < 0)
     {
-      util_error ("sigaction: %s", strerror (errno));
+      mu_error ("sigaction: %s", strerror (errno));
       sigaction (SIGINT, &saveintr, NULL);
       return;
     }      
@@ -388,7 +391,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg)
   pid = fork ();
   if (pid < 0)
     {
-      util_error ("fork: %s", strerror (errno));
+      mu_error ("fork: %s", strerror (errno));
     }
   else if (pid == 0)
     {
diff --git a/mail/echo.c b/mail/echo.c
index 0579e20..57dea9e 100644
--- a/mail/echo.c
+++ b/mail/echo.c
@@ -21,129 +21,55 @@
  * ec[ho] string ...
  */
 
-static int echo (char *s);
-
-int
-mail_echo (int argc, char **argv)
+static int
+echo (char *s)
 {
-  int i = 0;
-  if (argc > 1)
+  struct mu_wordsplit ws;
+  size_t len = strlen (s);
+  int rc = 1;
+
+  /* FIXME: This logic is flawed */
+  if (len > 0 && s[len - 1] == '\\')
     {
-      for (i = 1; i < argc - 1; i++)
+      if (len == 1)
+       return 0;
+      if (s[len-2] != '\\')
        {
-         echo (argv[i]);
-         fputc (' ', ofile);
+         --len;
+         rc = 0;
        }
-      /* Last argument.  */
-      if (echo(argv[argc - 1]) == 0)
-       fputc ('\n', ofile);
     }
-  return 0;
+      
+      
+  if (mu_wordsplit_len (s, len, &ws,
+                       MU_WRDSF_NOSPLIT |
+                       MU_WRDSF_NOCMD | MU_WRDSF_NOVAR | MU_WRDSF_QUOTE))
+    {
+      mu_error (_("cannot split `%s': %s"), s,
+               mu_wordsplit_strerror (&ws));
+    }
+  else
+    {
+      mu_printf ("%s", ws.ws_wordv[0]);
+      mu_wordsplit_free (&ws);
+    }
+  return rc;
 }
 
-/* Cumbersome switch for checking escape char '\'
-   if present replace with appropriately.
-   Return of 1 means to not print newline.  */
-static int
-echo (char *s)
+int
+mail_echo (int argc, char **argv)
 {
-  int process_escape = 0;
-  int c;
-
-  if (s == NULL)
-    return 0;
-
-  for (; (c = *s) != 0; s++)
+  if (argc > 1)
     {
-      if (process_escape)
+      int i = 0;
+      
+      for (i = 1; i < argc; i++)
        {
-         switch (c)
-           {
-             /* \a Bell.  */
-           case 'a':
-             c = '\a';
-             break;
-
-             /* \b Backspace.  */
-           case 'b':
-             c = '\b';
-             break;
-
-             /* \c means not to print ending newline.  */
-             /* Bail out and tell the caller not to print newline.  */
-           case 'c':
-             return 1;
-             break;
-
-             /* \f Formfeed.  */
-           case 'f':
-             c = '\f';
-             break;
-
-             /* \n Newline.  */
-           case 'n':
-             c = '\n';
-             break;
-
-             /* \r Carriage return.  */
-           case 'r':
-             c = '\r';
-             break;
-
-             /* \t Tab. */
-           case 't':
-             c = '\t';
-             break;
-
-             /* \v Vertical Tab.  */
-           case 'v':
-             c = '\v';
-             break;
-
-             /* Escape sequence.  */
-           case '\\':
-             c = '\\';
-             break;
-
-             /* \0x99 for example, let strtol() handle it.  */
-             /* WARNING: Side effects because of strtol().  */
-           case '0':
-             {
-               long number = strtol (s, &s, 0);
-               switch (number)
-                 {
-                 case LONG_MIN:
-                 case LONG_MAX:
-                   /* if (errno == ERANGE) */
-                   /*  fputc (c, ofile); */
-                   break;
-
-                 default:
-                   fprintf (ofile, "%ld", number);
-                   s--;
-                   continue;
-                 }
-             }
-             break;
-
-             /* Can not be here.  */
-           case '\0':
-             return 0;
-             break;
-
-             /* \\ means \ It was not an escape char.  */
-           default:
-             fputc ('\\', ofile);
-
-           }
-         process_escape =0;
-       }
-      else if (c == '\\') /* Find the escape char, go back and process.  */
-       {
-         process_escape = 1;
-         continue;
+         if (echo (argv[i]))
+           mu_printf (" ");
        }
-      fputc (c, ofile);
+      mu_printf ("\n");
     }
   return 0;
 }
+
diff --git a/mail/envelope.c b/mail/envelope.c
index 575c12a..287a355 100644
--- a/mail/envelope.c
+++ b/mail/envelope.c
@@ -38,8 +38,8 @@ print_envelope (msgset_t *mspec, mu_message_t msg, void *data)
       mu_envelope_sget_sender (env, &sender);
       mu_envelope_sget_date (env, &date);
       if (data)
-       fprintf (ofile, "%s ", (char*) data);
-      fprintf (ofile, "%s %s", sender, date);
+       mu_printf ("%s ", (char*) data);
+      mu_printf ("%s %s", sender, date);
     }
   return 0;
 }
diff --git a/mail/eq.c b/mail/eq.c
index 6a414d9..d0fce27 100644
--- a/mail/eq.c
+++ b/mail/eq.c
@@ -32,9 +32,9 @@ mail_eq (int argc, char **argv)
     case 1:
       n = get_cursor ();
       if (n == 0)
-        util_error (_("No applicable message"));
+        mu_error (_("No applicable message"));
       else
-        fprintf (ofile, "%lu\n", (unsigned long) n);
+        mu_printf ("%lu\n", (unsigned long) n);
       break;
 
     case 2:
@@ -43,7 +43,8 @@ mail_eq (int argc, char **argv)
          if (list->msg_part[0] <= total)
            {
              set_cursor (list->msg_part[0]);
-             fprintf (ofile, "%lu\n", (unsigned long) list->msg_part[0]);
+             mu_printf ("%lu\n",
+                               (unsigned long) list->msg_part[0]);
            }
          else
            util_error_range (list->msg_part[0]);
diff --git a/mail/escape.c b/mail/escape.c
index a860c0e..de1c15e 100644
--- a/mail/escape.c
+++ b/mail/escape.c
@@ -21,27 +21,19 @@
 #include <sys/stat.h>
 
 static void
-dump_headers (FILE *fp, compose_env_t *env)
+dump_headers (mu_stream_t out, compose_env_t *env)
 {
-  char buffer[512];
   mu_stream_t stream = NULL;
-  size_t n;
   int rc;
   
   rc = mu_header_get_streamref (env->header, &stream);
   if (rc)
     {
-      util_error ("mu_header_get_streamref: %s",
+      mu_error ("mu_header_get_streamref: %s",
                  mu_stream_strerror (stream, rc));
       return;
     }
-  /* FIXME: Use mu_stream_copy */
-  while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0
-        && n != 0)
-    {
-      buffer[n] = 0;
-      fprintf (fp, "%s", buffer);
-    }
+  mu_stream_copy (out, stream, 0, NULL);
   mu_stream_destroy (&stream);
 }
 
@@ -50,29 +42,29 @@ dump_headers (FILE *fp, compose_env_t *env)
 #define STATE_BODY 2
 
 static int
-parse_headers (FILE *fp, compose_env_t *env)
+parse_headers (mu_stream_t input, compose_env_t *env)
 {
   int status;
   mu_header_t header;
   char *name = NULL;
   char *value = NULL;
-  char *buf = NULL;
   int state = STATE_INIT;
-  size_t n = 0;
+  char *buf = NULL;
+  size_t size = 0, n;
   int errcnt = 0, line = 0;
   
   if ((status = mu_header_create (&header, NULL, 0)) != 0)
     {
-      util_error (_("Cannot create header: %s"), mu_strerror (status));
+      mu_error (_("Cannot create header: %s"), mu_strerror (status));
       return 1;
     }
 
-  while (state != STATE_BODY
-        && errcnt == 0 && getline (&buf, &n, fp) > 0 && n > 0)
+  mu_stream_seek (input, 0, MU_SEEK_SET, NULL);
+  while (state != STATE_BODY &&
+        errcnt == 0 &&
+        mu_stream_getline (input, &buf, &size, &n) == 0 && n > 0)
     {
-      int len = strlen (buf);
-      if (len > 0 && buf[len-1] == '\n')
-       buf[len-1] = 0;
+      mu_rtrim_class (buf, MU_CTYPE_SPACE);
 
       line++;
       switch (state)
@@ -99,7 +91,7 @@ parse_headers (FILE *fp, compose_env_t *env)
                }
              else
                {
-                 util_error (_("%d: not a header line"), line);
+                 mu_error (_("%d: not a header line"), line);
                  errcnt++;
                }
            }
@@ -125,7 +117,7 @@ parse_headers (FILE *fp, compose_env_t *env)
                }
              else
                {
-                 util_error (_("%d: not a header line"), line);
+                 mu_error (_("%d: not a header line"), line);
                  errcnt++;
                }
            }
@@ -161,7 +153,7 @@ parse_headers (FILE *fp, compose_env_t *env)
 static void
 escape_continue (void)
 {
-  fprintf (stdout, _("(continue)\n"));
+  mu_printf (_("(continue)\n"));
 }
 
 static int 
@@ -171,7 +163,7 @@ escape_check_args (int argc, char **argv)
     {
       char *escape = "~";
       mailvar_get (&escape, "escape", mailvar_type_string, 0);
-      util_error (_("%c%s requires an argument"), escape[0], argv[0]);
+      mu_error (_("%c%s requires an argument"), escape[0], argv[0]);
       return 1;
     }
   return 0;
@@ -181,12 +173,7 @@ escape_check_args (int argc, char **argv)
 int
 escape_shell (int argc, char **argv, compose_env_t *env)
 {
-  int status;
-  ofile = env->ofile;
-  ++*argv;
-  status = mail_execute (1, argc, argv);
-  ofile = env->file;
-  return status;
+  return mail_execute (1, argc - 1, argv + 1);
 }
 
 /* ~:[mail-command] */
@@ -196,7 +183,7 @@ escape_command (int argc, char **argv, compose_env_t *env)
 {
   const struct mail_command_entry *entry;
   int status;
-
+  
   if (escape_check_args (argc, argv))
     return 1;
   if (argv[1][0] == '#')
@@ -204,18 +191,16 @@ escape_command (int argc, char **argv, compose_env_t *env)
   entry = mail_find_command (argv[1]);
   if (!entry)
     {
-      util_error (_("Unknown command: %s"), argv[1]);
+      mu_error (_("Unknown command: %s"), argv[1]);
       return 1;
     }
   if (entry->flags & (EF_FLOW | EF_SEND))
     {
-      util_error (_("Command not allowed in an escape sequence\n"));
+      mu_error (_("Command not allowed in an escape sequence\n"));
       return 1;
     }
 
-  ofile = env->ofile;
   status = (*entry->func) (argc - 1, argv + 1);
-  ofile = env->file;
   return status;
 }
 
@@ -236,37 +221,32 @@ escape_help (int argc, char **argv, compose_env_t *env 
MU_ARG_UNUSED)
 /* ~A */
 /* ~a */
 int
-escape_sign (int argc MU_ARG_UNUSED, char **argv, compose_env_t *env 
MU_ARG_UNUSED)
+escape_sign (int argc MU_ARG_UNUSED, char **argv, compose_env_t *env)
 {
   char *p;
 
   if (mailvar_get (&p, mu_isupper (argv[0][0]) ? "Sign" : "sign",
                   mailvar_type_string, 1) == 0)
     {
-      fputs ("-- \n", ofile);
+      mu_stream_printf (env->compstr, "-- \n");
       if (mu_isupper (argv[0][0]))
        {
          char *name = util_fullpath (p);
-         FILE *fp = fopen (name, "r");
-         char *buf = NULL;
-         size_t n = 0;
+         int rc;
+         mu_stream_t signstr;
 
-         if (!fp)
+         rc = mu_file_stream_create (&signstr, name, MU_STREAM_READ);
+         if (rc)
+           mu_error (_("Cannot open %s: %s"), name, mu_strerror (rc));
+         else
            {
-             util_error (_("Cannot open %s: %s"), name, mu_strerror (errno));
-             free (name);
+             mu_printf (_("Reading %s\n"), name);
+             mu_stream_copy (env->compstr, signstr, 0, NULL);
+             mu_stream_destroy (&signstr);
            }
-
-         fprintf (stdout, _("Reading %s\n"), name);
-         while (getline (&buf, &n, fp) > 0)
-           fprintf (ofile, "%s", buf);
-
-         fclose (fp);
-         free (buf);
-         free (name);
        }
       else
-       fprintf (ofile, "%s", p);
+       mu_stream_printf (env->compstr, "%s\n", p);
       escape_continue ();
     }
   return 0;
@@ -290,20 +270,50 @@ escape_cc (int argc, char **argv, compose_env_t *env)
   return 0;
 }
 
+static int
+verbose_copy (mu_stream_t dest, mu_stream_t src, const char *filename,
+             mu_off_t *psize)
+{
+  int rc;
+  char *buf = NULL;
+  size_t size = 0, n;
+  size_t lines;
+  mu_off_t total;
+  
+  total = lines = 0;
+
+  while ((rc = mu_stream_getline (src, &buf, &size, &n)) == 0 && n > 0)
+    {
+      lines++;
+      rc = mu_stream_write (dest, buf, n, NULL);
+      if (rc)
+       break;
+      total += n;
+    }
+  if (rc)
+    mu_error (_("error copying data: %s"), mu_strerror (rc));
+  mu_printf ("\"%s\" %lu/%lu\n", filename,
+                   (unsigned long) lines, (unsigned long) total);
+  if (psize)
+    *psize = total;
+  return rc;
+}
+
 /* ~d */
 int
 escape_deadletter (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED,
-                  compose_env_t *env MU_ARG_UNUSED)
+                  compose_env_t *env)
 {
-  FILE *dead = fopen (getenv ("DEAD"), "r");
-  int c;
-
-  if (dead)
+  const char *name = getenv ("DEAD");
+  mu_stream_t str;
+  int rc = mu_file_stream_create (&str, name, MU_STREAM_READ);
+  if (rc)
     {
-      while ((c = fgetc (dead)) != EOF)
-       fputc (c, ofile);
-      fclose (dead);
+      mu_error (_("Cannot open file %s: %s"), name, strerror (rc));
+      return 1;
     }
+  verbose_copy (env->compstr, str, name, NULL);
+  mu_stream_destroy (&str);
   return 0;
 }
 
@@ -321,60 +331,80 @@ run_editor (char *ed, char *arg)
 static int
 escape_run_editor (char *ed, int argc, char **argv, compose_env_t *env)
 {
-  if (!mailvar_get (NULL, "editheaders", mailvar_type_boolean, 0))
+  char *filename;
+  int fd;
+  mu_stream_t tempstream;
+  int rc;
+  
+  rc = mu_tempfile (NULL, 0, &fd, &filename);
+  if (rc)
     {
-      char *filename;
-      int fd;
-      FILE *fp;
-      char buffer[512];
-      int rc;
-      
-      rc = mu_tempfile (NULL, 0, &fd, &filename);
-      if (rc)
-        {
-           mu_diag_funcall (MU_DIAG_ERROR, "mu_tempfile", NULL, rc);
-           return rc;
-        }
-
-      fp = fdopen (fd, "w+");
-      dump_headers (fp, env);
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_tempfile", NULL, rc);
+      return rc;
+    }
+  rc = mu_fd_stream_create (&tempstream, filename, fd, MU_STREAM_RDWR);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_fd_stream_create", filename, rc);
+      unlink (filename);
+      free (filename);
+      close (fd);
+      return rc;
+    }
 
-      rewind (env->file);
-      while (fgets (buffer, sizeof (buffer), env->file))
-       fputs (buffer, fp);
+  mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+  if (!mailvar_get (NULL, "editheaders", mailvar_type_boolean, 0))
+    {
+      dump_headers (tempstream, env);
 
-      fclose (env->file);
+      mu_stream_copy (tempstream, env->compstr, 0, NULL);
       
       do
        {
-         fclose (fp);
+         mu_stream_destroy (&tempstream);
          run_editor (ed, filename);
-         fp = fopen (filename, "r");
-       }
-      while ((rc = parse_headers (fp, env)) < 0);
-
-      if (rc == 0)
-       {
-         env->file = fopen (env->filename, "w");
-         while (fgets (buffer, sizeof (buffer), fp))
-           fputs (buffer, env->file);
-
-         fclose (env->file);
+         rc = mu_file_stream_create (&tempstream, filename, MU_STREAM_RDWR);
+         if (rc)
+           {
+             mu_diag_funcall (MU_DIAG_ERROR, "mu_file_stream_create",
+                              filename, rc);
+             unlink (filename);
+             free (filename);
+             return rc;
+           }
        }
-      fclose (fp);
-      unlink (filename);
-      free (filename);
+      while ((rc = parse_headers (tempstream, env)) < 0);
     }
   else
     {
-      fclose (env->file);
-      ofile = env->ofile;
-      run_editor (ed, env->filename);
+      mu_stream_copy (tempstream, env->compstr, 0, NULL);
+      mu_stream_destroy (&tempstream);
+      run_editor (ed, filename);
+      rc = mu_file_stream_create (&tempstream, filename, MU_STREAM_RDWR);
+      if (rc)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_file_stream_create",
+                          filename, rc);
+         unlink (filename);
+         free (filename);
+         return rc;
+       }
     }
 
-  env->file = fopen (env->filename, "a+");
-  ofile = env->file;
+  if (rc == 0)
+    {
+      mu_off_t size;
       
+      mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+      mu_stream_copy (env->compstr, tempstream, 0, &size);
+      mu_stream_truncate (env->compstr, size);
+    }
+  mu_stream_destroy (&tempstream);
+  unlink (filename);
+  free (filename);
+
+  mu_stream_seek (env->compstr, 0, MU_SEEK_END, NULL);
+  
   escape_continue ();
   return 0;
 }
@@ -425,57 +455,53 @@ escape_headers (int argc, char **argv, compose_env_t *env)
 
 /* ~i[var-name] */
 int
-escape_insert (int argc, char **argv, compose_env_t *send_env MU_ARG_UNUSED)
+escape_insert (int argc, char **argv, compose_env_t *env)
 {
   if (escape_check_args (argc, argv))
     return 1;
-  mailvar_variable_format (ofile, mailvar_find_variable (argv[1], 0), NULL);
+  mailvar_variable_format (env->compstr, mailvar_find_variable (argv[1], 0),
+                          NULL);
   return 0;
 }
 
 /* ~m[mesg-list] */
 /* ~M[mesg-list] */
 
+struct quote_closure
+{
+  mu_stream_t str;
+  int islower;
+};
+
 int
 quote0 (msgset_t *mspec, mu_message_t mesg, void *data)
 {
+  struct quote_closure *clos = data;
   int rc;
   mu_stream_t stream;
   char *prefix = "\t";
-  mu_stream_t outstr, flt;
+  mu_stream_t flt;
   char *argv[3];
-  int yes = 1;
 
-  fprintf (stdout, _("Interpolating: %lu\n"),
-          (unsigned long) mspec->msg_part[0]);
+  mu_printf (_("Interpolating: %lu\n"),
+                   (unsigned long) mspec->msg_part[0]);
 
   mailvar_get (&prefix, "indentprefix", mailvar_type_string, 0);
 
-  fflush (ofile);
-  rc = mu_stdio_stream_create (&outstr, fileno (ofile), MU_STREAM_WRITE);
-  if (rc)
-    {
-      mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", NULL, rc);
-      return rc;
-    }
-  /* Set borrow flag to prevent fileno (ofile) from being closed on
-     destroying outstr. */
-  mu_stream_ioctl (outstr, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
   argv[0] = "INLINE-COMMENT";
   argv[1] = prefix;
   argv[2] = NULL;
-  rc = mu_filter_create_args (&flt, outstr, "INLINE-COMMENT",
+  rc = mu_filter_create_args (&flt, clos->str, "INLINE-COMMENT",
                              2, (const char**) argv,
                              MU_FILTER_ENCODE,
                              MU_STREAM_WRITE);
-  mu_stream_unref (outstr);
   if (rc)
     {
       mu_diag_funcall (MU_DIAG_ERROR, "mu_filter_create_args", NULL, rc);
       return rc;
     }
   
-  if (*(int*)data)
+  if (clos->islower)
     {
       mu_header_t hdr;
       mu_body_t body;
@@ -503,7 +529,7 @@ quote0 (msgset_t *mspec, mu_message_t mesg, void *data)
 
   if (rc)
     {
-      util_error (_("get_streamref error: %s"), mu_strerror (rc));
+      mu_error (_("get_streamref error: %s"), mu_strerror (rc));
       return rc;
     }
 
@@ -518,8 +544,11 @@ quote0 (msgset_t *mspec, mu_message_t mesg, void *data)
 int
 escape_quote (int argc, char **argv, compose_env_t *env)
 {
-  int lower = mu_islower (argv[0][0]);
-  util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT, quote0, &lower);
+  struct quote_closure clos;
+  
+  clos.str = env->compstr;
+  clos.islower = mu_islower (argv[0][0]);
+  util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT, quote0, &clos);
   escape_continue ();
   return 0;
 }
@@ -528,18 +557,12 @@ escape_quote (int argc, char **argv, compose_env_t *env)
 int
 escape_type_input (int argc, char **argv, compose_env_t *env)
 {
-  char buffer[512];
-
-  fprintf (env->ofile, _("Message contains:\n"));
-
-  dump_headers (env->ofile, env);
-
-  rewind (env->file);
-  while (fgets (buffer, sizeof (buffer), env->file))
-    fputs (buffer, env->ofile);
-
+  /* FIXME: Enable paging */
+  mu_printf (_("Message contains:\n"));
+  dump_headers (mu_strout, env);
+  mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+  mu_stream_copy (mu_strout, env->compstr, 0, NULL);
   escape_continue ();
-
   return 0;
 }
 
@@ -548,31 +571,23 @@ int
 escape_read (int argc, char **argv, compose_env_t *env MU_ARG_UNUSED)
 {
   char *filename;
-  FILE *inf;
-  size_t size, lines;
-  char buf[512];
-
+  mu_stream_t instr;
+  int rc;
+  
   if (escape_check_args (argc, argv))
     return 1;
   filename = util_fullpath (argv[1]);
-  inf = fopen (filename, "r");
-  if (!inf)
+
+  rc = mu_file_stream_create (&instr, filename, MU_STREAM_READ);
+  if (rc)
     {
-      util_error (_("Cannot open %s: %s"), filename, mu_strerror (errno));
+      mu_error (_("Cannot open %s: %s"), filename, mu_strerror (rc));
       free (filename);
       return 1;
     }
 
-  size = lines = 0;
-  while (fgets (buf, sizeof (buf), inf))
-    {
-      lines++;
-      size += strlen (buf);
-      fputs (buf, ofile);
-    }
-  fclose (inf);
-  fprintf (stdout, "\"%s\" %lu/%lu\n", filename,
-          (unsigned long) lines, (unsigned long) size);
+  verbose_copy (env->compstr, instr, filename, NULL);
+  mu_stream_destroy (&instr);
   free (filename);
   return 0;
 }
@@ -581,9 +596,12 @@ escape_read (int argc, char **argv, compose_env_t *env 
MU_ARG_UNUSED)
 int
 escape_subj (int argc, char **argv, compose_env_t *env)
 {
+  char *buf;
   if (escape_check_args (argc, argv))
     return 1;
-  compose_header_set (env, MU_HEADER_SUBJECT, argv[1], COMPOSE_REPLACE);
+  mu_argcv_string (argc - 1, argv + 1, &buf);
+  compose_header_set (env, MU_HEADER_SUBJECT, buf, COMPOSE_REPLACE);
+  free (buf);
   return 0;
 }
 
@@ -601,34 +619,28 @@ int
 escape_write (int argc, char **argv, compose_env_t *env)
 {
   char *filename;
-  FILE *fp;
-  size_t size, lines;
-  char buf[512];
-
+  mu_stream_t wstr;
+  int rc;
+  mu_off_t size;
+  
   if (escape_check_args (argc, argv))
     return 1;
-
   filename = util_fullpath (argv[1]);
-  fp = fopen (filename, "w");  /*FIXME: check for the existence first */
-
-  if (!fp)
+  /* FIXME: check for existence first */
+  rc = mu_file_stream_create (&wstr, filename,
+                             MU_STREAM_WRITE|MU_STREAM_CREAT);
+  if (rc)
     {
-      util_error (_("Cannot open %s: %s"), filename, mu_strerror (errno));
+      mu_error (_("Cannot open %s for writing: %s"),
+                 filename, mu_strerror (rc));
       free (filename);
       return 1;
     }
 
-  rewind (env->file);
-  size = lines = 0;
-  while (fgets (buf, sizeof (buf), env->file))
-    {
-      lines++;
-      size += strlen (buf);
-      fputs (buf, fp);
-    }
-  fclose (fp);
-  fprintf (stdout, "\"%s\" %lu/%lu\n", filename,
-          (unsigned long) lines, (unsigned long) size);
+  mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+  verbose_copy (wstr, env->compstr, filename, &size);
+  mu_stream_truncate (wstr, size);
+  mu_stream_destroy (&wstr);
   free (filename);
   return 0;
 }
@@ -637,20 +649,16 @@ escape_write (int argc, char **argv, compose_env_t *env)
 int
 escape_pipe (int argc, char **argv, compose_env_t *env)
 {
+  int rc, status;
   int p[2];
   pid_t pid;
   int fd;
-
-  if (argc == 1)
-    {
-      /* TRANSLATORS: 'pipe' is a command name. Do not translate it! */
-      util_error (_("pipe: no command specified"));
-      return 1;
-    }
-
+  mu_off_t isize, osize = 0;
+  mu_stream_t tstr;
+  
   if (pipe (p))
     {
-      util_error ("pipe: %s", mu_strerror (errno));
+      mu_error ("pipe: %s", mu_strerror (errno));
       return 1;
     }
 
@@ -662,16 +670,14 @@ escape_pipe (int argc, char **argv, compose_env_t *env)
       close (p[0]);
       close (p[1]);
       close (fd);
-      util_error ("fork: %s", mu_strerror (errno));
+      mu_error ("fork: %s", mu_strerror (errno));
       return 1;
     }
   else if (pid == 0)
     {
       /* Child */
-      int i;
-      char **xargv;
 
-      /* Attache the pipes */
+      /* Attach the pipes */
       close (0);
       dup (p[0]);
       close (p[0]);
@@ -681,94 +687,61 @@ escape_pipe (int argc, char **argv, compose_env_t *env)
       dup (fd);
       close (fd);
 
-      /* Execute the process */
-      xargv = xcalloc (argc, sizeof (xargv[0]));
-      for (i = 0; i < argc - 1; i++)
-       xargv[i] = argv[i + 1];
-      xargv[i] = NULL;
-      execvp (xargv[0], xargv);
-      util_error (_("Cannot exec process `%s': %s"), xargv[0], mu_strerror 
(errno));
-      exit (1);
+      execvp (argv[1], argv + 1);
+      mu_error (_("Cannot execute `%s': %s"), argv[1], mu_strerror (errno));
+      _exit (127);
     }
-  else
-    {
-      FILE *fp;
-      char *buf = NULL;
-      size_t n;
-      size_t lines, size;
-      int rc = 1;
-      int status;
 
-      close (p[0]);
+  close (p[0]);
 
-      /* Parent */
-      fp = fdopen (p[1], "w");
-
-      fclose (env->file);
-      env->file = fopen (env->filename, "r");
+  rc = mu_stdio_stream_create (&tstr, p[1], MU_STREAM_WRITE);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", NULL, rc);
+      kill (pid, SIGKILL);
+      close (fd);
+      return rc;
+    }
 
-      lines = size = 0;
-      while (getline (&buf, &n, env->file) > 0)
-       {
-         lines++;
-         size += n;
-         fputs (buf, fp);
-       }
-      fclose (env->file);
-      fclose (fp);             /* Closes p[1] */
+  mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+  mu_stream_copy (tstr, env->compstr, 0, &isize);
+  mu_stream_destroy (&tstr);
 
-      waitpid (pid, &status, 0);
-      if (!WIFEXITED (status))
-       {
-         util_error (_("Child terminated abnormally: %d"), WEXITSTATUS 
(status));
-       }
+  waitpid (pid, &status, 0);
+  if (!WIFEXITED (status))
+    mu_error (_("Child terminated abnormally: %d"),
+               WEXITSTATUS (status));
+  else
+    {
+      struct stat st;
+      if (fstat (fd, &st))
+       mu_error (_("Cannot stat output file: %s"), mu_strerror (errno));
       else
-       {
-         struct stat st;
-         if (fstat (fd, &st))
-           {
-             util_error (_("Cannot stat output file: %s"), mu_strerror 
(errno));
-           }
-         else if (st.st_size > 0)
-           rc = 0;
-       }
+       osize = st.st_size;
+    }
 
-      fprintf (stdout, "\"|%s\" in: %lu/%lu ", argv[1],
-              (unsigned long) lines, (unsigned long) size);
+  mu_stream_printf (mu_strout, "\"|%s\" in: %lu ", argv[1],
+                   (unsigned long) isize);
+  if (osize == 0)
+    mu_stream_printf (mu_strout, _("no lines out\n"));
+  else
+    {
+      mu_stream_t str;
+      
+      mu_stream_printf (mu_strout, "out: %lu\n", (unsigned long) osize);
+      rc = mu_fd_stream_create (&str, NULL, fd,
+                               MU_STREAM_RDWR | MU_STREAM_SEEK);
       if (rc)
        {
-         fprintf (stdout, _("no lines out\n"));
+         mu_error (_("Cannot open composition stream: %s"),
+                     mu_strerror (rc));
+         close (fd);
        }
       else
        {
-         /* Ok, replace the old tempfile */
-         fp = fdopen (fd, "r");
-         rewind (fp);
-
-         env->file = fopen (env->filename, "w+");
-
-         lines = size = 0;
-         while (getline (&buf, &n, fp) > 0)
-           {
-             lines++;
-             size += n;
-             fputs (buf, env->file);
-           }
-         fclose (env->file);
-
-         fprintf (stdout, "out: %lu/%lu\n",
-                  (unsigned long) lines, (unsigned long) size);
+         mu_stream_destroy (&env->compstr);
+         env->compstr = str;
        }
-
-      /* Clean up the things */
-      if (buf)
-       free (buf);
-
-      env->file = fopen (env->filename, "a+");
-      ofile = env->file;
     }
-
-  close (fd);
-
   return 0;
 }
diff --git a/mail/file.c b/mail/file.c
index bf4acbd..73060b3 100644
--- a/mail/file.c
+++ b/mail/file.c
@@ -37,7 +37,7 @@ mail_expand_name (const char *name)
     case '#':
       if (!prev_name)
        {
-         util_error (_("No previous file"));
+         mu_error (_("No previous file"));
          return NULL;
        }
       else
@@ -47,7 +47,7 @@ mail_expand_name (const char *name)
     case '&':
       name = getenv ("MBOX");
       if (!name)
-       util_error (_("MBOX environment variable not set"));
+       mu_error (_("MBOX environment variable not set"));
       else
        name = xstrdup (name);
       break;
@@ -91,7 +91,7 @@ mail_file (int argc, char **argv)
          || (status = mu_mailbox_open (newbox, MU_STREAM_RDWR)) != 0)
        {
          mu_mailbox_destroy (&newbox);
-         util_error(_("Cannot open mailbox %s: %s"), name, mu_strerror 
(status));
+         mu_error(_("Cannot open mailbox %s: %s"), name, mu_strerror (status));
          free (name);
          return 1;
        }
@@ -126,7 +126,7 @@ mail_file (int argc, char **argv)
     }
   else
     {
-      util_error(_("%s takes only one argument"), argv[0]);
+      mu_error (_("%s takes only one argument"), argv[0]);
     }
   return 1;
 }
diff --git a/mail/folders.c b/mail/folders.c
index b21316c..2311e08 100644
--- a/mail/folders.c
+++ b/mail/folders.c
@@ -34,7 +34,7 @@ mail_folders (int argc MU_ARG_UNUSED, char **argv 
MU_ARG_UNUSED)
       char *tmp = alloca (strlen (path) + 3);
       if (!tmp)
        {
-         util_error (_("Not enough memory"));
+         mu_error (_("Not enough memory"));
          return 1;
        } 
 
diff --git a/mail/followup.c b/mail/followup.c
index c8c5e26..77f25bb 100644
--- a/mail/followup.c
+++ b/mail/followup.c
@@ -40,7 +40,7 @@ mail_followup (int argc, char **argv)
   n = get_cursor ();
   if (n == 0)
     {
-      util_error (_("No applicable message"));
+      mu_error (_("No applicable message"));
       return 1;
     }
 
@@ -77,9 +77,10 @@ mail_followup (int argc, char **argv)
 
   msgset_free (msglist);
 
-  fprintf (ofile, "To: %s\n", compose_header_get (&env, MU_HEADER_TO, ""));
-  fprintf (ofile, "Subject: %s\n\n",
-          compose_header_get (&env, MU_HEADER_SUBJECT, ""));
+  mu_printf ("To: %s\n",
+                   compose_header_get (&env, MU_HEADER_TO, ""));
+  mu_printf ("Subject: %s\n\n",
+                   compose_header_get (&env, MU_HEADER_SUBJECT, ""));
 
   status = mail_send0 (&env, mu_isupper (argv[0][0]));
   compose_destroy (&env);
diff --git a/mail/from.c b/mail/from.c
index 9515138..f8863a5 100644
--- a/mail/from.c
+++ b/mail/from.c
@@ -72,7 +72,7 @@ static void
 format_pad (size_t n)
 {
   for (; n; n--)
-    fputc (' ', ofile);
+    mu_stream_write (mu_strout, " ", 1, NULL);
 }
 
 static void
@@ -113,17 +113,17 @@ format_headline (struct header_segm *seg, msgset_t 
*mspec, mu_message_t msg)
       if (seg->align == ALIGN_RIGHT)
        {
          format_pad (width - len);
-         fprintf (ofile, "%*.*s", (int) len, (int) len, p);
+         mu_printf ("%*.*s", (int) len, (int) len, p);
        }
       else
        {
-         fprintf (ofile, "%*.*s", (int) len, (int) len, p);
+         mu_printf ("%*.*s", (int) len, (int) len, p);
          format_pad (width - len);
        }
       out_cols += width;
     }
 
-  fprintf (ofile, "\n");
+  mu_printf ("\n");
   free (args.buf);
 }    
 
diff --git a/mail/if.c b/mail/if.c
index 12c6744..8fe087a 100644
--- a/mail/if.c
+++ b/mail/if.c
@@ -52,7 +52,7 @@ _cond_push(int val)
 
   if (!_cond_stack)
     {
-      util_error(_("Not enough memory"));
+      mu_error(_("Not enough memory"));
       exit (EXIT_FAILURE);
     }
   _cond_stack[_cond_level++] = val;
@@ -63,7 +63,7 @@ _cond_pop()
 {
   if (_cond_level == 0)
     {
-      util_error(_("Internal error: condition stack underflow"));
+      mu_error(_("Internal error: condition stack underflow"));
       abort();
     }
   return _cond_stack[--_cond_level];
@@ -86,13 +86,13 @@ mail_if (int argc, char **argv)
   if (argc != 2)
     {
       /* TRANSLATORS: 'if' is the function name. Do not translate it */
-      util_error(_("if requires an argument: s | r | t"));
+      mu_error(_("if requires an argument: s | r | t"));
       return 1;
     }
 
   if (argv[1][1] != 0)
     {
-      util_error(_("Valid if arguments are: s | r | t"));
+      mu_error(_("Valid if arguments are: s | r | t"));
       return 1;
     }
 
@@ -116,7 +116,7 @@ mail_if (int argc, char **argv)
          cond = isatty (fileno (stdout));
          break;
        default:
-         util_error(_("Valid if arguments are: s | r | t"));
+         mu_error(_("Valid if arguments are: s | r | t"));
          return 1;
        }
     }
@@ -133,7 +133,7 @@ mail_else (int argc MU_ARG_UNUSED, char **argv 
MU_ARG_UNUSED)
   if (_cond_level == 0)
     {
       /* TRANSLATORS: 'else' and 'if' are function names. Do not translate 
them */
-      util_error(_("else without matching if"));
+      mu_error(_("else without matching if"));
       return 1;
     }
   cond = _cond_pop();
@@ -149,7 +149,7 @@ mail_endif (int argc MU_ARG_UNUSED, char **argv 
MU_ARG_UNUSED)
   if (_cond_level == 0)
     {
       /* TRANSLATORS: 'endif' and 'if' are function names. Do not translate 
them */
-      util_error(_("endif without matching if"));
+      mu_error (_("endif without matching if"));
       return 1;
     }
   _cond_pop();
diff --git a/mail/inc.c b/mail/inc.c
index a9dec14..c5f1123 100644
--- a/mail/inc.c
+++ b/mail/inc.c
@@ -27,10 +27,10 @@ mail_inc (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
   if (!mu_mailbox_is_updated (mbox))
     {
       mu_mailbox_messages_count (mbox, &total);
-      fprintf (ofile, _("New mail has arrived.\n"));
+      mu_printf (_("New mail has arrived.\n"));
     }
   else
-    fprintf (ofile, _("No new mail for %s\n"), mail_whoami());
+    mu_printf (_("No new mail for %s\n"), mail_whoami ());
 
   return 0;
 }
diff --git a/mail/mail.c b/mail/mail.c
index adf207c..6cc8496 100644
--- a/mail/mail.c
+++ b/mail/mail.c
@@ -21,7 +21,6 @@
 /* Global variables and constants*/
 mu_mailbox_t mbox;            /* Mailbox being operated upon */
 size_t total;                 /* Total number of messages in the mailbox */
-FILE *ofile;                  /* Output file */
 int interactive;              /* Is the session interactive */  
 
 static mu_list_t command_list;   /* List of commands to be executed after 
parsing
@@ -221,20 +220,20 @@ mail_cmdline (void *closure, int cont MU_ARG_UNUSED)
        {
          mu_mailbox_messages_count (mbox, &total);
          page_invalidate (0);
-         fprintf (ofile, _("New mail has arrived.\n"));
+         mu_printf (_("New mail has arrived.\n"));
        }
 
       rc = ml_readline (prompt);
       
       if (ml_got_interrupt ())
        {
-         util_error (_("Interrupt"));
+         mu_error (_("Interrupt"));
          continue;
        }
 
       if (!rc && mailvar_get (NULL, "ignoreeof", mailvar_type_boolean, 0) == 0)
        {
-         util_error (_("Use \"quit\" to quit."));
+         mu_error (_("Use \"quit\" to quit."));
          continue;
        }
 
@@ -324,7 +323,7 @@ main (int argc, char **argv)
   struct arguments args;
   int i, rc;
   
-  ofile = stdout;
+  mu_stdstream_setup ();
   set_cursor (1);
 
   /* Native Language Support */
@@ -399,7 +398,18 @@ main (int argc, char **argv)
   util_run_cached_commands (&command_list);
 
   if (interactive)
-    /* nothing? */;
+    {
+      /* Reset standard error stream so that it does not print program
+        name before the actual diagnostic message. */
+      mu_stream_t errstr;
+      int rc = mu_stdstream_strerr_create (&errstr, MU_STRERR_STDERR, 0, 0,
+                                          NULL, NULL);
+      if (rc == 0)
+       {
+         mu_stream_destroy (&mu_strerr);
+         mu_strerr = errstr;
+       }
+    }
   else
     {
       util_do_command ("set nocrt");
@@ -433,10 +443,10 @@ main (int argc, char **argv)
       if ((rc = mu_mailbox_create_default (&mbox, args.file)) != 0)
        {
          if (args.file)
-           util_error (_("Cannot create mailbox %s: %s"), args.file,
+           mu_error (_("Cannot create mailbox %s: %s"), args.file,
                        mu_strerror (rc));
          else
-           util_error (_("Cannot create mailbox: %s"),
+           mu_error (_("Cannot create mailbox: %s"),
                        mu_strerror (rc));
          exit (EXIT_FAILURE);
        }
@@ -445,7 +455,7 @@ main (int argc, char **argv)
        {
          mu_url_t url = NULL;
          mu_mailbox_get_url (mbox, &url);
-         util_error (_("Cannot open mailbox %s: %s"),
+         mu_error (_("Cannot open mailbox %s: %s"),
                      mu_url_to_string (url), mu_strerror (rc));
          mu_mailbox_destroy (&mbox);
        }
@@ -458,7 +468,7 @@ main (int argc, char **argv)
            {
              mu_url_t url = NULL;
              mu_mailbox_get_url (mbox, &url);
-             util_error (_("Cannot read mailbox %s: %s"),
+             mu_error (_("Cannot read mailbox %s: %s"),
                          mu_url_to_string (url), mu_strerror (rc));
              exit (EXIT_FAILURE);
            }
@@ -474,7 +484,7 @@ main (int argc, char **argv)
            do_and_quit ("from *");
          else if (strcmp (mode, "read"))
            {
-             util_error (_("Unknown mode `%s'"), mode);
+             mu_error (_("Unknown mode `%s'"), mode);
              util_do_command ("quit");
              return 1;
            }
@@ -485,10 +495,10 @@ main (int argc, char **argv)
              || mailvar_get (NULL, "emptystart", mailvar_type_boolean, 0)))
         {
          if (args.file)
-           fprintf (ofile, _("%s: 0 messages\n"), args.file);
+           mu_printf (_("%s: 0 messages\n"), args.file);
          else
-           fprintf (ofile, _("No mail for %s\n"),
-                    args.user ? args.user : mail_whoami ());
+           mu_printf (_("No mail for %s\n"),
+                             args.user ? args.user : mail_whoami ());
           return 1;
         }
 
@@ -501,7 +511,7 @@ main (int argc, char **argv)
 
       mailvar_get (&prompt, "prompt", mailvar_type_string, 0);
       mail_mainloop (mail_cmdline, (void*) prompt, 1);
-      fprintf (ofile, "\n");
+      mu_printf ("\n");
       util_do_command ("quit");
       return 0;
     }
@@ -551,11 +561,11 @@ mail_mainloop (char *(*input) (void *, int),
 int
 mail_warranty (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
 {
-  fputs (_("GNU Mailutils -- a suite of utilities for electronic mail\n"
+  mu_printf (
+        _("GNU Mailutils -- a suite of utilities for electronic mail\n"
            "Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,\n"
-           "2007, 2009 Free Software Foundation, Inc.\n\n"),
-           ofile);
-  fputs (
+           "2007, 2009, 2010 Free Software Foundation, Inc.\n\n"));
+  mu_printf (
   _("   GNU Mailutils is free software; you can redistribute it and/or 
modify\n"
     "   it under the terms of the GNU General Public License as published by\n"
     "   the Free Software Foundation; either version 3 of the License, or\n"
@@ -570,8 +580,7 @@ mail_warranty (int argc MU_ARG_UNUSED, char **argv 
MU_ARG_UNUSED)
     "   with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.\n" 
     "\n"
     "\n"
-),
-    ofile);
+));
 
   return 0;
 }
diff --git a/mail/mail.h b/mail/mail.h
index 4857717..f2bb9ca 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -102,9 +102,7 @@ typedef int function_t (int, char **);
 typedef struct compose_env
 {
   mu_header_t header;   /* The message headers */
-  char *filename;    /* Name of the temporary compose file */
-  FILE *file;        /* Temporary compose file */
-  FILE *ofile;       /* Diagnostics output channel */
+  mu_stream_t compstr;    /* Temporary compose stream */
   char **outfiles;   /* Names of the output files. The message is to be
                        saved in each of these. */
   int nfiles;        /* Number of output files */
@@ -174,7 +172,6 @@ typedef int (*msg_handler_t) (msgset_t *mp, mu_message_t 
mesg, void *data);
 /* Global variables and constants*/
 extern mu_mailbox_t mbox;
 extern size_t total;
-extern FILE *ofile;
 extern int interactive;
 extern const char *program_version;
 
@@ -358,7 +355,7 @@ extern int mailvar_get (void *ptr, const char *variable,
                        enum mailvar_type type, int warn);
 
 extern void mailvar_print (int set);
-extern void mailvar_variable_format (FILE *fp,
+extern void mailvar_variable_format (mu_stream_t,
                                     const struct mailvar_variable *,
                                     const char *defval);
 
@@ -382,7 +379,6 @@ extern char *util_slist_to_string (mu_list_t list, const 
char *delim);
 extern void util_strcat (char **dest, const char *str);
 extern char *util_outfolder_name (char *str);
 extern void util_save_outgoing (mu_message_t msg, char *savefile);
-extern void util_error (const char *format, ...) MU_PRINTFLIKE(1,2);
 extern int util_error_range (size_t msgno);
 extern void util_noapp (void);
 extern int util_tempfile (char **namep);
@@ -403,7 +399,9 @@ void util_mark_read (mu_message_t msg);
 
 const char *util_url_to_string (mu_url_t url);
 
-size_t fprint_msgset (FILE *fp, const msgset_t *msgset);
+mu_stream_t open_pager (size_t lines);
+
+void format_msgset (mu_stream_t str, const msgset_t *msgset, size_t *count);
 
 int is_address_field (const char *name);
 
diff --git a/mail/mailline.c b/mail/mailline.c
index c420757..e92459f 100644
--- a/mail/mailline.c
+++ b/mail/mailline.c
@@ -118,58 +118,24 @@ ml_readline_init ()
 char *
 ml_readline_internal ()
 {
-  char *line;
-  char *p;
-  size_t alloclen, linelen;
-
-  p = line = xcalloc (1, 255);
-  alloclen = 255;
-  linelen = 0;
-  for (;;)
+  char *buf = NULL;
+  size_t size = 0, n;
+  int rc;
+  
+  rc = mu_stream_getline (mu_strin, &buf, &size, &n);
+  if (rc)
     {
-      size_t n;
-
-      p = fgets (p, alloclen - linelen, stdin);
-
-      if (p)
-       n = strlen(p);
-      else if (_interrupted)
-       {
-         free (line);
-         return NULL;
-       }
-      else
-       n = 0;
-
-      linelen += n;
-
-      /* Error.  */
-      if (linelen == 0)
-       {
-         free (line);
-         return NULL;
-       }
-
-      /* Ok.  */
-      if (line[linelen - 1] == '\n')
-       {
-         line[linelen - 1] = '\0';
-         return line;
-       }
-      else
-        {
-         char *tmp;
-         alloclen *= 2;
-         tmp = realloc (line, alloclen);
-         if (tmp == NULL)
-           {
-             free (line);
-             return NULL;
-           }
-         line = tmp;
-         p = line + linelen;
-       }
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_getline", NULL, rc);
+      return NULL;
     }
+  if (_interrupted)
+    {
+      free (buf);
+      return NULL;
+    }
+  if (n == 0)
+    return NULL;
+  return buf;
 }
 
 char *
@@ -185,7 +151,7 @@ ml_readline_with_intr (const char *prompt)
 {
   char *str = ml_readline (prompt);
   if (_interrupted)
-    printf ("\n");
+    mu_printf ("\n");
   return str;
 }
 
@@ -816,7 +782,7 @@ ml_reread (const char *prompt, char **text)
 
   if (!line)
     {
-      util_error (_("Not enough memory to edit the line"));
+      mu_error (_("Not enough memory to edit the line"));
       return -1;
     }
 
@@ -844,7 +810,7 @@ ml_reread (const char *prompt, char **text)
          if ((p = realloc (line, line_size + LINE_INC)) == NULL)
            {
              fputs ("\n", stdout);
-             util_error (_("Not enough memory to edit the line"));
+             mu_error (_("Not enough memory to edit the line"));
              break;
            }
          else
@@ -891,7 +857,7 @@ ml_reread (const char *prompt, char **text)
              if ((p = realloc (line, line_size + LINE_INC)) == NULL)
                {
                  fputs ("\n", stdout);
-                 util_error (_("Not enough memory to edit the line"));
+                 mu_error (_("Not enough memory to edit the line"));
                  break;
                }
              else
@@ -927,7 +893,7 @@ ml_reread (const char *prompt, char **text)
          if ((p = realloc (line, line_size + LINE_INC)) == NULL)
            {
              fputs ("\n", stdout);
-             util_error (_("Not enough memory to edit the line"));
+             mu_error (_("Not enough memory to edit the line"));
              break;
            }
          else
@@ -959,8 +925,8 @@ readline (char *prompt)
 {
   if (prompt)
     {
-      fprintf (ofile, "%s", prompt);
-      fflush (ofile);
+      mu_printf ("%s", prompt);
+      mu_stream_flush (mu_strout);
     }
 
   return ml_readline_internal ();
diff --git a/mail/mailvar.c b/mail/mailvar.c
index 2edbd2e..5c94597 100644
--- a/mail/mailvar.c
+++ b/mail/mailvar.c
@@ -285,21 +285,27 @@ find_mailvar_symbol (const char *var)
 }
 
 static void
-print_descr (FILE *out, const char *s, int n,
+print_descr (mu_stream_t out, const char *s, int n,
             int doc_col, int rmargin, char *pfx)
 {
+  mu_stream_stat_buffer stat;
+  
   if (!s)
     return;
+  
+  mu_stream_set_stat (out, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT),
+                     stat);
+  stat[MU_STREAM_STAT_OUT] = n;
   do
     {
       const char *p;
       const char *space = NULL;
 
-      if (n == 1 && pfx)
-       n += fprintf (out, "%s", pfx);
+      if (stat[MU_STREAM_STAT_OUT] && pfx)
+       mu_stream_printf (out, "%s", pfx);
       
-      for (; n < doc_col; n++)
-       fputc (' ', out);
+      while (stat[MU_STREAM_STAT_OUT] < doc_col)
+       mu_stream_write (out, " ", 1, NULL);
 
       for (p = s; *p && p < s + (rmargin - doc_col); p++)
        if (mu_isspace (*p))
@@ -307,20 +313,21 @@ print_descr (FILE *out, const char *s, int n,
       
       if (!space || p < s + (rmargin - doc_col))
        {
-         fprintf (out, "%s", s);
+         mu_stream_printf (out, "%s", s);
          s += strlen (s);
        }
       else
        {
          for (; s < space; s++)
-           fputc (*s, out);
+           mu_stream_write (out, s, 1, NULL);
          for (; *s && mu_isspace (*s); s++)
            ;
        }
-      fputc ('\n', out);
-      n = 1;
+      mu_stream_printf (out, "\n");
+      stat[MU_STREAM_STAT_OUT] = 1;
     }
   while (*s);
+  mu_stream_set_stat (out, 0, NULL);
 }
 
 /* Functions for dealing with internal mailvar_list variables */
@@ -409,7 +416,7 @@ mailvar_get (void *ptr, const char *variable, enum 
mailvar_type type, int warn)
   if (!var->set || var->type != type)
     {
       if (warn)
-       util_error (_("No value set for \"%s\""), variable);
+       mu_error (_("No value set for \"%s\""), variable);
       return 1;
     }
   if (ptr)
@@ -680,17 +687,15 @@ void
 mailvar_print (int set)
 {
   struct mailvar_variable **vartab;
-  FILE *out = ofile;
+  mu_stream_t out;
   size_t i, count;
-  int pagelines = util_get_crt ();
   int width = util_getcols ();
   int prettyprint = mailvar_get (NULL, "variable-pretty-print",
                                 mailvar_type_boolean, 0) == 0;
   
   vartab = mailvar_make_array (set, &count);
 
-  if (pagelines && count > pagelines)
-    out = popen (getenv ("PAGER"), "w");
+  out = open_pager (count);
 
   for (i = 0; i < count; i++)
     {
@@ -704,40 +709,41 @@ mailvar_print (int set)
              if (sym->flags & MAILVAR_HIDDEN)
                continue;
              if (sym->flags & MAILVAR_RDONLY)
-               fprintf (out, "# %s:\n", _("Read-only variable"));
+               mu_stream_printf (out, "# %s:\n", _("Read-only variable"));
              print_descr (out, gettext (sym->descr), 1, 3, width - 1, "# ");
            }
        }
       switch (vartab[i]->type)
        {
        case mailvar_type_number:
-         fprintf (out, "%s=%d", vartab[i]->name, vartab[i]->value.number);
+         mu_stream_printf (out, "%s=%d",
+                           vartab[i]->name, vartab[i]->value.number);
          break;
          
        case mailvar_type_string:
-         fprintf (out, "%s=\"%s\"", vartab[i]->name, vartab[i]->value.string);
+         mu_stream_printf (out, "%s=\"%s\"",
+                           vartab[i]->name, vartab[i]->value.string);
          break;
          
        case mailvar_type_boolean:
          if (!vartab[i]->value.bool)
-           fprintf (out, "no");
-         fprintf (out, "%s", vartab[i]->name);
+           mu_stream_printf (out, "no");
+         mu_stream_printf (out, "%s", vartab[i]->name);
          break;
          
        case mailvar_type_whatever:
-         fprintf (out, "%s %s", vartab[i]->name, _("oops?"));
+         mu_stream_printf (out, "%s %s", vartab[i]->name, _("oops?"));
        }
-      fprintf (out, "\n");
+      mu_stream_printf (out, "\n");
     }
   free (vartab);
 
-  if (out != ofile)
-    pclose (out);
+  mu_stream_unref (out);
 }
 
 
 void
-mailvar_variable_format (FILE *fp,
+mailvar_variable_format (mu_stream_t stream,
                         const struct mailvar_variable *var,
                         const char *defval)
 {
@@ -745,20 +751,20 @@ mailvar_variable_format (FILE *fp,
     switch (var->type)
       {
       case mailvar_type_string:
-       fprintf (fp, "%s", var->value.string);
+       mu_stream_printf (stream, "%s", var->value.string);
        break;
 
       case mailvar_type_number:
-       fprintf (fp, "%d", var->value.number);
+       mu_stream_printf (stream, "%d", var->value.number);
        break;
 
       case mailvar_type_boolean:
-       fprintf (fp, "%s", var->set ? "yes" : "no");
+       mu_stream_printf (stream, "%s", var->set ? "yes" : "no");
        break;
 
       default:
        if (defval)
-         fprintf (fp, "%s", defval);
+         mu_stream_printf (stream, "%s", defval);
        break;
       }
 }
@@ -773,45 +779,51 @@ static char *typestr[] =
   };
 
 static void
-describe_symbol (FILE *out, int width, const struct mailvar_symbol *sym)
+describe_symbol (mu_stream_t out, int width, const struct mailvar_symbol *sym)
 {
-  int n;
   int i, t;
   const struct mailvar_symbol *ali;
+  mu_stream_stat_buffer stat;
 
-  n = fprintf (out, "%s", sym->var.name);
+  mu_stream_set_stat (out, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT),
+                     stat);
+  mu_stream_printf (out, "%s", sym->var.name);
   for (ali = sym + 1; ali->var.name && ali->flags & MAILVAR_ALIAS; ali++)
     {
       size_t len = strlen (ali->var.name) + 2;
-      if (n + len > width)
-       n = fprintf (out, "\n%s", ali->var.name);
+      if (stat[MU_STREAM_STAT_OUT] + len > width)
+       {
+         stat[MU_STREAM_STAT_OUT] = 0;
+         mu_stream_printf (out, "\n%s", ali->var.name);
+       }
       else
-       n = fprintf (out, ", %s", ali->var.name);
+       mu_stream_printf (out, ", %s", ali->var.name);
     }
-  fputc ('\n', out);
+  mu_stream_printf (out, "\n");
+  mu_stream_set_stat (out, 0, NULL);
   
-  fprintf (out, _("Type: "));
+  mu_stream_printf (out, _("Type: "));
   for (i = 0, t = 0; i < sizeof (typestr) / sizeof (typestr[0]); i++)
     if (sym->flags & MAILVAR_TYPEMASK (i))
       {
        if (t++)
-         fprintf (out, " %s ", _("or"));
-       fprintf (out, "%s", gettext (typestr[i]));
+         mu_stream_printf (out, " %s ", _("or"));
+       mu_stream_printf (out, "%s", gettext (typestr[i]));
       }
   if (!t)
-    fprintf (out, "%s", gettext (typestr[0]));
-  fputc ('\n', out);
+    mu_stream_printf (out, "%s", gettext (typestr[0]));
+  mu_stream_printf (out, "\n");
   
-  fprintf (out, "%s", _("Current value: "));
+  mu_stream_printf (out, "%s", _("Current value: "));
   mailvar_variable_format (out, &sym->var, _("[not set]"));
 
   if (sym->flags & MAILVAR_RDONLY)
-    fprintf (out, " [%s]", _("read-only"));
-  fputc ('\n', out);
+    mu_stream_printf (out, " [%s]", _("read-only"));
+  mu_stream_printf (out, "\n");
   
   print_descr (out, gettext (sym->descr ? sym->descr : N_("Not documented")),
               1, 1, width - 1, NULL);
-  fputc ('\n', out);
+  mu_stream_printf (out, "\n");
 }
 
 int
@@ -819,10 +831,7 @@ mail_variable (int argc, char **argv)
 {
   int pagelines = util_get_crt ();
   int width = util_getcols ();
-  FILE *out = ofile;
-
-  if (pagelines)
-    out = popen (getenv ("PAGER"), "w");
+  mu_stream_t out = open_pager (pagelines + 1);
   
   if (argc == 1)
     {
@@ -840,13 +849,12 @@ mail_variable (int argc, char **argv)
        {
          struct mailvar_symbol *sym = find_mailvar_symbol (argv[i]);
          if (!sym)
-           fprintf (out, "%s: unknown\n", argv[i]);
+           mu_stream_printf (out, "%s: unknown\n", argv[i]);
          else
            describe_symbol (out, width, sym);
        }
     }
-  if (out != ofile)
-    pclose (out);
+  mu_stream_unref (out);
   return 0;
 }
 
diff --git a/mail/msgset.y b/mail/msgset.y
index 8f6ae9d..b7b6148 100644
--- a/mail/msgset.y
+++ b/mail/msgset.y
@@ -241,21 +241,21 @@ static char *cur_p;
 int
 yyerror (const char *s)
 {
-  fprintf (stderr, "%s: ", xargv[0]);
-  fprintf (stderr, "%s", s);
+  mu_stream_printf (mu_strerr, "%s: ", xargv[0]);
+  mu_stream_printf (mu_strerr, "%s", s);
   if (!cur_p)
-    fprintf (stderr, _(" near end"));
+    mu_stream_printf (mu_strerr, _(" near end"));
   else if (*cur_p == 0)
     {
       int i =  (*cur_p == 0) ? cur_ind + 1 : cur_ind;
       if (i == xargc)
-       fprintf (stderr, _(" near end"));
+       mu_stream_printf (mu_strerr, _(" near end"));
       else
-       fprintf (stderr, _(" near %s"), xargv[i]);
+       mu_stream_printf (mu_strerr, _(" near %s"), xargv[i]);
     }
   else
-    fprintf (stderr, _(" near %s"), cur_p);
-  fprintf (stderr, "\n");
+    mu_stream_printf (mu_strerr, _(" near %s"), cur_p);
+  mu_stream_printf (mu_strerr, "\n");
   return 0;
 }
 
@@ -727,7 +727,7 @@ check_set (msgset_t **pset)
                }
              else
                {
-                 util_error (_("%lu: Inappropriate message (has been 
deleted)"),
+                 mu_error (_("%lu: Inappropriate message (has been deleted)"),
                              (unsigned long) p->msg_part[0]);
                  /* Delete entire set */
                  delset = *pset;
@@ -756,13 +756,13 @@ void
 msgset_print (msgset_t *mset)
 {
   int i;
-  printf ("(");
-  printf ("%d .", mset->msg_part[0]);
+  mu_printf ("(");
+  mu_printf ("%d .", mset->msg_part[0]);
   for (i = 1; i < mset->npart; i++)
     {
-      printf (" %d", mset->msg_part[i]);
+      mu_printf (" %d", mset->msg_part[i]);
     }
-  printf (")\n");
+  mu_printf (")\n");
 }
 
 int
diff --git a/mail/next.c b/mail/next.c
index aea6367..61b665a 100644
--- a/mail/next.c
+++ b/mail/next.c
@@ -36,7 +36,7 @@ mail_next (int argc, char **argv)
       n = get_cursor ();
       if (n == 0 || util_get_message (mbox, n, &msg))
        {
-         util_error (_("No applicable message"));
+         mu_error (_("No applicable message"));
          return 1;
        }
 
@@ -59,7 +59,7 @@ mail_next (int argc, char **argv)
 
       if (rc)
        {
-         util_error (_("No applicable message"));
+         mu_error (_("No applicable message"));
          return 1;
        }
     }
@@ -76,7 +76,7 @@ mail_next (int argc, char **argv)
        }
       else
        {
-         util_error (_("No applicable message"));
+         mu_error (_("No applicable message"));
          return 1;
        }
     }
diff --git a/mail/previous.c b/mail/previous.c
index 81ca149..2c4bd41 100644
--- a/mail/previous.c
+++ b/mail/previous.c
@@ -45,7 +45,7 @@ mail_previous (int argc, char **argv)
 
       if (rc)
        {
-         util_error (_("No applicable message"));
+         mu_error (_("No applicable message"));
          return 1;
        }
     }
@@ -62,7 +62,7 @@ mail_previous (int argc, char **argv)
        }
       else
        {
-         util_error (_("No applicable message"));
+         mu_error (_("No applicable message"));
          return 1;
        }
     }
diff --git a/mail/print.c b/mail/print.c
index d851908..50011fc 100644
--- a/mail/print.c
+++ b/mail/print.c
@@ -30,9 +30,8 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void 
*data)
   mu_header_t hdr;
   mu_body_t body;
   mu_stream_t stream;
-  char buffer[512];
-  size_t n = 0, lines = 0;
-  FILE *out = ofile;
+  size_t lines = 0;
+  mu_stream_t out;
   int pagelines = util_get_crt ();
   int status;
   
@@ -56,8 +55,7 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void 
*data)
        }
     }
 
-  if (pagelines && lines > pagelines)
-    out = popen (getenv ("PAGER"), "w");
+  out = open_pager (lines);
 
   if (mailvar_get (NULL, "showenvelope", mailvar_type_boolean, 0) == 0)
     print_envelope (mspec, mesg, "From");
@@ -77,16 +75,16 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void 
*data)
            continue;
          if (mail_header_is_visible (sptr))
            {
-             fprintf (out, "%s: ", sptr);
+             mu_stream_printf (out, "%s: ", sptr);
              mu_header_aget_field_value (hdr, i, &tmp);
              if (mail_header_is_unfoldable (sptr))
                mu_string_unfold (tmp, NULL);
              util_rfc2047_decode (&tmp);
-             fprintf (out, "%s\n", tmp);
+             mu_stream_printf (out, "%s\n", tmp);
              free (tmp);
            }
        }
-      fprintf (out, "\n");
+      mu_stream_printf (out, "\n");
       mu_message_get_body (mesg, &body);
       status = mu_body_get_streamref (body, &stream);
     }
@@ -96,26 +94,20 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void 
*data)
   if (status)
     {
       mu_error (_("get_stream error: %s"), mu_strerror (status));
-      if (out != ofile)
-       pclose (out);
+      mu_stream_unref (out);
       return 0;
     }
 
-  /* FIXME: Use mu_stream_copy instead? */
-  while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0
-        && n != 0)
-    {
+  mu_stream_copy (out, stream, 0, NULL);
+  /* FIXME:
       if (ml_got_interrupt())
        {
-         util_error (_("\nInterrupt"));
+         mu_error (_("\nInterrupt"));
          break;
        }
-      buffer[n] = '\0';
-      fprintf (out, "%s", buffer);
-    }
+  */
   mu_stream_destroy (&stream);
-  if (out != ofile)
-    pclose (out);
+  mu_stream_destroy (&out);
   
   util_mark_read (mesg);
 
diff --git a/mail/quit.c b/mail/quit.c
index 9632c72..93628ef 100644
--- a/mail/quit.c
+++ b/mail/quit.c
@@ -49,7 +49,7 @@ mail_mbox_close ()
   
   mu_mailbox_get_url (mbox, &url);
   mu_mailbox_messages_count (mbox, &held_count);
-  fprintf (ofile, 
+  mu_printf (
            ngettext ("Held %d message in %s\n",
                      "Held %d messages in %s\n",
                      held_count),
@@ -116,14 +116,14 @@ mail_mbox_commit ()
               
              if ((status = mu_mailbox_create_default (&dest_mbox, name)) != 0)
                {
-                 util_error (_("Cannot create mailbox %s: %s"), name,
+                 mu_error (_("Cannot create mailbox %s: %s"), name,
                               mu_strerror (status));
                  return 1;
                }
               if ((status = mu_mailbox_open (dest_mbox,
                                          MU_STREAM_WRITE | 
MU_STREAM_CREAT))!=0)
                {
-                 util_error (_("Cannot open mailbox %s: %s"), name,
+                 mu_error (_("Cannot open mailbox %s: %s"), name,
                               mu_strerror (status));
                  return 1;
                }
@@ -131,7 +131,7 @@ mail_mbox_commit ()
 
          status = mu_mailbox_append_message (dest_mbox, msg);
          if (status)
-           util_error (_("Cannot append message: %s"), mu_strerror (status));
+           mu_error (_("Cannot append message: %s"), mu_strerror (status));
          else
            {
              mu_attribute_set_deleted (attr);
@@ -153,7 +153,7 @@ mail_mbox_commit ()
       mu_url_t u = NULL;
 
       mu_mailbox_get_url (dest_mbox, &u);
-      fprintf(ofile, 
+      mu_printf (
               ngettext ("Saved %d message in %s\n",
                         "Saved %d messages in %s\n",
                        saved_count),
diff --git a/mail/reply.c b/mail/reply.c
index ff5e8af..4f980f1 100644
--- a/mail/reply.c
+++ b/mail/reply.c
@@ -21,7 +21,7 @@ void
 make_in_reply_to (compose_env_t *env, mu_message_t msg)
 {
   char *value = NULL;
-
+  wd();
   mu_rfc2822_in_reply_to (msg, &value);
   compose_header_set (env, MU_HEADER_IN_REPLY_TO, value,
                      COMPOSE_REPLACE);
@@ -111,13 +111,13 @@ reply0 (msgset_t *mspec, mu_message_t msg, void *data)
   else
     compose_header_set (&env, MU_HEADER_SUBJECT, "", COMPOSE_REPLACE);
 
-  fprintf (ofile, "To: %s\n",
+  mu_printf ("To: %s\n",
           compose_header_get (&env, MU_HEADER_TO, ""));
   str = compose_header_get (&env, MU_HEADER_CC, NULL);
   if (str)
-    fprintf (ofile, "Cc: %s\n", str);
-  fprintf (ofile, "Subject: %s\n\n",
-          compose_header_get (&env, MU_HEADER_SUBJECT, ""));
+    mu_printf ("Cc: %s\n", str);
+  mu_printf ("Subject: %s\n\n",
+                   compose_header_get (&env, MU_HEADER_SUBJECT, ""));
   
   make_in_reply_to (&env, msg);
   make_references (&env, msg);
@@ -138,3 +138,9 @@ mail_reply (int argc, char **argv)
   return util_foreach_msg (argc, argv, MSG_NODELETED, reply0, &lower);
 }
 
+wd()
+{
+  int volatile _st=1;
+  while (!_st)
+    _st=_st;
+}
diff --git a/mail/retain.c b/mail/retain.c
index 08d76a8..4b1b567 100644
--- a/mail/retain.c
+++ b/mail/retain.c
@@ -31,7 +31,7 @@ process_list (int argc, char **argv,
   if (argc == 1)
     {
       if (mu_list_is_empty (*list))
-       fprintf (ofile, _(msg));
+       mu_printf ("%s", _(msg));
       else
        util_slist_print (*list, 1);
       return 0;
@@ -125,7 +125,8 @@ mail_nosender (int argc, char **argv)
   if (argc == 1)
     {
       util_slist_destroy (&sender_headers);
-      fprintf (ofile, _("Sender address is obtained from the envelope\n"));
+      mu_printf (
+                       _("Sender address is obtained from the envelope\n"));
     }
   else 
     while (--argc)
diff --git a/mail/send.c b/mail/send.c
index 6d3e42a..17476d0 100644
--- a/mail/send.c
+++ b/mail/send.c
@@ -52,7 +52,7 @@ list_headers (void *item, void *data)
 
   if (!name || strcmp (name, hp->name) == 0)
     {
-      printf ("%s: %s\n", hp->name, hp->value);
+      mu_printf ("%s: %s\n", hp->name, hp->value);
     }
   return 0;
 }
@@ -67,7 +67,7 @@ add_header (char *name, char *value, int mode)
       int rc = mu_list_create (&add_header_list);
       if (rc)
        {
-         util_error (_("Cannot create header list: %s"), mu_strerror (rc));
+         mu_error (_("Cannot create header list: %s"), mu_strerror (rc));
          exit (1);
        }
     }
@@ -89,7 +89,7 @@ send_append_header (char *text)
   p = strchr (text, ':');
   if (!p)
     {
-      util_error (_("Invalid header: %s"), text);
+      mu_error (_("Invalid header: %s"), text);
       return;
     }
   len = p - text;
@@ -223,7 +223,7 @@ compose_header_set (compose_env_t * env, const char *name,
   if (!env->header
       && (status = mu_header_create (&env->header, NULL, 0)) != 0)
     {
-      util_error (_("Cannot create header: %s"), mu_strerror (status));
+      mu_error (_("Cannot create header: %s"), mu_strerror (status));
       return status;
     }
 
@@ -333,7 +333,7 @@ fill_body (mu_message_t msg, mu_stream_t instr)
        {
          char *str;
          if (mailvar_get (&str, "nullbodymsg", mailvar_type_string, 0) == 0)
-           util_error ("%s\n", _(str));
+           mu_error ("%s\n", _(str));
        }
       else
        return 1;
@@ -347,27 +347,27 @@ save_dead_message (compose_env_t *env)
 {
   if (mailvar_get (NULL, "save", mailvar_type_boolean, 0) == 0)
     {
-      FILE *fp = fopen (getenv ("DEAD"),
-                       mailvar_get (NULL, "appenddeadletter",
-                                    mailvar_type_boolean, 0) == 0 ?
-                       "a" : "w");
-      
-      if (!fp)
+      mu_stream_t dead_letter;
+      int rc;
+      const char *name = getenv ("DEAD");
+
+      /* FIXME: Use MU_STREAM_APPEND if appenddeadletter, instead of the
+        stream manipulations below */
+      rc = mu_file_stream_create (&dead_letter, name, MU_STREAM_WRITE);
+      if (rc)
        {
-         util_error (_("Cannot open file %s: %s"), getenv ("DEAD"),
-                     strerror (errno));
+         mu_error (_("Cannot open file %s: %s"), name, strerror (rc));
          return 1;
        }
+      if (mailvar_get (NULL, "appenddeadletter",
+                      mailvar_type_boolean, 0) == 0)
+       mu_stream_seek (dead_letter, 0, MU_SEEK_END, NULL);
       else
-       {
-         char *buf = NULL;
-         size_t n;
-         rewind (env->file);
-         while (getline (&buf, &n, env->file) > 0)
-           fputs (buf, fp);
-         fclose (fp);
-         free (buf);
-       }
+       mu_stream_truncate (dead_letter, 0);
+
+      mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+      mu_stream_copy (dead_letter, env->compstr, 0, NULL);
+      mu_stream_destroy (&dead_letter);
     }
   return 0;
 }
@@ -401,17 +401,17 @@ send_message (mu_message_t msg)
                  mu_mailer_close (mailer);
                }
              else
-               util_error (_("Cannot open mailer: %s"), mu_strerror (status));
+               mu_error (_("Cannot open mailer: %s"), mu_strerror (status));
              mu_mailer_destroy (&mailer);
            }
          else
-           util_error (_("Cannot create mailer: %s"),
+           mu_error (_("Cannot create mailer: %s"),
                        mu_strerror (status));
        }
     }
   else
     {
-      util_error (_("Variable sendmail not set: no mailer"));
+      mu_error (_("Variable sendmail not set: no mailer"));
       status = ENOSYS;
     }
   return status;
@@ -433,28 +433,22 @@ send_message (mu_message_t msg)
    addresses on the command line and message contents on standard input. */
 
 int
-mail_send0 (compose_env_t * env, int save_to)
+mail_send0 (compose_env_t *env, int save_to)
 {
   int done = 0;
-  int fd, rc;
-  char *filename;
+  int rc;
   char *savefile = NULL;
   int int_cnt;
   char *escape;
 
-  rc = mu_tempfile (NULL, 0, &fd, &filename);
+  /* Prepare environment */
+  rc = mu_temp_file_stream_create (&env->compstr, NULL, 0);
   if (rc)
     {
-      util_error (_("Cannot open temporary file: %s"), mu_strerror (rc));
+      mu_error (_("Cannot open temporary file: %s"), mu_strerror (rc));
       return 1;
     }
 
-  /* Prepare environment */
-  env = env;
-  env->filename = filename;
-  env->file = fdopen (fd, "w+");
-  env->ofile = ofile;
-
   ml_clear_interrupt ();
   int_cnt = 0;
   while (!done)
@@ -466,7 +460,7 @@ mail_send0 (compose_env_t * env, int save_to)
        {
          if (mailvar_get (NULL, "ignore", mailvar_type_boolean, 0) == 0)
            {
-             fprintf (stdout, "@\n");
+             mu_printf ("@\n");
            }
          else
            {
@@ -474,7 +468,7 @@ mail_send0 (compose_env_t * env, int save_to)
                free (buf);
              if (++int_cnt == 2)
                break;
-             util_error (_("\n(Interrupt -- one more to kill letter)"));
+             mu_error (_("\n(Interrupt -- one more to kill letter)"));
            }
          continue;
        }
@@ -484,7 +478,7 @@ mail_send0 (compose_env_t * env, int save_to)
          if (interactive 
              && mailvar_get (NULL, "ignoreeof", mailvar_type_boolean, 0) == 0)
            {
-             util_error (mailvar_get (NULL, "dot", mailvar_type_boolean, 0) == 
0 ?
+             mu_error (mailvar_get (NULL, "dot", mailvar_type_boolean, 0) == 0 
?
                          _("Use \".\" to terminate letter.") :
                          _("Use \"~.\" to terminate letter."));
              continue;
@@ -502,7 +496,7 @@ mail_send0 (compose_env_t * env, int save_to)
               && buf[0] == escape[0])
        {
          if (buf[1] == buf[0])
-           fprintf (env->file, "%s\n", buf + 1);
+           mu_stream_printf (env->compstr, "%s\n", buf + 1);
          else if (buf[1] == '.')
            done = 1;
          else if (buf[1] == 'x')
@@ -515,8 +509,6 @@ mail_send0 (compose_env_t * env, int save_to)
              struct mu_wordsplit ws;
              int status;
 
-             ofile = env->file;
-
              if (mu_wordsplit (buf + 1, &ws, MU_WRDSF_DEFFLAGS) == 0)
                {
                  if (ws.ws_wordc > 0)
@@ -528,24 +520,22 @@ mail_send0 (compose_env_t * env, int save_to)
                        status = (*entry->escfunc) (ws.ws_wordc, ws.ws_wordv,
                                                    env);
                      else
-                       util_error (_("Unknown escape %s"), ws.ws_wordv[0]);
+                       mu_error (_("Unknown escape %s"), ws.ws_wordv[0]);
                    }
                  else
-                   util_error (_("Unfinished escape"));
+                   mu_error (_("Unfinished escape"));
                  mu_wordsplit_free (&ws);
                }
              else
                {
-                 util_error (_("Cannot parse escape sequence: %s"),
+                 mu_error (_("Cannot parse escape sequence: %s"),
                              mu_wordsplit_strerror (&ws));
                }
-
-             ofile = env->ofile;
            }
        }
       else
-       fprintf (env->file, "%s\n", buf);
-      fflush (env->file);
+       mu_stream_printf (env->compstr, "%s\n", buf);
+      mu_stream_flush (env->compstr);
       free (buf);
     }
 
@@ -553,9 +543,7 @@ mail_send0 (compose_env_t * env, int save_to)
   if (int_cnt)
     {
       save_dead_message (env);
-      fclose (env->file);
-      remove (filename);
-      free (filename);
+      mu_stream_destroy (&env->compstr);
       return 1;
     }
 
@@ -571,115 +559,100 @@ mail_send0 (compose_env_t * env, int save_to)
 
   if (util_header_expand (&env->header) == 0)
     {
+      mu_message_t msg = NULL;
       int rc;
-      mu_stream_t instr;
+      int status = 0;
+      
+      mu_message_create (&msg, NULL);
+      
+      /* Fill the body.  */
+      mu_stream_seek (env->compstr, 0, MU_SEEK_SET, NULL);
+      rc = fill_body (msg, env->compstr);
 
-      rc = mu_file_stream_create (&instr, filename, MU_STREAM_READ);
-      if (rc)
-       mu_error (_("cannot open temporary stream `%s' for reading: %s"),
-                 filename, mu_strerror (rc));
-      else
+      if (rc == 0)
        {
-         mu_message_t msg = NULL;
-         int rc;
-         int status = 0;
-         
-         mu_message_create (&msg, NULL);
-         
-         /* Fill the body.  */
-         rc = fill_body (msg, instr);
-         mu_stream_destroy (&instr);
-
-         if (rc == 0)
+         /* Save outgoing message */
+         if (save_to)
            {
-             /* Save outgoing message */
-             if (save_to)
-               {
-                 char *tmp = compose_header_get (env, MU_HEADER_TO, NULL);
-                 mu_address_t addr = NULL;
+             char *tmp = compose_header_get (env, MU_HEADER_TO, NULL);
+             mu_address_t addr = NULL;
              
-                 mu_address_create (&addr, tmp);
-                 mu_address_aget_email (addr, 1, &savefile);
-                 mu_address_destroy (&addr);
-                 if (savefile)
-                   {
-                     char *p = strchr (savefile, '@');
-                     if (p)
-                       *p = 0;
-                   }
-               }
-             util_save_outgoing (msg, savefile);
+             mu_address_create (&addr, tmp);
+             mu_address_aget_email (addr, 1, &savefile);
+             mu_address_destroy (&addr);
              if (savefile)
-               free (savefile);
+               {
+                 char *p = strchr (savefile, '@');
+                 if (p)
+                   *p = 0;
+               }
+           }
+         util_save_outgoing (msg, savefile);
+         if (savefile)
+           free (savefile);
 
-             /* Check if we need to save the message to files or pipes.  */
-             if (env->outfiles)
+         /* Check if we need to save the message to files or pipes.  */
+         if (env->outfiles)
+           {
+             int i;
+             for (i = 0; i < env->nfiles; i++)
                {
-                 int i;
-                 for (i = 0; i < env->nfiles; i++)
+                 /* Pipe to a cmd.  */
+                 if (env->outfiles[i][0] == '|')
+                   status = msg_to_pipe (env->outfiles[i] + 1, msg);
+                 /* Save to a file.  */
+                 else
                    {
-                     /* Pipe to a cmd.  */
-                     if (env->outfiles[i][0] == '|')
-                       status = msg_to_pipe (env->outfiles[i] + 1, msg);
-                     /* Save to a file.  */
-                     else
+                     mu_mailbox_t mbx = NULL;
+                     status = mu_mailbox_create_default (&mbx, 
+                                                         env->outfiles[i]);
+                     if (status == 0)
                        {
-                         mu_mailbox_t mbx = NULL;
-                         status = mu_mailbox_create_default (&mbx, 
-                                                              
env->outfiles[i]);
+                         status = mu_mailbox_open (mbx, MU_STREAM_WRITE
+                                                   | MU_STREAM_CREAT);
                          if (status == 0)
                            {
-                             status = mu_mailbox_open (mbx, MU_STREAM_WRITE
-                                                       | MU_STREAM_CREAT);
-                             if (status == 0)
-                               {
-                                 status = mu_mailbox_append_message (mbx, msg);
-                                 if (status)
-                                   util_error (_("Cannot append message: %s"),
-                                               mu_strerror (status));
-                                 mu_mailbox_close (mbx);
-                               }
-                             mu_mailbox_destroy (&mbx);
+                             status = mu_mailbox_append_message (mbx, msg);
+                             if (status)
+                               mu_error (_("Cannot append message: %s"),
+                                           mu_strerror (status));
+                             mu_mailbox_close (mbx);
                            }
-                         if (status)
-                           util_error (_("Cannot create mailbox %s: %s"), 
-                                       env->outfiles[i],
-                                       mu_strerror (status));
+                         mu_mailbox_destroy (&mbx);
                        }
+                     if (status)
+                       mu_error (_("Cannot create mailbox %s: %s"), 
+                                   env->outfiles[i],
+                                   mu_strerror (status));
                    }
                }
-
-             /* Do we need to Send the message on the wire?  */
-             if (status == 0 &&
-                 (compose_header_get (env, MU_HEADER_TO, NULL) ||
-                  compose_header_get (env, MU_HEADER_CC, NULL) ||
-                  compose_header_get (env, MU_HEADER_BCC, NULL)))
+           }
+         
+         /* Do we need to Send the message on the wire?  */
+         if (status == 0 &&
+             (compose_header_get (env, MU_HEADER_TO, NULL) ||
+              compose_header_get (env, MU_HEADER_CC, NULL) ||
+              compose_header_get (env, MU_HEADER_BCC, NULL)))
+           {
+             mu_message_set_header (msg, env->header, NULL);
+             env->header = NULL;
+             status = send_message (msg);
+             if (status)
                {
-                 mu_message_set_header (msg, env->header, NULL);
-                 env->header = NULL;
-                 status = send_message (msg);
-                 if (status)
-                   {
-                     mu_error (_("cannot send message: %s"),
-                               mu_strerror (status));
-                     save_dead_message (env);
-                   }
+                 mu_error (_("cannot send message: %s"),
+                           mu_strerror (status));
+                 save_dead_message (env);
                }
            }
-         fclose (env->file);
-         mu_message_destroy (&msg, NULL);
-         remove (filename);
-         free (filename);
-         return status;
-       }
+       }  
+      mu_stream_destroy (&env->compstr);
+      mu_message_destroy (&msg, NULL);
+      return status;
     }
   else
     save_dead_message (env);
   
-  fclose (env->file);
-
-  remove (filename);
-  free (filename);
+  mu_stream_destroy (&env->compstr);
   return 1;
 }
 
@@ -705,7 +678,7 @@ msg_to_pipe (const char *cmd, mu_message_t msg)
   status = mu_command_stream_create (&progstream, cmd, MU_STREAM_WRITE);
   if (status)
     {
-      util_error (_("Cannot pipe to %s: %s"), cmd, mu_strerror (status));
+      mu_error (_("Cannot pipe to %s: %s"), cmd, mu_strerror (status));
       return status;
     }
 
@@ -721,7 +694,7 @@ msg_to_pipe (const char *cmd, mu_message_t msg)
   
   if (status)
     {
-      util_error (_("Sending data to %s failed: %s"), cmd,
+      mu_error (_("Sending data to %s failed: %s"), cmd,
                  mu_strerror (status));
     }
   return status;
diff --git a/mail/setenv.c b/mail/setenv.c
index cccb4f6..ffc5280 100644
--- a/mail/setenv.c
+++ b/mail/setenv.c
@@ -29,7 +29,7 @@ mail_setenv (int argc, char **argv)
       char **p;
       
       for (p = environ; *p; p++)
-       printf ("%s\n", *p);
+       mu_printf ("%s\n", *p);
     }
   else
     {
diff --git a/mail/shell.c b/mail/shell.c
index df710fa..3ec5885 100644
--- a/mail/shell.c
+++ b/mail/shell.c
@@ -35,7 +35,7 @@ expand_bang (char **pbuf)
 
   if (!last)
     {
-      util_error (_("No previous command"));
+      mu_error (_("No previous command"));
       return;
     }
 
@@ -60,81 +60,65 @@ expand_bang (char **pbuf)
 int
 mail_execute (int shell, int argc, char **argv)
 {
-  pid_t pid;
-  char *buf = NULL;
-  char *argv0 = NULL;
+  int xargc, i, status, rc;
+  char **xargv;
+  char *buf;
 
-  if (argc)
+  if (argc == 0)
     {
-      argv0 = argv[0]; 
-  
-      /* Skip leading whitespace from argv[0] */
-      while (mu_isspace (**argv))
-       (*argv)++;
+      /* No arguments mean execute a copy of the user shell */
+      shell = 1;
     }
+  
+  xargc = argc;
+  if (shell && argc < 3)
+    xargc = 3;
+  xargv = xcalloc (xargc + 1, sizeof (xargv[0]));
+  
+  for (i = 0; i < argc; i++)
+    xargv[i] = argv[i];
 
   /* Expand arguments if required */
   if (mailvar_get (NULL, "bang", mailvar_type_boolean, 0) == 0)
     {
       int i;
 
-      for (i = 0; i < argc; i++)
-       expand_bang (argv + i);
+      for (i = 0; i < xargc; i++)
+       expand_bang (xargv + i);
     }
 
-  /* Construct command line and save it to gnu-last-command variable */
-  mu_argcv_string (argc, argv, &buf);
+  /* Reconstruct the command line and save it to gnu-last-command variable.
+     Important: use argc (not xargc)!
+  */
+  mu_argcv_string (argc, xargv, &buf);
   mailvar_set ("gnu-last-command", buf, mailvar_type_string, 
-             MOPTF_QUIET|MOPTF_OVERWRITE);
+              MOPTF_QUIET | MOPTF_OVERWRITE);
 
-  /* Do actual work */
-  
-  pid = fork ();  
-  if (pid == 0)
+  if (shell)
     {
-      if (shell)
+      xargv[0] = getenv ("SHELL");
+      if (argc == 0)
+       xargv[1] = NULL;
+      else
        {
-         if (argc == 0)
-           {
-             argv = xmalloc (sizeof (argv[0]) * 2);
-             argv[0] = getenv ("SHELL");
-             argv[1] = NULL;
-             argc = 1;
-           }
-         else
-           {
-             /* 1(shell) + 1 (-c) + 1(arg) + 1 (null) = 4  */
-             argv = xmalloc (4 * (sizeof (argv[0])));
-         
-             argv[0] = getenv ("SHELL");
-             argv[1] = "-c";
-             argv[2] = buf;
-             argv[3] = NULL;
-
-             argc = 3;
-           }
+         xargv[1] = "-c";
+         xargv[2] = buf;
+         xargv[3] = NULL;
        }
-      
-      execvp (argv[0], argv);
-      exit (1);
-    }
-  else
+    }  
+  
+  rc = mu_spawnvp (xargv[0], xargv, &status);
+  if (rc)
     {
-      if (argv0) /* Restore argv[0], else mu_argcv_free will coredump */
-       argv[0] = argv0;
-      free (buf);
-      if (pid > 0)
-       {
-         while (waitpid (pid, NULL, 0) == -1)
-           /* do nothing */;
-         return 0;
-       }
-      else /* if (pid < 0) */
-       {
-         mu_error ("fork failed: %s", mu_strerror (errno));
-         return 1;
-       }
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_spawnvp", xargv[0], rc);
     }
+  /* FIXME:
+  else if (status)
+    mu_diag_output (MU_DIAG_NOTICE, ....
+  */
+  free (buf);
+  free (xargv);
+  return rc;
 }
 
 /*
diff --git a/mail/size.c b/mail/size.c
index 186d36d..4c8c8e0 100644
--- a/mail/size.c
+++ b/mail/size.c
@@ -29,11 +29,11 @@ size0 (msgset_t *mspec, mu_message_t msg, void *data)
   mu_message_size (msg, &size);
   mu_message_lines (msg, &lines);
   
-  fprintf (ofile, "%c%2lu %3lu/%-5lu\n",
-          is_current_message (mspec->msg_part[0]) ? '>' : ' ',
-          (unsigned long) mspec->msg_part[0],
-          (unsigned long) lines,
-          (unsigned long) size);
+  mu_printf ("%c%2lu %3lu/%-5lu\n",
+                   is_current_message (mspec->msg_part[0]) ? '>' : ' ',
+                   (unsigned long) mspec->msg_part[0],
+                   (unsigned long) lines,
+                   (unsigned long) size);
   return 0;
 }
 
diff --git a/mail/source.c b/mail/source.c
index 6b7af0a..61efc1f 100644
--- a/mail/source.c
+++ b/mail/source.c
@@ -20,19 +20,24 @@
 static char *
 source_readline (void *closure, int cont MU_ARG_UNUSED)
 {
-  FILE *fp = closure;
-  size_t s = 0;
+  mu_stream_t input = closure;
+  size_t size = 0, n;
   char *buf = NULL;
-  
-  if (getline (&buf, &s, fp) >= 0)
+  int rc;
+
+  rc = mu_stream_getline (input, &buf, &size, &n);
+  if (rc)
     {
-      mu_rtrim_class (buf, MU_CTYPE_SPACE);
-      mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
-                       MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_LINE, NULL);
-      return buf;
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_getline", NULL, rc);
+      return NULL;
     }
-  
-  return NULL;
+  if (n == 0)
+    return NULL;
+
+  mu_rtrim_class (buf, MU_CTYPE_SPACE);
+  mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+                  MU_IOCTL_LOGSTREAM_ADVANCE_LOCUS_LINE, NULL);
+  return buf;
 }
   
 /*
@@ -42,22 +47,23 @@ source_readline (void *closure, int cont MU_ARG_UNUSED)
 int
 mail_source (int argc, char **argv)
 {
-  FILE *fp;
+  mu_stream_t input;
   int save_term;
   struct mu_locus locus;
+  int rc;
   
   if (argc != 2)
     {
       /* TRANSLATORS: 'source' is a command name. Do not translate it! */
-      util_error (_("source requires a single argument"));
+      mu_error (_("source requires a single argument"));
       return 1;
     }
-  
-  fp = fopen (argv[1], "r");
-  if (!fp)
+
+  rc = mu_file_stream_create (&input, argv[1], MU_STREAM_READ);
+  if (rc)
     {
-      if (errno != ENOENT)
-       util_error(_("Cannot open `%s': %s"), argv[1], strerror(errno));
+      if (rc != ENOENT)
+       mu_error(_("Cannot open `%s': %s"), argv[1], strerror (rc));
       return 1;
     }
 
@@ -68,10 +74,10 @@ mail_source (int argc, char **argv)
   locus.mu_col = 0;
   mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
                    MU_IOCTL_LOGSTREAM_SET_LOCUS, &locus);
-  mail_mainloop (source_readline, fp, 0);
+  mail_mainloop (source_readline, input, 0);
   interactive = save_term;
   mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
                    MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
-  fclose (fp);
+  mu_stream_unref (input);
   return 0;
 }
diff --git a/mail/struct.c b/mail/struct.c
index 0f241df..4814063 100644
--- a/mail/struct.c
+++ b/mail/struct.c
@@ -24,21 +24,20 @@ show_part (struct mime_descend_closure *closure, void *data)
   size_t width;
   size_t size = 0;
   
-  width = fprint_msgset (ofile, closure->msgset);
+  format_msgset (mu_strout, closure->msgset, &width);
   for (; width < 5; width++)
-    fputc (' ', ofile);
+    mu_stream_write (mu_strout, " ", 1, NULL);
     
-  fprintf (ofile, " %-25s", closure->type);
+  mu_printf (" %-25s", closure->type);
 
   mu_message_size (closure->message, &size);
   if (size < 1024)
-    fprintf (ofile, " %4lu", (unsigned long) size);
+    mu_printf (" %4lu", (unsigned long) size);
   else if (size < 1024*1024)
-    fprintf (ofile, "%4luK", (unsigned long) size / 1024);
+    mu_printf ("%4luK", (unsigned long) size / 1024);
   else
-    fprintf (ofile, "%4luM", (unsigned long) size / 1024 / 1024);
-
-  fprintf (ofile, "\n");
+    mu_printf ("%4luM", (unsigned long) size / 1024 / 1024);
+  mu_printf ("\n");
   return 0;
 }
 
diff --git a/mail/summary.c b/mail/summary.c
index 95ab7b5..a7026cb 100644
--- a/mail/summary.c
+++ b/mail/summary.c
@@ -60,16 +60,20 @@ mail_summary (int argc MU_ARG_UNUSED, char **argv 
MU_ARG_UNUSED)
   {
     mu_url_t url = NULL;
     mu_mailbox_get_url (mbox, &url);
-    printf("\"%s\": ", util_url_to_string (url));
+    mu_printf ("\"%s\": ", util_url_to_string (url));
   }
-  printf (ngettext ("%d message", "%d messages", count), count);
+  mu_printf (
+                   ngettext ("%d message", "%d messages", count), count);
   if (mnew > 0)
-    printf (ngettext (" %d new", " %d new", mnew), mnew);
+    mu_printf (ngettext (" %d new", " %d new", mnew), mnew);
   if (mseen > 0)
-    printf (ngettext (" %d unread", " %d unread", mseen), mseen);
+    mu_printf (ngettext (" %d unread", " %d unread", mseen),
+                     mseen);
   if (mdelete > 0)
-    printf (ngettext (" %d deleted", " %d deleted", mdelete), mdelete);
-  printf("\n");
+    mu_printf (
+                     ngettext (" %d deleted", " %d deleted", mdelete),
+                     mdelete);
+  mu_printf ("\n");
 
   /* Set the cursor.  */
   set_cursor ((first_new == 0) ? ((first_unread == 0) ?
diff --git a/mail/top.c b/mail/top.c
index c70801f..ad4271a 100644
--- a/mail/top.c
+++ b/mail/top.c
@@ -25,23 +25,23 @@ static int
 top0 (msgset_t *mspec, mu_message_t msg, void *data)
 {
   mu_stream_t stream;
-  char buf[512];
-  size_t n;
+  char *buf = NULL;
+  size_t size = 0, n;
   int lines;
   
   if (mailvar_get (&lines, "toplines", mailvar_type_number, 1)
       || lines < 0)
     return 1;
 
-  /* FIXME: Use mu_stream_copy */
   mu_message_get_streamref (msg, &stream);
   for (; lines > 0; lines--)
     {
-      int status = mu_stream_readline (stream, buf, sizeof (buf), &n);
+      int status = mu_stream_getline (stream, &buf, &size, &n);
       if (status != 0 || n == 0)
        break;
-      fprintf (ofile, "%s", buf);
+      mu_printf ("%s", buf);
     }
+  free (buf);
   mu_stream_destroy (&stream);
   set_cursor (mspec->msg_part[0]);
 
diff --git a/mail/unalias.c b/mail/unalias.c
index d97c794..a47dfbe 100644
--- a/mail/unalias.c
+++ b/mail/unalias.c
@@ -27,7 +27,7 @@ mail_unalias (int argc, char **argv)
   if (argc == 1)
     {
       /* TRANSLATORS: 'unalias' is a command name. Do not translate it! */
-      util_error (_("unalias requires at least one argument"));
+      mu_error (_("unalias requires at least one argument"));
       return 1;
     }
   while (--argc)
diff --git a/mail/unset.c b/mail/unset.c
index 77e6fb4..d4f20f1 100644
--- a/mail/unset.c
+++ b/mail/unset.c
@@ -31,7 +31,7 @@ mail_unset (int argc, char **argv)
   else
     {
       int status = 0, i = 1;
-      for (i=1; i < argc; i++)
+      for (i = 1; i < argc; i++)
        {
          char *buf = xmalloc ((7+strlen (argv[i])) * sizeof (char));
          strcpy (buf, "set no");
diff --git a/mail/util.c b/mail/util.c
index d8e87b3..dd53221 100644
--- a/mail/util.c
+++ b/mail/util.c
@@ -32,11 +32,6 @@
 #endif
 #include <mailutils/io.h>
 
-/*
- * expands command into its command and arguments, then runs command
- * cmd is the command to parse and run
- * returns exit status of the command
- */
 int
 util_do_command (const char *fmt, ...)
 {
@@ -149,9 +144,9 @@ util_do_command (const char *fmt, ...)
   else
     {
       if (argc)
-       util_error (_("Unknown command: %s"), argv[0]);
+       mu_error (_("Unknown command: %s"), argv[0]);
       else
-       util_error (_("Invalid command"));
+       mu_error (_("Invalid command"));
       status = 1;
     }
 
@@ -218,7 +213,7 @@ util_range_msg (size_t low, size_t high, int flags,
      if ((flags & MSG_NODELETED) && util_isdeleted (low))
        {
         if (!(flags & MSG_SILENT))
-          util_error (_("%lu: Inappropriate message (has been deleted)"),
+          mu_error (_("%lu: Inappropriate message (has been deleted)"),
                       (unsigned long) low);
         continue;
        }
@@ -278,22 +273,20 @@ util_help (void *table, size_t nmemb, size_t size, const 
char *word)
   if (!word)
     {
       int i = 0;
-      FILE *out = stdout;
+      mu_stream_t out;
       char *p;
 
-      if (mailvar_get (NULL, "crt", mailvar_type_boolean, 0) == 0)
-       out = popen (getenv ("PAGER"), "w");
+      out = open_pager (util_screen_lines () + 1);
 
       for (p = table, i = 0; i < nmemb; i++, p += size)
        {
          struct mail_command *cp = (struct mail_command *)p;
          if (cp->synopsis == NULL)
            continue;
-         fprintf (out, "%s\n", cp->synopsis);
+         mu_stream_printf (out, "%s\n", cp->synopsis);
        }
       
-      if (out != stdout)
-       pclose (out);
+      mu_stream_unref (out);
 
       return 0;
     }
@@ -302,11 +295,11 @@ util_help (void *table, size_t nmemb, size_t size, const 
char *word)
       int status = 0;
       struct mail_command *cp = util_find_entry (table, nmemb, size, word);
       if (cp && cp->synopsis)
-       fprintf (stdout, "%s\n", cp->synopsis);
+       mu_printf ("%s\n", cp->synopsis);
       else
        {
          status = 1;
-         fprintf (stdout, _("Unknown command: %s\n"), word);
+         mu_printf (_("Unknown command: %s\n"), word);
        }
       return status;
     }
@@ -339,12 +332,12 @@ util_command_list (void *table, size_t nmemb, size_t size)
       if (pos >= cols)
        {
          pos = len + 1;
-         fprintf (ofile, "\n%s ", cmd);
+         mu_printf ("\n%s ", cmd);
        }
       else
-        fprintf (ofile, "%s ", cmd);
+        mu_printf ("%s ", cmd);
     }
-  fprintf (ofile, "\n");
+  mu_printf ("\n");
   return 0;
 }
 
@@ -473,7 +466,7 @@ util_get_homedir ()
   if (!homedir)
     {
       /* Shouldn't happen, but one never knows */
-      util_error (_("Cannot get homedir"));
+      mu_error (_("Cannot get homedir"));
       exit (EXIT_FAILURE);
     }
   return homedir;
@@ -537,14 +530,14 @@ util_get_sender (int msgno, int strip)
       if (mu_envelope_sget_sender (env, &buffer)
          || mu_address_create (&addr, buffer))
        {
-         util_error (_("Cannot determine sender name (msg %d)"), msgno);
+         mu_error (_("Cannot determine sender name (msg %d)"), msgno);
          return NULL;
        }
     }
 
   if (mu_address_aget_email (addr, 1, &buf))
     {
-      util_error (_("Cannot determine sender name (msg %d)"), msgno);
+      mu_error (_("Cannot determine sender name (msg %d)"), msgno);
       mu_address_destroy (&addr);
       return NULL;
     }
@@ -572,8 +565,7 @@ util_slist_print (mu_list_t list, int nl)
   for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next 
(itr))
     {
       mu_iterator_current (itr, (void **)&name);
-      fprintf (ofile, "%s%c", name, nl ? '\n' : ' ');
-
+      mu_printf ("%s%c", name, nl ? '\n' : ' ');
     }
   mu_iterator_destroy (&itr);
 }
@@ -728,7 +720,7 @@ util_save_outgoing (mu_message_t msg, char *savefile)
       rc = mu_mailbox_create_default (&outbox, filename);
       if (rc)
        {
-         util_error (_("Cannot create output mailbox `%s': %s"),
+         mu_error (_("Cannot create output mailbox `%s': %s"),
                      filename, strerror (rc));
          free (filename);
          return;
@@ -736,13 +728,13 @@ util_save_outgoing (mu_message_t msg, char *savefile)
 
       rc = mu_mailbox_open (outbox, MU_STREAM_WRITE | MU_STREAM_CREAT);
       if (rc)
-       util_error (_("Cannot open output mailbox `%s': %s"),
+       mu_error (_("Cannot open output mailbox `%s': %s"),
                    filename, strerror (rc));
       else
        {
          rc = mu_mailbox_append_message (outbox, msg);
          if (rc)
-           util_error (_("Cannot append message to `%s': %s"),
+           mu_error (_("Cannot append message to `%s': %s"),
                        filename, strerror (rc));
        }
 
@@ -753,19 +745,6 @@ util_save_outgoing (mu_message_t msg, char *savefile)
     }
 }
 
-void
-util_error (const char *format, ...)
-{
-  va_list ap;
-
-  va_start (ap, format);
-  
-  vfprintf (stderr, format, ap);
-  fprintf (stderr, "\n");
-
-  va_end(ap);
-}
-
 static int
 util_descend_subparts (mu_message_t mesg, msgset_t *msgset, mu_message_t *part)
 {
@@ -784,7 +763,7 @@ util_descend_subparts (mu_message_t mesg, msgset_t *msgset, 
mu_message_t *part)
        {
          if (mu_message_unencapsulate (mesg, &submsg, NULL))
            {
-             util_error (_("Cannot unencapsulate message/part"));
+             mu_error (_("Cannot unencapsulate message/part"));
              return 1;
            }
          mesg = submsg;
@@ -793,14 +772,14 @@ util_descend_subparts (mu_message_t mesg, msgset_t 
*msgset, mu_message_t *part)
       mu_message_get_num_parts (mesg, &nparts);
       if (nparts < msgset->msg_part[i])
        {
-         util_error (_("No such (sub)part in the message: %lu"),
+         mu_error (_("No such (sub)part in the message: %lu"),
                      (unsigned long) msgset->msg_part[i]);
          return 1;
        }
 
       if (mu_message_get_part (mesg, msgset->msg_part[i], &submsg))
        {
-         util_error (_("Cannot get (sub)part from the message: %lu"),
+         mu_error (_("Cannot get (sub)part from the message: %lu"),
                      (unsigned long) msgset->msg_part[i]);
          return 1;
        }
@@ -928,7 +907,7 @@ util_header_expand (mu_header_t *phdr)
   rc = mu_header_create (&hdr, "", 0);
   if (rc)
     {
-      util_error (_("Cannot create temporary header: %s"), mu_strerror (rc));
+      mu_error (_("Cannot create temporary header: %s"), mu_strerror (rc));
       return 1;
     }
       
@@ -980,10 +959,10 @@ util_header_expand (mu_header_t *phdr)
                {
                  errcnt++;
                  if (exp)
-                   util_error (_("Cannot parse address `%s' (while expanding 
`%s'): %s"),
+                   mu_error (_("Cannot parse address `%s' (while expanding 
`%s'): %s"),
                                exp, p, mu_strerror (rc));
                  else
-                   util_error (_("Cannot parse address `%s': %s"),
+                   mu_error (_("Cannot parse address `%s': %s"),
                                p, mu_strerror (rc));
                }
              
@@ -1033,7 +1012,7 @@ util_get_message (mu_mailbox_t mbox, size_t msgno, 
mu_message_t *msg)
   status = mu_mailbox_get_message (mbox, msgno, msg);
   if (status)
     {
-      util_error (_("Cannot get message %lu: %s"),
+      mu_error (_("Cannot get message %lu: %s"),
                  (unsigned long) msgno, mu_strerror (status));
       return status;
     }
@@ -1044,14 +1023,14 @@ util_get_message (mu_mailbox_t mbox, size_t msgno, 
mu_message_t *msg)
 int
 util_error_range (size_t msgno)
 {
-  util_error (_("%lu: invalid message number"), (unsigned long) msgno);
+  mu_error (_("%lu: invalid message number"), (unsigned long) msgno);
   return 1;
 }
 
 void
 util_noapp ()
 {
-  util_error (_("No applicable messages"));
+  mu_error (_("No applicable messages"));
 }
 
 void
@@ -1150,3 +1129,29 @@ util_url_to_string (mu_url_t url)
     }
   return mu_url_to_string (url);
 }
+
+mu_stream_t
+open_pager (size_t lines)
+{
+  const char *pager;
+  unsigned pagelines = util_get_crt ();
+  mu_stream_t str;
+  
+  if (pagelines && lines > pagelines && (pager = getenv ("PAGER")))
+    {
+      int rc = mu_command_stream_create (&str, pager, MU_STREAM_WRITE);
+      if (rc)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_prog_stream_create",
+                          pager, rc);
+         str = mu_strout;
+         mu_stream_ref (str);
+       }
+    }
+  else
+    {
+      str = mu_strout;
+      mu_stream_ref (str);
+    }
+  return str;
+}
diff --git a/mail/version.c b/mail/version.c
index 12c907b..8ba28b6 100644
--- a/mail/version.c
+++ b/mail/version.c
@@ -39,16 +39,16 @@ static const char *with_defs[] =
 int
 mail_version (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
 { 
-  fprintf (ofile, "%s", program_version);
+  mu_printf ("%s", program_version);
   if (with_defs[0] != NULL)
     {
       int i;
-      fprintf (ofile, " (");
+      mu_printf (" (");
       for (i = 0; with_defs[i]; i++)
-       fprintf (ofile, " %s", with_defs[i]);
-      fprintf (ofile, " )");
+       mu_printf (" %s", with_defs[i]);
+      mu_printf (" )");
     }
-  fprintf (ofile, "\n");
+  mu_printf ("\n");
 
   return 0;
 }
diff --git a/mail/write.c b/mail/write.c
index 1368d11..586eeb3 100644
--- a/mail/write.c
+++ b/mail/write.c
@@ -43,7 +43,7 @@ mail_write (int argc, char **argv)
       char *p = NULL;
       if (n == 0)
         {
-          util_error (_("No applicable message"));
+          mu_error (_("No applicable message"));
           return 1;
         }
       mu_asprintf (&p, "%lu", (unsigned long) n);
@@ -72,7 +72,7 @@ mail_write (int argc, char **argv)
                              MU_STREAM_APPEND|MU_STREAM_CREAT);
   if (rc)
     {
-      util_error (_("can't open %s: %s"), filename, mu_strerror (rc));
+      mu_error (_("can't open %s: %s"), filename, mu_strerror (rc));
       free (filename);
       msgset_free (msglist);
       return 1;
@@ -114,8 +114,8 @@ mail_write (int argc, char **argv)
   mu_stream_close (output);
   mu_stream_destroy (&output);
   
-  fprintf (ofile, "\"%s\" %3lu/%-5lu\n", filename,
-          (unsigned long) total_lines, (unsigned long) total_size);
+  mu_printf ("\"%s\" %3lu/%-5lu\n", filename,
+                   (unsigned long) total_lines, (unsigned long) total_size);
 
   free (filename);
   msgset_free (msglist);
diff --git a/mail/z.c b/mail/z.c
index 52a90f5..c2ec923 100644
--- a/mail/z.c
+++ b/mail/z.c
@@ -61,7 +61,7 @@ z_parse_args(int argc, char **argv,
         dir = D_NONE;
         break;
        default:
-        util_error (_("Bad arguments for the scrolling command"));
+        mu_error (_("Bad arguments for the scrolling command"));
         return 1;
        }
 
@@ -76,7 +76,7 @@ z_parse_args(int argc, char **argv,
 
       if (argc > 1)
        {
-         util_error (_("Too many arguments for the scrolling command"));
+         mu_error (_("Too many arguments for the scrolling command"));
          return 1;
        }
 
@@ -84,13 +84,13 @@ z_parse_args(int argc, char **argv,
        {
          if (dir == D_NONE)
            {
-             util_error (_("Argument not applicable for z"));
+             mu_error (_("Argument not applicable for z"));
              return 1;
            }
 
          if ((mul = strtoul (argp, NULL, 10)) == 0)
            {
-             util_error (_("Bad number of pages"));
+             mu_error (_("Bad number of pages"));
              return 1;
            }
        }
@@ -120,7 +120,7 @@ mail_z (int argc, char **argv)
     case D_BWD:
       if (page_move (-count) == 0)
        {
-         fprintf (stdout, _("On first screenful of messages\n"));
+         mu_printf (_("On first screenful of messages\n"));
          return 0;
        }
       break;
@@ -128,7 +128,7 @@ mail_z (int argc, char **argv)
     case D_FWD:
       if (page_move (count) == 0)
        {
-         fprintf (stdout, _("On last screenful of messages\n"));
+         mu_printf (_("On last screenful of messages\n"));
          return 0;
        }
       break;


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]