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-114-ge105df6


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-114-ge105df6
Date: Sun, 03 Oct 2010 18:52:12 +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=e105df67dcc3f11787259c6334e68a9dabb167c1

The branch, master has been updated
       via  e105df67dcc3f11787259c6334e68a9dabb167c1 (commit)
       via  aa0826526df4dc51cafc2297b7b8306831c38f98 (commit)
       via  af4665d48e3dbfe8b9179740509a61722291e13b (commit)
       via  f223b22f5a8cc3ed3428092ddf30dd315a3213f3 (commit)
      from  9d1a990614d460252b6217cb4f98742b69d29314 (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 e105df67dcc3f11787259c6334e68a9dabb167c1
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Oct 3 21:42:58 2010 +0300

    Bugfix.
    
    * examples/http.c (main): Fix open/wait loop.
    * libmailutils/stream.c (mu_stream_wait): May be used
    on not-open streams.
    * examples/.gitignore: Add more files.

commit aa0826526df4dc51cafc2297b7b8306831c38f98
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Oct 3 21:24:52 2010 +0300

    New utility: mu
    
    The `mu' program is a multi-purpose tool for doing various mail-
    and mailutils-related operations.  It includes a pop3 shell,
    a coder/decoder for all filter formats supported by Mailutils,
    a utility to extract arbitrary values from the MU configuration
    files, a configuration information utility and many more, in the
    short run.  It supercedes examples/pop3client and (partially)
    mailutils-config, both of which will be removed in the future.
    
    * Makefile.am (SUBDIRS): Add mu.
    * configure.ac: Likewise.
    * po/POTFILES.in: Add new files.
    * mu/.gitignore: New file.
    * mu/Makefile.am: New file.
    * mu/filter.c: New file.
    * mu/flt2047.c: New file.
    * mu/info.c: New file.
    * mu/mu.c: New file.
    * mu/mu.h: New file.
    * mu/pop.c: New file.
    * mu/query.c: New file.
    * mu/shell.c: New file.

commit af4665d48e3dbfe8b9179740509a61722291e13b
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Oct 3 14:43:44 2010 +0300

    Improve stream creation consistency.
    
    One of stream flags bits indicates whether the stream is
    open or not.  The mu_stream_open function refuses to act if it
    already is.  The rest of functions (including mu_stream_close)
    refuses to act if the stream was not open.  A special function
    (mu_stream_is_open) is provided to check if the stream is in
    open state.
    
    Any stream creation function returns an already open stream.  The
    function mu_stream_open should be called only if the stream was
    previously closed by a call to mu_stream_close.
    
    * include/mailutils/stream.h (mu_stream_is_open): New proto.
    * include/mailutils/sys/stream.h (_MU_STR_OPEN): New flag.
    * libmailutils/stream.c (_mu_stream_create): Permit setting the
    _MU_STR_OPEN flag.
    (_stream_init): New static.
    (mu_stream_open): Return MU_ERR_OPEN if the stream is already open.
    (mu_stream_is_open): New function.
    (mu_stream_seek, mu_stream_read, mu_stream_readdelim)
    (mu_stream_getdelim, mu_stream_write, mu_stream_flush)
    (mu_stream_close, mu_stream_size, mu_stream_wait)
    (mu_stream_truncate): Check if the stream is open. Return MU_ERR_NOT_OPEN
    otherwise.
    
    * libmailutils/errors (MU_ERR_OPEN): Reword the diagnostics.
    
    * libmailutils/dbgstream.c (mu_dbgstream_create): Open the stream.
    * libmailutils/file_stream.c (mu_file_stream_create)
    (mu_fd_stream_create): Open the stream.
    * libmailutils/filter_iconv.c (mu_filter_iconv_create): Open the stream.
    * libmailutils/mapfile_stream.c (mu_mapfile_stream_create): Open the stream.
    * libmailutils/fltstream.c (mu_filter_stream_create): Mark the stream
    as open.
    * libmailutils/iostream.c (mu_iostream_create): Likewise.
    * libmailutils/memory_stream.c: Likewise.
    * libmailutils/message.c (_message_stream_create): Likewise.
    * libmailutils/message_stream.c (mu_message_stream_create): Likewise.
    * libmailutils/prog_stream.c (mu_prog_stream_create): Likewise.
    * libmailutils/socket_stream.c (mu_socket_stream_create): Likewise.
    * libmailutils/temp_file_stream.c (mu_temp_file_stream_create): Likewise.
    
    * libmailutils/amd.c (_amd_attach_message): Mark stream as open.
    * libmailutils/body.c (_body_get_stream): Likewise.
    * libmailutils/memory_stream.c: Likewise.
    * libmailutils/rdcache_stream.c (mu_rdcache_stream_create: Likewise.
    * libmailutils/stdio_stream.c (mu_stdio_stream_create): Likewise.
    * libmailutils/streamref.c (mu_streamref_create_abridged): Likewise.
    * libmailutils/tcp.c (mu_tcp_stream_create_with_source_ip): Likewise.
    * libmailutils/xscript-stream.c (mu_xscript_stream_create): Likewise.
    * libmu_auth/tls.c (_mu_tls_io_stream_create): Likewise.
    (_mu_tls_stream_create): Likewise.
    * libproto/pop/pop3_stream.c (mu_pop3_stream_create): Likewise.
    
    * examples/base64.c: Remove unnecessary mu_stream_open.
    * examples/http.c: Likewise.
    * examples/iconv.c: Likewise.
    * examples/msg-send.c: Likewise.
    * examples/murun.c: Likewise.
    * examples/musocio.c: Likewise.
    * examples/pop3client.c: Likewise.
    * imap4d/append.c: Likewise.
    * imap4d/io.c: Likewise.
    * imap4d/preauth.c: Likewise.
    * lib/mailcap.c: Likewise.
    * libmailutils/attachment.c: Likewise.
    * libmailutils/cfg_driver.c: Likewise.
    * libmailutils/header.c: Likewise.
    * libmailutils/mailcap.c: Likewise.
    * libmailutils/mimehdr.c: Likewise.
    * libmailutils/mutil.c: Likewise.
    * libmailutils/tests/fltst.c: Likewise.
    * libmailutils/tests/mailcap.c: Likewise.
    * libmailutils/vartab.c: Likewise.
    * libmailutils/wicket.c: Likewise.
    * libmu_argp/muinit.c: Likewise.
    * libmu_auth/ldap.c: Likewise.
    * libmu_sieve/extensions/pipe.c: Likewise.
    * libmu_sieve/extensions/spamd.c: Likewise.
    * libmu_sieve/extensions/vacation.c: Likewise.
    * libproto/imap/folder.c: Likewise.
    * libproto/mailer/smtp.c: Likewise.
    * libproto/mailer/smtp_starttls.c: Likewise.
    * libproto/mbox/mbox.c: Likewise.
    * libproto/nntp/nntp_connect.c: Likewise.
    * libproto/pop/mbox.c: Likewise.
    * libproto/pop/pop3_connect.c: Likewise.
    * libproto/pop/pop3_stls.c: Likewise.
    * maidag/mailtmp.c: Likewise.
    * mail/decode.c: Likewise.
    * mail/pipe.c: Likewise.
    * mail/send.c: Likewise.
    * mail/send.c: Likewise.
    * mail/write.c: Likewise.
    * mh/burst.c: Likewise.
    * mh/comp.c: Likewise.
    * mh/compcommon.c: Likewise.
    * mh/forw.c: Likewise.
    * mh/mh_init.c: Likewise.
    * mh/mh_whatnow.c: Likewise.
    * mh/mhl.c: Likewise.
    * mh/mhn.c: Likewise.
    * mh/repl.c: Likewise.
    * mimeview/mimeview.c: Likewise.
    * pop3d/extra.c: Likewise.
    * sieve/sieve.c: Likewise.
    * testsuite/smtpsend.c: Likewise.

commit f223b22f5a8cc3ed3428092ddf30dd315a3213f3
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Oct 3 14:39:42 2010 +0300

    Fix the SMTP SASL (client) without trace.
    
    * include/mailutils/sys/smtp.h (_mu_smtp_get_streams)
    (_mu_smtp_set_streams): New protos.
    * libproto/mailer/smtp_gsasl.c (insert_gsasl_stream): Use 
_mu_smtp_get_streams
    and _mu_smtp_set_streams to change streams.
    * libproto/mailer/smtp_starttls.c (smtp_get_streams): Rename to
    _mu_smtp_get_streams. All callers changed.
    (smtp_set_streams): Rename to
    _mu_smtp_set_streams. All callers changed.

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

Summary of changes:
 Makefile.am                       |    1 +
 configure.ac                      |    1 +
 examples/.gitignore               |    2 +
 examples/base64.c                 |    2 -
 examples/http.c                   |    9 +-
 examples/iconv.c                  |    3 -
 examples/msg-send.c               |    1 -
 examples/murun.c                  |   10 -
 examples/musocio.c                |    1 -
 examples/pop3client.c             |    9 -
 imap4d/append.c                   |    3 +-
 imap4d/io.c                       |    5 -
 imap4d/preauth.c                  |    9 -
 include/mailutils/stream.h        |    1 +
 include/mailutils/sys/smtp.h      |    4 +
 include/mailutils/sys/stream.h    |   11 +-
 lib/mailcap.c                     |   10 -
 libmailutils/amd.c                |   11 +-
 libmailutils/attachment.c         |   56 ++--
 libmailutils/body.c               |    5 +-
 libmailutils/cfg_driver.c         |    1 -
 libmailutils/dbgstream.c          |   13 +-
 libmailutils/errors               |    2 +-
 libmailutils/file_stream.c        |   18 +-
 libmailutils/filter_iconv.c       |   11 +-
 libmailutils/fltstream.c          |    1 +
 libmailutils/header.c             |    6 -
 libmailutils/iostream.c           |    1 +
 libmailutils/mailcap.c            |  106 +++---
 libmailutils/mapfile_stream.c     |   13 +-
 libmailutils/memory_stream.c      |   26 +-
 libmailutils/message.c            |    4 +-
 libmailutils/message_stream.c     |   19 +-
 libmailutils/mimehdr.c            |    4 -
 libmailutils/mutil.c              |    9 +-
 libmailutils/prog_stream.c        |   36 +-
 libmailutils/rdcache_stream.c     |    5 +-
 libmailutils/socket_stream.c      |    8 +-
 libmailutils/stdio_stream.c       |    1 +
 libmailutils/stream.c             |  109 +++++-
 libmailutils/streamref.c          |    3 +-
 libmailutils/tcp.c                |   13 +-
 libmailutils/temp_file_stream.c   |   17 +-
 libmailutils/tests/fltst.c        |    3 -
 libmailutils/tests/mailcap.c      |    8 -
 libmailutils/vartab.c             |    1 -
 libmailutils/wicket.c             |  105 +++---
 libmailutils/xscript-stream.c     |    3 +-
 libmu_argp/muinit.c               |    1 -
 libmu_auth/ldap.c                 |    4 -
 libmu_auth/tls.c                  |   14 +-
 libmu_sieve/extensions/pipe.c     |    3 -
 libmu_sieve/extensions/spamd.c    |   13 -
 libmu_sieve/extensions/vacation.c |   11 -
 libproto/imap/folder.c            |   16 +-
 libproto/mailer/smtp.c            |    7 -
 libproto/mailer/smtp_gsasl.c      |   11 +-
 libproto/mailer/smtp_starttls.c   |   18 +-
 libproto/mbox/mbox.c              |   60 +--
 libproto/nntp/nntp_connect.c      |    7 +-
 libproto/pop/mbox.c               |   13 -
 libproto/pop/pop3_connect.c       |    9 +-
 libproto/pop/pop3_stls.c          |    2 -
 libproto/pop/pop3_stream.c        |    3 +-
 maidag/mailtmp.c                  |    7 -
 mail/decode.c                     |    6 -
 mail/pipe.c                       |    2 -
 mail/send.c                       |    2 -
 mail/write.c                      |    2 -
 mh/burst.c                        |    7 +-
 mh/comp.c                         |    3 +-
 mh/compcommon.c                   |    3 +-
 mh/forw.c                         |    3 +-
 mh/mh_init.c                      |   14 +-
 mh/mh_whatnow.c                   |    6 -
 mh/mhl.c                          |   12 -
 mh/mhn.c                          |   56 ---
 mh/repl.c                         |    7 -
 mimeview/mimeview.c               |    1 -
 mu/.gitignore                     |    1 +
 mu/Makefile.am                    |   43 ++
 mu/filter.c                       |  159 ++++++++
 mu/flt2047.c                      |  153 ++++++++
 mu/info.c                         |   93 +++++
 mu/mu.c                           |  150 +++++++
 mu/mu.h                           |   40 ++
 mu/pop.c                          |  778 +++++++++++++++++++++++++++++++++++++
 mu/query.c                        |  121 ++++++
 mu/shell.c                        |  492 +++++++++++++++++++++++
 po/POTFILES.in                    |    8 +
 pop3d/extra.c                     |   12 +-
 sieve/sieve.c                     |    6 -
 testsuite/smtpsend.c              |    6 +-
 93 files changed, 2494 insertions(+), 591 deletions(-)
 create mode 100644 mu/.gitignore
 create mode 100644 mu/Makefile.am
 create mode 100644 mu/filter.c
 create mode 100644 mu/flt2047.c
 create mode 100644 mu/info.c
 create mode 100644 mu/mu.c
 create mode 100644 mu/mu.h
 create mode 100644 mu/pop.c
 create mode 100644 mu/query.c
 create mode 100644 mu/shell.c

diff --git a/Makefile.am b/Makefile.am
index e8f8e94..7c403d6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -109,6 +109,7 @@ SUBDIRS = . \
  doc\
  config\
  examples\
+ mu\
  $(FRM_DIR)\
  $(POP3D_DIR)\
  $(IMAP4D_DIR)\
diff --git a/configure.ac b/configure.ac
index 13cf4fa..509a569 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1389,6 +1389,7 @@ AC_CONFIG_FILES([
  mu-aux/Makefile
  mu-aux/mailutils.spec
  sieve/Makefile
+ mu/Makefile
  ])
 AC_OUTPUT
 
diff --git a/examples/.gitignore b/examples/.gitignore
index f5ec94c..b42a928 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -15,8 +15,10 @@ mimetest
 msg-send
 mta
 muauth
+mucat
 muemail
 murun
+musocio
 nntpclient
 pop3client
 sfrom
diff --git a/examples/base64.c b/examples/base64.c
index aa6bdeb..1f54ea7 100644
--- a/examples/base64.c
+++ b/examples/base64.c
@@ -151,14 +151,12 @@ main (int argc, char * argv [])
     MU_ASSERT (mu_file_stream_create (&in, input, 
MU_STREAM_READ|MU_STREAM_SEEK));
   else
     MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
-  MU_ASSERT (mu_stream_open (in));
 
   if (output)
     MU_ASSERT (mu_file_stream_create (&out, output, 
                                       MU_STREAM_WRITE|MU_STREAM_CREAT));
   else
     MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
-  MU_ASSERT (mu_stream_open (out));
 
   if (line_length_option)
     reset_line_length (encoding, line_length);
diff --git a/examples/http.c b/examples/http.c
index a2bb6b7..44666e5 100644
--- a/examples/http.c
+++ b/examples/http.c
@@ -91,19 +91,22 @@ main (int argc, char **argv)
            argc == 3 ? argv[2] : "/");
 
   ret = mu_tcp_stream_create (&stream, url, 80, MU_STREAM_NONBLOCK);
-  if (ret != 0)
+  if (ret != 0 && !(ret == EAGAIN || ret == EINPROGRESS))
     {
       mu_error ("mu_tcp_stream_create: %s", mu_strerror (ret));
       exit (EXIT_FAILURE);
     }
 
-  for (attempt = 0; (ret = mu_stream_open (stream)); )
+  for (attempt = 0; ret; )
     {
       if ((ret == EAGAIN || ret == EINPROGRESS) && attempt < io_attempts)
        {
          ret = http_stream_wait(stream, MU_STREAM_READY_WR, &attempt);
          if (ret == 0)
-           continue;
+           {
+             ret = mu_stream_open (stream);
+             continue;
+           }
        }
       mu_error ("mu_stream_open: %s", mu_strerror (ret));
       exit (EXIT_FAILURE);
diff --git a/examples/iconv.c b/examples/iconv.c
index fd293bf..7876dc6 100644
--- a/examples/iconv.c
+++ b/examples/iconv.c
@@ -43,13 +43,10 @@ main (int argc, char **argv)
     }
 
   MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
-  MU_ASSERT (mu_stream_open (in));
   MU_ASSERT (mu_filter_iconv_create (&cvt, in, argv[1], argv[2], 
                                      0, mu_fallback_none));
-  MU_ASSERT (mu_stream_open (cvt));
   
   MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
-  MU_ASSERT (mu_stream_open (out));
 
   while ((rc = mu_stream_read (cvt, buffer, sizeof (buffer), &size)) == 0
         && size > 0)
diff --git a/examples/msg-send.c b/examples/msg-send.c
index 5c4f70f..46dd82a 100644
--- a/examples/msg-send.c
+++ b/examples/msg-send.c
@@ -109,7 +109,6 @@ main (int argc, char *argv[])
     }
 
   MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_SEEK));
-  MU_ASSERT (mu_stream_open (in));
   MU_ASSERT (mu_message_create (&msg, NULL));
   MU_ASSERT (mu_message_set_stream (msg, in, NULL));
   MU_ASSERT (mu_mailer_create (&mailer, optmailer));
diff --git a/examples/murun.c b/examples/murun.c
index 51b4710..c4f822f 100644
--- a/examples/murun.c
+++ b/examples/murun.c
@@ -69,7 +69,6 @@ main (int argc, char *argv[])
     {
       mu_stream_t in;
       MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
-      MU_ASSERT (mu_stream_open (in));
       rc = mu_filter_prog_stream_create (&stream, cmdline, in);
       /* Make sure closing/destroying stream will close/destroy in */
       mu_stream_unref (in);
@@ -83,16 +82,7 @@ main (int argc, char *argv[])
       exit (1);
     }
   
-  rc = mu_stream_open (stream);
-  if (rc)
-    {
-      fprintf (stderr, "%s: cannot open program filter stream: %s\n",
-              argv[0], mu_strerror (rc));
-      exit (1);
-    }
-
   MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
-  MU_ASSERT (mu_stream_open (out));
   
   read_and_print (stream, out);
   mu_stream_close (stream);
diff --git a/examples/musocio.c b/examples/musocio.c
index d19a200..31ca7d3 100644
--- a/examples/musocio.c
+++ b/examples/musocio.c
@@ -90,7 +90,6 @@ main (int argc, char * argv [])
   mu_stream_set_buffer (out, mu_buffer_line, 0);
   MU_ASSERT (mu_socket_stream_create (&sock, argv[1], MU_STREAM_RDWR));
   mu_stream_set_buffer (sock, mu_buffer_line, 0);
-  MU_ASSERT (mu_stream_open (sock));
   
   pid = fork ();
   if (pid == -1)
diff --git a/examples/pop3client.c b/examples/pop3client.c
index c924638..87f0c44 100644
--- a/examples/pop3client.c
+++ b/examples/pop3client.c
@@ -1030,15 +1030,6 @@ com_connect (int argc, char **argv)
            {
              mu_stream_t tlsstream;
              
-             status = mu_stream_open (tcp);
-             if (status)
-               {
-                 mu_error ("cannot open connection: %s",
-                           mu_stream_strerror (tcp, status));
-                 mu_stream_destroy (&tcp);
-                 return 0;
-               }
-
              status = mu_tls_client_stream_create (&tlsstream, tcp, tcp, 0);
              mu_stream_unref (tcp);
              if (status)
diff --git a/imap4d/append.c b/imap4d/append.c
index bf126b8..3ec431c 100644
--- a/imap4d/append.c
+++ b/imap4d/append.c
@@ -76,8 +76,7 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char 
*date_time, char *text,
   if (mu_message_create (&msg, &tm))
     return 1;
 
-  if (mu_memory_stream_create (&stream, MU_STREAM_RDWR)
-      || mu_stream_open (stream))
+  if (mu_memory_stream_create (&stream, MU_STREAM_RDWR))
     {
       mu_message_destroy (&msg, &tm);
       return 1;
diff --git a/imap4d/io.c b/imap4d/io.c
index e61a89a..14959da 100644
--- a/imap4d/io.c
+++ b/imap4d/io.c
@@ -98,14 +98,9 @@ imap4d_init_tls_server ()
   
   rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0);
   if (rc)
-    return 1;
-
-  rc = mu_stream_open (tlsstream);
-  if (rc)
     {
       mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"),
                      mu_stream_strerror (tlsstream, rc));
-      mu_stream_destroy (&tlsstream);
       return 1;
     }
 
diff --git a/imap4d/preauth.c b/imap4d/preauth.c
index 4c505b3..b876ea8 100644
--- a/imap4d/preauth.c
+++ b/imap4d/preauth.c
@@ -213,7 +213,6 @@ decode64_buf (const char *name, unsigned char **pbuf, 
size_t *psize)
   mu_memory_stream_create (&str, 0);
   mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE,
                    MU_STREAM_READ | MU_STREAM_AUTOCLOSE);
-  mu_stream_open (str);
   mu_stream_write (str, name, namelen, NULL);
   mu_stream_read (flt, buf, sizeof buf, &size);
   mu_stream_destroy (&flt);
@@ -357,14 +356,6 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr 
*srv_sa)
       return NULL;
     }
 
-  rc = mu_stream_open (stream);
-  if (rc)
-    {
-      mu_diag_output (MU_DIAG_INFO, _("cannot open TCP stream to %s:%d: %s"),
-                     hostaddr, ident_port, mu_strerror (rc));
-      return NULL;
-    }
-
   mu_stream_printf (stream, "%u , %u\n",
                    ntohs (clt_addr->sin_port),
                    ntohs (srv_addr->sin_port));
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index a8eb9c9..c076ade 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -99,6 +99,7 @@ int mu_stream_last_error (mu_stream_t stream);
 void mu_stream_clearerr (mu_stream_t stream);
 int mu_stream_seterr (struct _mu_stream *stream, int code, int perm);
 
+int mu_stream_is_open (mu_stream_t stream);
 int mu_stream_eof (mu_stream_t stream);
 int mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
                    mu_off_t *pres);
diff --git a/include/mailutils/sys/smtp.h b/include/mailutils/sys/smtp.h
index 0afe1e5..4099824 100644
--- a/include/mailutils/sys/smtp.h
+++ b/include/mailutils/sys/smtp.h
@@ -97,4 +97,8 @@ int _mu_smtp_mech_impl (mu_smtp_t smtp, mu_list_t list);
 int _mu_smtp_data_begin (mu_smtp_t smtp);
 int _mu_smtp_data_end (mu_smtp_t smtp);
 
+int _mu_smtp_get_streams (mu_smtp_t smtp, mu_stream_t *streams);
+int _mu_smtp_set_streams (mu_smtp_t smtp, mu_stream_t *streams);
+
+
 #endif
diff --git a/include/mailutils/sys/stream.h b/include/mailutils/sys/stream.h
index c3c405a..aa95f7e 100644
--- a/include/mailutils/sys/stream.h
+++ b/include/mailutils/sys/stream.h
@@ -17,12 +17,13 @@
 #ifndef _MAILUTILS_SYS_STREAM_H
 #define _MAILUTILS_SYS_STREAM_H
 
-#define _MU_STR_DIRTY         0x10000000    /* Buffer dirty */
-#define _MU_STR_WRT           0x20000000    /* Unflushed write pending */
-#define _MU_STR_ERR           0x40000000    /* Permanent error state */
-#define _MU_STR_EOF           0x80000000    /* EOF encountered */
+#define _MU_STR_OPEN          0x01000000    /* Stream open */
+#define _MU_STR_DIRTY         0x02000000    /* Buffer dirty */
+#define _MU_STR_WRT           0x04000000    /* Unflushed write pending */
+#define _MU_STR_ERR           0x08000000    /* Permanent error state */
+#define _MU_STR_EOF           0x10000000    /* EOF encountered */
 
-#define _MU_STR_INTERN_MASK   0xf0000000
+#define _MU_STR_INTERN_MASK   0xff000000
 
 #define _MU_STR_EVENT_SETFLAG   0
 #define _MU_STR_EVENT_CLRFLAG   1
diff --git a/lib/mailcap.c b/lib/mailcap.c
index 752a965..4a05484 100644
--- a/lib/mailcap.c
+++ b/lib/mailcap.c
@@ -602,16 +602,6 @@ find_entry (const char *file, struct mime_context *ctx)
       return -1;
     }
 
-  status = mu_stream_open (stream);
-  if (status)
-    {
-      mu_stream_destroy (&stream);
-      if (status != ENOENT)
-       mu_error ("cannot open file stream %s: %s",
-                 file, mu_strerror (status));
-      return -1;
-    }
-
   status = mu_mailcap_create (&mailcap, stream);
   if (status == 0)
     {
diff --git a/libmailutils/amd.c b/libmailutils/amd.c
index a0dec4e..a5dac3f 100644
--- a/libmailutils/amd.c
+++ b/libmailutils/amd.c
@@ -485,7 +485,8 @@ _amd_attach_message (mu_mailbox_t mailbox, struct 
_amd_message *mhm,
 
     str = (struct _amd_body_stream *)
               _mu_stream_create (sizeof (*str),
-                                mailbox->flags | MU_STREAM_SEEK);
+                                mailbox->flags | MU_STREAM_SEEK | 
+                                _MU_STR_OPEN);
     if (!str)
       {
        mu_body_destroy (&body, msg);
@@ -1596,13 +1597,7 @@ amd_message_stream_open (struct _amd_message *mhm)
   /* FIXME: Select buffer size dynamically */
   mu_stream_set_buffer (mhm->stream, mu_buffer_full, 16384);
   
-  status = mu_stream_open (mhm->stream);
-
-  if (status != 0)
-    mu_stream_destroy (&mhm->stream);
-
-  if (status == 0)
-    status = amd_scan_message (mhm);
+  status = amd_scan_message (mhm);
 
   return status;
 }
diff --git a/libmailutils/attachment.c b/libmailutils/attachment.c
index 6bed79f..c642681 100644
--- a/libmailutils/attachment.c
+++ b/libmailutils/attachment.c
@@ -104,16 +104,13 @@ mu_message_create_attachment (const char *content_type, 
const char *encoding,
                       mu_file_stream_create (&fstream, filename,
                                              MU_STREAM_READ)) == 0)
                    {
-                     if ((ret = mu_stream_open (fstream)) == 0)
+                     if ((ret =
+                          mu_filter_create (&tstream, fstream, encoding,
+                                            MU_FILTER_ENCODE,
+                                            MU_STREAM_READ)) == 0)
                        {
-                         if ((ret =
-                              mu_filter_create (&tstream, fstream, encoding,
-                                                MU_FILTER_ENCODE,
-                                                MU_STREAM_READ)) == 0)
-                           {
-                             mu_body_set_stream (body, tstream, *newmsg);
-                             mu_message_set_header (*newmsg, hdr, NULL);
-                           }
+                         mu_body_set_stream (body, tstream, *newmsg);
+                         mu_message_set_header (*newmsg, hdr, NULL);
                        }
                    }
                }
@@ -293,30 +290,27 @@ mu_message_save_attachment (mu_message_t msg, const char 
*filename,
              mu_file_stream_create (&info->fstream, fname,
                                     MU_STREAM_WRITE | MU_STREAM_CREAT)) == 0)
        {
-         if ((ret = mu_stream_open (info->fstream)) == 0)
+         char *content_encoding;
+         char *content_encoding_mem = NULL;
+         
+         mu_header_get_value (hdr, "Content-Transfer-Encoding", NULL, 0,
+                              &size);
+         if (size)
            {
-             char *content_encoding;
-             char *content_encoding_mem = NULL;
-
-             mu_header_get_value (hdr, "Content-Transfer-Encoding", NULL, 0,
-                                  &size);
-             if (size)
-               {
-                 content_encoding_mem = malloc (size + 1);
-                 if (content_encoding_mem == NULL)
-                   ret = ENOMEM;
-                 content_encoding = content_encoding_mem;
-                 mu_header_get_value (hdr, "Content-Transfer-Encoding",
-                                      content_encoding, size + 1, 0);
-               }
-             else
-               content_encoding = "7bit";
-             ret =
-               mu_filter_create (&info->stream, istream, content_encoding,
-                                 MU_FILTER_DECODE,
-                                 MU_STREAM_READ);
-             free (content_encoding_mem);
+             content_encoding_mem = malloc (size + 1);
+             if (content_encoding_mem == NULL)
+               ret = ENOMEM;
+             content_encoding = content_encoding_mem;
+             mu_header_get_value (hdr, "Content-Transfer-Encoding",
+                                  content_encoding, size + 1, 0);
            }
+         else
+           content_encoding = "7bit";
+         ret =
+           mu_filter_create (&info->stream, istream, content_encoding,
+                             MU_FILTER_DECODE,
+                             MU_STREAM_READ);
+         free (content_encoding_mem);
        }
     }
   if (info->stream && istream)
diff --git a/libmailutils/body.c b/libmailutils/body.c
index f076e4a..05b47f1 100644
--- a/libmailutils/body.c
+++ b/libmailutils/body.c
@@ -173,7 +173,7 @@ _body_get_stream (mu_body_t body, mu_stream_t *pstream, int 
ref)
          struct _mu_body_stream *str =
            (struct _mu_body_stream *)
            _mu_stream_create (sizeof (*str),
-                              MU_STREAM_RDWR|MU_STREAM_SEEK);
+                              MU_STREAM_RDWR|MU_STREAM_SEEK|_MU_STR_OPEN);
          if (!str)
            return ENOMEM;
          
@@ -184,9 +184,6 @@ _body_get_stream (mu_body_t body, mu_stream_t *pstream, int 
ref)
          if (status != 0)
            return status;
          mu_stream_set_buffer (body->fstream, mu_buffer_full, 0);
-         status = mu_stream_open (body->fstream);
-         if (status != 0)
-           return status;
          str->stream.ctl = _body_ioctl;
          str->stream.read = _body_read;
          str->stream.write = _body_write;
diff --git a/libmailutils/cfg_driver.c b/libmailutils/cfg_driver.c
index f4d56f7..f07a22f 100644
--- a/libmailutils/cfg_driver.c
+++ b/libmailutils/cfg_driver.c
@@ -590,7 +590,6 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char 
*progname,
     {
       mu_stream_t stream;
       mu_stdio_stream_create (&stream, MU_STDERR_FD, 0);
-      mu_stream_open (stream);
       mu_cfg_format_parse_tree (stream, parse_tree, MU_CFG_FMT_LOCUS);
       mu_stream_destroy (&stream);
     }
diff --git a/libmailutils/dbgstream.c b/libmailutils/dbgstream.c
index 18f8834..b784813 100644
--- a/libmailutils/dbgstream.c
+++ b/libmailutils/dbgstream.c
@@ -66,6 +66,8 @@ int
 mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, mu_log_level_t level,
                    int flags)
 {
+  int rc;
+  mu_stream_t stream;
   struct _mu_dbgstream *sp;
 
   sp = (struct _mu_dbgstream *)
@@ -79,8 +81,13 @@ mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, 
mu_log_level_t level,
   
   sp->debug = debug;
   sp->level = level;
-  mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 0);
-  *pref = (mu_stream_t) sp;
-  return 0;
+  stream = (mu_stream_t) sp;
+  mu_stream_set_buffer (stream, mu_buffer_line, 0);
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pref = stream;
+  return rc;
 }
   
diff --git a/libmailutils/errors b/libmailutils/errors
index 7828f20..8593c79 100644
--- a/libmailutils/errors
+++ b/libmailutils/errors
@@ -29,7 +29,7 @@ MU_ERR_MBX_NULL             _("Mailbox null")
 MU_ERR_MBX_REMOVED          _("Mailbox removed")
 
 MU_ERR_NOT_OPEN             _("Resource not open")
-MU_ERR_OPEN                 _("Resource still open")
+MU_ERR_OPEN                 _("Resource is already open")
 
 MU_ERR_BAD_822_FORMAT       _("Format of RFC822 object is bad")
 MU_ERR_EMPTY_ADDRESS        _("Address contains no addr specs")
diff --git a/libmailutils/file_stream.c b/libmailutils/file_stream.c
index 814e80d..247768c 100644
--- a/libmailutils/file_stream.c
+++ b/libmailutils/file_stream.c
@@ -295,8 +295,13 @@ mu_file_stream_create (mu_stream_t *pstream, const char 
*filename, int flags)
                                   flags | MU_STREAM_SEEK | 
MU_STREAM_AUTOCLOSE);
   if (rc == 0)
     {
-      *pstream = (mu_stream_t) fstr;
-      mu_stream_set_buffer ((mu_stream_t) fstr, mu_buffer_full, 0);
+      mu_stream_t stream = (mu_stream_t) fstr;
+      mu_stream_set_buffer (stream, mu_buffer_full, 0);
+      rc = mu_stream_open (stream);
+      if (rc)
+       mu_stream_unref (stream);
+      else
+       *pstream = stream;
     }
   return rc;
 }
@@ -310,8 +315,13 @@ mu_fd_stream_create (mu_stream_t *pstream, char *filename, 
int fd, int flags)
                                   filename, fd, flags);
   if (rc == 0)
     {
-      *pstream = (mu_stream_t) fstr;
-      mu_stream_set_buffer ((mu_stream_t) fstr, mu_buffer_full, 0);
+      mu_stream_t stream = (mu_stream_t) fstr;
+      mu_stream_set_buffer (stream, mu_buffer_full, 0);
+      rc = mu_stream_open (stream);
+      if (rc)
+       mu_stream_unref (stream);
+      else
+       *pstream = stream;
     }
   return rc;
 }
diff --git a/libmailutils/filter_iconv.c b/libmailutils/filter_iconv.c
index d47bb17..571e8b7 100644
--- a/libmailutils/filter_iconv.c
+++ b/libmailutils/filter_iconv.c
@@ -434,7 +434,9 @@ mu_filter_iconv_create (mu_stream_t *s, mu_stream_t 
transport,
 {
   struct icvt_stream *iptr;
   iconv_t cd;
-  
+  int rc;
+  mu_stream_t stream;
+    
   cd = iconv_open (tocode, fromcode);
   if (cd == (iconv_t) -1)
     return MU_ERR_FAILURE;
@@ -470,6 +472,11 @@ mu_filter_iconv_create (mu_stream_t *s, mu_stream_t 
transport,
   iptr->stream.wait = _icvt_wait;
   iptr->stream.seek = _icvt_seek;
   iptr->stream.flags = MU_STREAM_READ | MU_STREAM_SEEK;
-  *s = (mu_stream_t)iptr;
+  stream = (mu_stream_t)iptr;
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *s = stream;
   return 0;
 }
diff --git a/libmailutils/fltstream.c b/libmailutils/fltstream.c
index 4359e03..f6fe6ad 100644
--- a/libmailutils/fltstream.c
+++ b/libmailutils/fltstream.c
@@ -480,6 +480,7 @@ mu_filter_stream_create (mu_stream_t *pflt,
   if (!fs)
     return ENOMEM;
   
+  flags |= _MU_STR_OPEN;
   if (flags & MU_STREAM_READ)
     {
       fs->stream.read = filter_read;
diff --git a/libmailutils/header.c b/libmailutils/header.c
index 2861c67..7c95e08 100644
--- a/libmailutils/header.c
+++ b/libmailutils/header.c
@@ -1086,12 +1086,6 @@ header_write (mu_stream_t os, const char *buf, size_t 
buflen, size_t *pnwrite)
       status = mu_memory_stream_create (&header->mstream, MU_STREAM_RDWR);
       if (status)
        return status;
-      status = mu_stream_open (header->mstream);
-      if (status)
-       {
-         mu_stream_destroy (&header->mstream);
-         return status;
-       }
     }
 
   status = mu_stream_write (header->mstream, buf, buflen, NULL);
diff --git a/libmailutils/iostream.c b/libmailutils/iostream.c
index 6608312..d2185f7 100644
--- a/libmailutils/iostream.c
+++ b/libmailutils/iostream.c
@@ -261,6 +261,7 @@ mu_iostream_create (mu_stream_t *pref, mu_stream_t in, 
mu_stream_t out)
   if (!sp)
     return ENOMEM;
 
+  sp->stream.flags |= _MU_STR_OPEN;
   sp->stream.read = _iostream_read; 
   if (in->readdelim)
     sp->stream.readdelim = _iostream_readdelim; 
diff --git a/libmailutils/mailcap.c b/libmailutils/mailcap.c
index d9e96f2..8d8c700 100644
--- a/libmailutils/mailcap.c
+++ b/libmailutils/mailcap.c
@@ -672,70 +672,66 @@ int main()
                                  MU_STREAM_READ);
   if (status == 0)
     {
-      status = mu_stream_open (stream);
+      mu_mailcap_t mailcap;
+      status = mu_mailcap_create (&mailcap, stream);
       if (status == 0)
        {
-         mu_mailcap_t mailcap;
-         status = mu_mailcap_create (&mailcap, stream);
-         if (status == 0)
+         int i, n;
+         size_t count = 0;
+         char buffer[256];
+         
+         mu_mailcap_entries_count (mailcap, &count);
+         for (i = 1; i <= count; i++)
            {
-             int i, n;
-             size_t count = 0;
-             char buffer[256];
-
-             mu_mailcap_entries_count (mailcap, &count);
-             for (i = 1; i <= count; i++)
-               {
-                 int j;
-                 mu_mailcap_entry_t entry = NULL;
-                 int fields_count = 0;
-
-                 printf ("entry[%d]\n", i);
+             int j;
+             mu_mailcap_entry_t entry = NULL;
+             int fields_count = 0;
+             
+             printf ("entry[%d]\n", i);
 #if 1
-
-                 mu_mailcap_get_entry (mailcap, i, &entry);
-                 /* Print typefield.  */
-                 mu_mailcap_entry_get_typefield (entry, buffer,
-                                                 sizeof (buffer), NULL);
-                 printf ("\ttypefield: %s\n", buffer);
-
-                 /* Print view-command.  */
-                 mu_mailcap_entry_get_viewcommand (entry, buffer,
-                                                   sizeof (buffer), NULL);
-                 printf ("\tview-command: %s\n", buffer);
-
-                 /* Print fields.  */
-                 mu_mailcap_entry_fields_count (entry, &fields_count);
-                 for (j = 1; j <= fields_count; j++)
-                   {
-                     mu_mailcap_entry_get_field (entry, j, buffer,
-                                                 sizeof (buffer), NULL);
-                     printf("\tfields[%d]: %s\n", j, buffer);
-                   }
-                 n = 0;
-                 mu_mailcap_entry_get_compose (entry, buffer,
-                                               sizeof (buffer), &n);
-                 if (n > 0)
-                   {
-                     printf("\tcompose[%s]\n", buffer);
-                   }
-                 printf("\n");
+             
+             mu_mailcap_get_entry (mailcap, i, &entry);
+             /* Print typefield.  */
+             mu_mailcap_entry_get_typefield (entry, buffer,
+                                             sizeof (buffer), NULL);
+             printf ("\ttypefield: %s\n", buffer);
+             
+             /* Print view-command.  */
+             mu_mailcap_entry_get_viewcommand (entry, buffer,
+                                               sizeof (buffer), NULL);
+             printf ("\tview-command: %s\n", buffer);
+             
+             /* Print fields.  */
+             mu_mailcap_entry_fields_count (entry, &fields_count);
+             for (j = 1; j <= fields_count; j++)
+               {
+                 mu_mailcap_entry_get_field (entry, j, buffer,
+                                             sizeof (buffer), NULL);
+                 printf("\tfields[%d]: %s\n", j, buffer);
+               }
+             n = 0;
+             mu_mailcap_entry_get_compose (entry, buffer,
+                                           sizeof (buffer), &n);
+             if (n > 0)
+               {
+                 printf("\tcompose[%s]\n", buffer);
                }
+             printf("\n");
+           }
 #else
-             for (i = 0; i < mailcap->entries_count; i++)
+         for (i = 0; i < mailcap->entries_count; i++)
+           {
+             int j;
+             mu_mailcap_entry_t entry = mailcap->entries[i];
+             printf("[%s];[%s]", entry->typefield, entry->viewcommand);
+             for (j = 0; j < entry->fields_count; j++)
                {
-                 int j;
-                 mu_mailcap_entry_t entry = mailcap->entries[i];
-                 printf("[%s];[%s]", entry->typefield, entry->viewcommand);
-                 for (j = 0; j < entry->fields_count; j++)
-                   {
-                     printf(";[%s]", entry->fields[j]);
-                   }
-                 printf("\n");
+                 printf(";[%s]", entry->fields[j]);
                }
-#endif
-             mu_mailcap_destroy (&mailcap);
+             printf("\n");
            }
+#endif
+         mu_mailcap_destroy (&mailcap);
        }
     }
   return 0;
diff --git a/libmailutils/mapfile_stream.c b/libmailutils/mapfile_stream.c
index 8733622..3cd7c6d 100644
--- a/libmailutils/mapfile_stream.c
+++ b/libmailutils/mapfile_stream.c
@@ -344,6 +344,8 @@ mu_mapfile_stream_create (mu_stream_t *pstream, const char 
*filename,
 #ifndef _POSIX_MAPPED_FILES
   return ENOSYS;
 #else
+  int rc;
+  mu_stream_t stream;
   struct _mu_mapfile_stream *str =
     (struct _mu_mapfile_stream *) _mu_stream_create (sizeof (*str),
                                                     flags | MU_STREAM_SEEK);
@@ -369,9 +371,14 @@ mu_mapfile_stream_create (mu_stream_t *pstream, const char 
*filename,
   str->stream.flush = _mapfile_flush;
   str->stream.done = _mapfile_done;
   str->stream.seek = _mapfile_seek;
-  
-  *pstream = (mu_stream_t) str;
-  return 0;
+
+  stream = (mu_stream_t) str;
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+  return rc;
 #endif
 }
 
diff --git a/libmailutils/memory_stream.c b/libmailutils/memory_stream.c
index 98db753..67952bc 100644
--- a/libmailutils/memory_stream.c
+++ b/libmailutils/memory_stream.c
@@ -131,16 +131,16 @@ static int
 _memory_open (mu_stream_t stream)
 {
   struct _mu_memory_stream *mfs = (struct _mu_memory_stream *) stream;
-  int status = 0;
 
   /* Close any previous stream. */
   if (mfs->ptr)
     free (mfs->ptr);
   mfs->ptr = NULL;
   mfs->size = 0;
+  mfs->offset = 0;
   mfs->capacity = 0;
-
-  return status;
+  
+  return 0;
 }
 
 static int
@@ -192,6 +192,8 @@ _memory_seek (struct _mu_stream *stream, mu_off_t off, 
mu_off_t *presult)
 int
 mu_memory_stream_create (mu_stream_t *pstream, int flags)
 {
+  int rc;
+  mu_stream_t stream;
   struct _mu_memory_stream *str;
 
   if (!flags)
@@ -202,11 +204,6 @@ mu_memory_stream_create (mu_stream_t *pstream, int flags)
   if (!str)
     return ENOMEM;
 
-  str->ptr = NULL;
-  str->size = 0;
-  str->offset = 0;
-  str->capacity = 0;
-
   str->stream.open = _memory_open;
   str->stream.close = _memory_close;
   str->stream.read = _memory_read;
@@ -216,9 +213,14 @@ mu_memory_stream_create (mu_stream_t *pstream, int flags)
   str->stream.done = _memory_done;
   str->stream.ctl = _memory_ioctl;
   str->stream.seek = _memory_seek;
-
-  *pstream = (mu_stream_t) str;
-
-  return 0;
+  
+  stream = (mu_stream_t) str;
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+
+  return rc;
 }
   
diff --git a/libmailutils/message.c b/libmailutils/message.c
index f276d0a..caeba8f 100644
--- a/libmailutils/message.c
+++ b/libmailutils/message.c
@@ -278,7 +278,9 @@ _message_stream_create (mu_stream_t *pmsg, mu_message_t 
msg, int flags)
   struct _mu_message_stream *sp;
 
   sp = (struct _mu_message_stream *) _mu_stream_create (sizeof (*sp),
-                                                       flags | MU_STREAM_SEEK);
+                                                       flags |
+                                                       MU_STREAM_SEEK |
+                                                       _MU_STR_OPEN);
   if (!sp)
     return ENOMEM;
 
diff --git a/libmailutils/message_stream.c b/libmailutils/message_stream.c
index 30c440d..6bfdae5 100644
--- a/libmailutils/message_stream.c
+++ b/libmailutils/message_stream.c
@@ -324,11 +324,12 @@ _message_error_string (struct _mu_stream *stream, int rc)
 }
 
 int
-mu_message_stream_create (mu_stream_t *stream, mu_stream_t src, int flags)
+mu_message_stream_create (mu_stream_t *pstream, mu_stream_t src, int flags)
 {
   struct _mu_message_stream *s;
   int sflag;
   int rc;
+  mu_stream_t stream;
   
   mu_stream_get_flags (src, &sflag);
   sflag &= MU_STREAM_SEEK;
@@ -355,8 +356,14 @@ mu_message_stream_create (mu_stream_t *stream, mu_stream_t 
src, int flags)
   s->stream.size = _message_size;
   s->stream.seek = _message_seek;
   s->stream.error_string = _message_error_string;
-  *stream = (mu_stream_t)s;
-  return 0;  
+
+  stream = (mu_stream_t)s;
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+  return rc;
 }
 
 
@@ -392,12 +399,6 @@ mu_stream_to_message (mu_stream_t instream, mu_message_t 
*pmsg)
   if ((rc = mu_message_stream_create (&draftstream, instream, 0)))
     return rc;
 
-  if ((rc = mu_stream_open (draftstream)))
-    {
-      mu_stream_destroy (&draftstream);
-      return rc;
-    }
-
   if ((rc = mu_message_create (&msg, draftstream)))
     {
       mu_stream_destroy (&draftstream);
diff --git a/libmailutils/mimehdr.c b/libmailutils/mimehdr.c
index 0314734..dd5eb34 100644
--- a/libmailutils/mimehdr.c
+++ b/libmailutils/mimehdr.c
@@ -525,10 +525,6 @@ mu_mimehdr_decode_param (const char *value, int flags,
                  if (rc)
                    break;
                  
-                 rc = mu_stream_open (cvt);
-                 if (rc)
-                   break;
-
                  while (mu_stream_read (cvt, iobuf, sizeof (iobuf),
                                         &nbytes) == 0
                         && nbytes)
diff --git a/libmailutils/mutil.c b/libmailutils/mutil.c
index aa11d56..5342523 100644
--- a/libmailutils/mutil.c
+++ b/libmailutils/mutil.c
@@ -1333,13 +1333,8 @@ mu_decode_filter (mu_stream_t *pfilter, mu_stream_t 
input,
                                       0, mu_default_fallback_mode);
       if (status == 0)
        {
-         if (mu_stream_open (cvt))
-           mu_stream_destroy (&cvt);
-         else
-            {
-              mu_stream_unref (filter);
-              filter = cvt;
-           }
+          mu_stream_unref (filter);
+          filter = cvt;
        }
     }
   *pfilter = filter;
diff --git a/libmailutils/prog_stream.c b/libmailutils/prog_stream.c
index 7ef63a3..b789def 100644
--- a/libmailutils/prog_stream.c
+++ b/libmailutils/prog_stream.c
@@ -307,12 +307,6 @@ _prog_open (mu_stream_t stream)
          _prog_close (stream);
          return rc;
        }
-      rc = mu_stream_open (fs->in);
-      if (rc)
-       {
-         _prog_close (stream);
-         return rc;
-       }
     }
   
   if (REDIRECT_STDIN_P (flags))
@@ -324,12 +318,6 @@ _prog_open (mu_stream_t stream)
          _prog_close (stream);
          return rc;
        }
-      rc = mu_stream_open (fs->out);
-      if (rc)
-       {
-         _prog_close (stream);
-         return rc;
-       }
     }
 
   _prog_stream_register (fs);
@@ -428,21 +416,32 @@ _prog_stream_create (const char *progname, int flags)
 int
 mu_prog_stream_create (mu_stream_t *pstream, const char *progname, int flags)
 {
+  int rc;
+  mu_stream_t stream;
+  
   if (pstream == NULL)
     return MU_ERR_OUT_PTR_NULL;
 
   if (progname == NULL)
     return EINVAL;
 
-  if ((*pstream = (mu_stream_t) _prog_stream_create (progname, flags)) == NULL)
+  if ((stream = (mu_stream_t) _prog_stream_create (progname, flags)) == NULL)
     return ENOMEM;
-  return 0;
+
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+  return rc;
 }
 
 int
 mu_filter_prog_stream_create (mu_stream_t *pstream, const char *progname,
                              mu_stream_t input)
 {
+  int rc;
+  mu_stream_t stream;
   struct _mu_prog_stream *fs;
 
   if (pstream == NULL)
@@ -456,7 +455,12 @@ mu_filter_prog_stream_create (mu_stream_t *pstream, const 
char *progname,
     return ENOMEM;
   mu_stream_ref (input);
   fs->input = input;
-  *pstream = (mu_stream_t) fs;
-  return 0;
+  stream = (mu_stream_t) fs;
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+  return rc;
 }
 
diff --git a/libmailutils/rdcache_stream.c b/libmailutils/rdcache_stream.c
index 4789811..c1d0013 100644
--- a/libmailutils/rdcache_stream.c
+++ b/libmailutils/rdcache_stream.c
@@ -183,7 +183,7 @@ mu_rdcache_stream_create (mu_stream_t *pstream, mu_stream_t 
transport,
     return EINVAL;
   
   sp = (struct _mu_rdcache_stream *)
-          _mu_stream_create (sizeof (*sp), sflags);
+          _mu_stream_create (sizeof (*sp), sflags | _MU_STR_OPEN);
   if (!sp)
     return ENOMEM;
 
@@ -200,8 +200,7 @@ mu_rdcache_stream_create (mu_stream_t *pstream, mu_stream_t 
transport,
     mu_stream_ref (transport);
   sp->transport = transport;
 
-  if ((rc = mu_memory_stream_create (&sp->cache, MU_STREAM_RDWR))
-      || (rc = mu_stream_open (sp->cache)))
+  if ((rc = mu_memory_stream_create (&sp->cache, MU_STREAM_RDWR)))
     {
       mu_stream_destroy ((mu_stream_t*) &sp);
       return rc;
diff --git a/libmailutils/socket_stream.c b/libmailutils/socket_stream.c
index 2764b2b..825a9da 100644
--- a/libmailutils/socket_stream.c
+++ b/libmailutils/socket_stream.c
@@ -117,6 +117,10 @@ mu_socket_stream_create (mu_stream_t *pstream, const char 
*filename, int flags)
       transport = str;
     }
 
-  *pstream = transport;
-  return 0;
+  rc = mu_stream_open (transport);
+  if (rc)
+    mu_stream_unref (transport);
+  else
+    *pstream = transport;
+  return rc;
 }
diff --git a/libmailutils/stdio_stream.c b/libmailutils/stdio_stream.c
index f525d9c..f9a5660 100644
--- a/libmailutils/stdio_stream.c
+++ b/libmailutils/stdio_stream.c
@@ -63,6 +63,7 @@ mu_stdio_stream_create (mu_stream_t *pstream, int fd, int 
flags)
                               filename, fd, flags & ~MU_STREAM_SEEK);
   if (rc)
     return rc;
+  fstr->stream.flags |= _MU_STR_OPEN;
   fstr->stream.open = NULL;
   transport = (mu_stream_t) fstr;
   mu_stream_set_buffer (transport, mu_buffer_line, 0);
diff --git a/libmailutils/stream.c b/libmailutils/stream.c
index 92faeb4..2dfbc82 100644
--- a/libmailutils/stream.c
+++ b/libmailutils/stream.c
@@ -249,7 +249,7 @@ _mu_stream_create (size_t size, int flags)
   if (size < sizeof (str))
     abort ();
   str = mu_zalloc (size);
-  str->flags = flags & ~_MU_STR_INTERN_MASK;
+  str->flags = flags & ~(_MU_STR_INTERN_MASK & ~_MU_STR_OPEN);
   mu_stream_ref (str);
   return str;
 }
@@ -289,21 +289,34 @@ mu_stream_unref (mu_stream_t stream)
   mu_stream_destroy (&stream);
 }
 
+static void
+_stream_init (mu_stream_t stream)
+{
+  stream->bytes_in = stream->bytes_out = 0;
+  stream->flags &= ~_MU_STR_INTERN_MASK;
+  _stream_setflag (stream, _MU_STR_OPEN);
+  stream->offset = 0;
+  stream->level = stream->pos = 0;
+  stream->last_err = 0;
+}  
+
 int
 mu_stream_open (mu_stream_t stream)
 {
   int rc;
 
+  if (stream->flags & _MU_STR_OPEN)
+    return MU_ERR_OPEN;
   if (stream->open)
     {
       if ((rc = stream->open (stream)))
        return mu_stream_seterr (stream, rc, 1);
-      if ((stream->flags & (MU_STREAM_APPEND|MU_STREAM_SEEK)) ==
-         (MU_STREAM_APPEND|MU_STREAM_SEEK) &&
-         (rc = mu_stream_seek (stream, 0, MU_SEEK_END, NULL)))
-       return mu_stream_seterr (stream, rc, 1);
     }
-  stream->bytes_in = stream->bytes_out = 0;
+  _stream_init (stream);
+  if ((stream->flags & (MU_STREAM_APPEND|MU_STREAM_SEEK)) ==
+      (MU_STREAM_APPEND|MU_STREAM_SEEK) &&
+      (rc = mu_stream_seek (stream, 0, MU_SEEK_END, NULL)))
+    return mu_stream_seterr (stream, rc, 1);
   return 0;
 }
 
@@ -345,12 +358,25 @@ mu_stream_eof (mu_stream_t stream)
 }
 
 int
+mu_stream_is_open (mu_stream_t stream)
+{
+  return stream->flags & _MU_STR_OPEN;
+}
+
+int
 mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
                mu_off_t *pres)
 {    
   int rc;
   mu_off_t size;
   
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+  
   if (!stream->seek)
     return mu_stream_seterr (stream, ENOSYS, 0);
 
@@ -654,6 +680,13 @@ _stream_write_unbuffered (mu_stream_t stream,
 int
 mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
 {
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+  
   if (stream->buftype == mu_buffer_none)
     return _stream_read_unbuffered (stream, buf, size, !pread, pread);
   else
@@ -770,6 +803,13 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t 
size,
   if (size == 0)
     return EINVAL;
 
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+
   if (stream->buftype == mu_buffer_none)
     {
       if (stream->readdelim)
@@ -803,6 +843,13 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, 
size_t *psize,
   size_t n = *psize;
   size_t cur_len = 0;
     
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+
   if (lineptr == NULL || n == 0)
     {
       char *new_lineptr;
@@ -883,6 +930,13 @@ mu_stream_write (mu_stream_t stream, const void *buf, 
size_t size,
 {
   int rc = 0;
   
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+
   if (stream->buftype == mu_buffer_none)
     rc = _stream_write_unbuffered (stream, buf, size,
                                   !pnwritten, pnwritten);
@@ -937,6 +991,12 @@ mu_stream_flush (mu_stream_t stream)
   
   if (!stream)
     return EINVAL;
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
   rc = _stream_flush_buffer (stream, 1);
   if (rc)
     return rc;
@@ -953,6 +1013,8 @@ mu_stream_close (mu_stream_t stream)
     
   if (!stream)
     return EINVAL;
+  if (!(stream->flags & _MU_STR_OPEN))
+    return MU_ERR_NOT_OPEN;
   
   mu_stream_flush (stream);
   /* Do close the stream only if it is not used by anyone else */
@@ -961,6 +1023,7 @@ mu_stream_close (mu_stream_t stream)
   _stream_event (stream, _MU_STR_EVENT_CLOSE, 0, NULL);
   if (stream->close)
     rc = stream->close (stream);
+  _stream_clrflag (stream, _MU_STR_OPEN);
   return rc;
 }
 
@@ -969,6 +1032,12 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
 {
   int rc;
     
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
   if (!stream->size)
     return mu_stream_seterr (stream, ENOSYS, 0);
   rc = stream->size (stream, psize);
@@ -999,9 +1068,21 @@ int
 mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
 {
   int flg = 0;
+
   if (stream == NULL)
     return EINVAL;
-  
+#if 0
+  /* NOTE: Sometimes mu_stream_wait is called after a failed mu_stream_open.
+     In particular, this is needed for a TCP stream opened with a
+     MU_STREAM_NONBLOCK flag (see examples/http.c).  Until a better
+     solution is found, this check is commented out. */
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+#endif
   /* Take to acount if we have any buffering.  */
   /* FIXME: How about MU_STREAM_READY_WR? */
   if ((*pflags) & MU_STREAM_READY_RD 
@@ -1026,6 +1107,13 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct 
timeval *tvp)
 int
 mu_stream_truncate (mu_stream_t stream, mu_off_t size)
 {
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+  
   if (stream->truncate)
     {
       int rc;
@@ -1040,6 +1128,13 @@ mu_stream_truncate (mu_stream_t stream, mu_off_t size)
 int
 mu_stream_shutdown (mu_stream_t stream, int how)
 {
+  if (!(stream->flags & _MU_STR_OPEN))
+    {
+      if (stream->open)
+       return MU_ERR_NOT_OPEN;
+      _stream_init (stream);
+    }
+  
   if (stream->shutdown)
     return stream->shutdown (stream, how);
   return ENOSYS;
diff --git a/libmailutils/streamref.c b/libmailutils/streamref.c
index 83f401e..e860a55 100644
--- a/libmailutils/streamref.c
+++ b/libmailutils/streamref.c
@@ -272,7 +272,8 @@ mu_streamref_create_abridged (mu_stream_t *pref, 
mu_stream_t str,
     return rc;
   mu_stream_get_flags (str, &flags);
   sp = (struct _mu_streamref *)
-         _mu_stream_create (sizeof (*sp), flags & ~MU_STREAM_AUTOCLOSE);
+         _mu_stream_create (sizeof (*sp), 
+                            (flags & ~MU_STREAM_AUTOCLOSE) | _MU_STR_OPEN);
   if (!sp)
     return ENOMEM;
 
diff --git a/libmailutils/tcp.c b/libmailutils/tcp.c
index ba15ae8..aea7809 100644
--- a/libmailutils/tcp.c
+++ b/libmailutils/tcp.c
@@ -304,11 +304,13 @@ _create_tcp_stream (int flags)
 }
 
 int
-mu_tcp_stream_create_with_source_ip (mu_stream_t *stream,
+mu_tcp_stream_create_with_source_ip (mu_stream_t *pstream,
                                     const char *host, int port,
                                     unsigned long source_ip,
                                     int flags)
 {
+  int rc;
+  mu_stream_t stream;
   struct _tcp_instance *tcp;
 
   if (host == NULL)
@@ -329,8 +331,13 @@ mu_tcp_stream_create_with_source_ip (mu_stream_t *stream,
   tcp->port = port;
   tcp->state = TCP_STATE_INIT;
   tcp->source_addr = source_ip;
-  *stream = (mu_stream_t) tcp;
-  return 0;
+  stream = (mu_stream_t) tcp;
+  rc = mu_stream_open (stream);
+  if (rc == 0 || rc == EAGAIN || rc == EINPROGRESS)
+    *pstream = stream;
+  else
+    mu_stream_destroy (&stream);
+  return rc;
 }
 
 int
diff --git a/libmailutils/temp_file_stream.c b/libmailutils/temp_file_stream.c
index c5346b2..857bada 100644
--- a/libmailutils/temp_file_stream.c
+++ b/libmailutils/temp_file_stream.c
@@ -49,7 +49,7 @@ mu_temp_file_stream_create (mu_stream_t *pstream, const char 
*dir)
 {
   int rc;
   struct _mu_file_stream *str;
-
+  mu_stream_t stream;
   rc = _mu_file_stream_create (&str,
                               sizeof (struct _mu_file_stream),
                               dir,
@@ -57,9 +57,16 @@ mu_temp_file_stream_create (mu_stream_t *pstream, const char 
*dir)
                               MU_STREAM_RDWR | MU_STREAM_SEEK |
                               MU_STREAM_CREAT | 
                               MU_STREAM_AUTOCLOSE);
-
-  str->stream.open = fd_temp_open;
-  str->flags = _MU_FILE_STREAM_TEMP;
-  *pstream = (mu_stream_t) str;
+  if (rc == 0)
+    {
+      str->stream.open = fd_temp_open;
+      str->flags = _MU_FILE_STREAM_TEMP;
+      stream = (mu_stream_t) str;
+      rc = mu_stream_open (stream);
+      if (rc)
+       mu_stream_unref (stream);
+      else
+       *pstream = stream;
+    }
   return 0;
 }
diff --git a/libmailutils/tests/fltst.c b/libmailutils/tests/fltst.c
index 6e36ede..8597dd5 100644
--- a/libmailutils/tests/fltst.c
+++ b/libmailutils/tests/fltst.c
@@ -153,10 +153,7 @@ main (int argc, char * argv [])
     }
   
   MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
-  MU_ASSERT (mu_stream_open (in));
-
   MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
-  MU_ASSERT (mu_stream_open (out));
 
   if (line_length_option)
     reset_line_length (fltname, line_length);
diff --git a/libmailutils/tests/mailcap.c b/libmailutils/tests/mailcap.c
index c4f8818..136b971 100644
--- a/libmailutils/tests/mailcap.c
+++ b/libmailutils/tests/mailcap.c
@@ -42,14 +42,6 @@ main (int argc, char **argv)
       exit (1);
     }
 
-  status = mu_stream_open (stream);
-  if (status)
-    {
-      mu_error ("cannot open input stream: %s",
-               mu_strerror (status));
-      exit (1);
-    }
-
   status = mu_mailcap_create (&mailcap, stream);
   if (status == 0)
     {
diff --git a/libmailutils/vartab.c b/libmailutils/vartab.c
index 7364ba8..566a507 100644
--- a/libmailutils/vartab.c
+++ b/libmailutils/vartab.c
@@ -227,7 +227,6 @@ mu_vartab_expand (mu_vartab_t vt, const char *str, char 
**pres)
       rc = mu_memory_stream_create (&vt->stream, 0);
       if (rc)
        return rc;
-      rc = mu_stream_open (vt->stream);
     }
   else
     mu_stream_truncate (vt->stream, 0);
diff --git a/libmailutils/wicket.c b/libmailutils/wicket.c
index 82b179b..8b0fbbb 100644
--- a/libmailutils/wicket.c
+++ b/libmailutils/wicket.c
@@ -249,72 +249,69 @@ get_ticket_url (mu_ticket_t ticket, mu_url_t url, 
mu_url_t *pticket_url)
   struct file_ticket *ft = mu_ticket_get_data (ticket);
   int rc;
   mu_url_t u = NULL;
+  char *buf = NULL;
+  size_t bufsize = 0;
+  size_t len;
   
   rc = mu_file_stream_create (&stream, ft->filename, MU_STREAM_READ);
   if (rc)
     return rc;
-  rc = mu_stream_open (stream);
-  if (rc == 0)
+    
+  while ((rc = mu_stream_getline (stream, &buf, &bufsize, &len)) == 0
+        && len > 0)
     {
-      char *buf = NULL;
-      size_t bufsize = 0;
-      size_t len;
-
-      while ((rc = mu_stream_getline (stream, &buf, &bufsize, &len)) == 0
-            && len > 0)
+      char *p;
+      int err;
+      
+      /* Truncate a trailing newline. */
+      if (len && buf[len - 1] == '\n')
+       buf[--len] = 0;
+      
+      /* Skip leading spaces  */
+      for (p = buf; *p == ' ' || *p == '\t'; p++)
+       ;
+      /* Skip trailing spaces */
+      for (; len > 0 && (p[len-1] == ' ' || p[len-1] == '\t'); )
+       p[--len] = 0;
+      
+      /* Skip empty lines and comments. */
+      if (*p == 0 || *p == '#')
+       continue;
+      
+      if ((err = mu_url_create (&u, p)) != 0)
        {
-         char *p;
-         int err;
-         
-         /* Truncate a trailing newline. */
-         if (len && buf[len - 1] == '\n')
-           buf[--len] = 0;
-
-         /* Skip leading spaces  */
-         for (p = buf; *p == ' ' || *p == '\t'; p++)
-           ;
-         /* Skip trailing spaces */
-         for (; len > 0 && (p[len-1] == ' ' || p[len-1] == '\t'); )
-           p[--len] = 0;
-         
-         /* Skip empty lines and comments. */
-         if (*p == 0 || *p == '#')
-           continue;
-
-         if ((err = mu_url_create (&u, p)) != 0)
-           {
-             /* Skip erroneous entry */
-             /* FIXME: Error message */
-             continue;
-           }
-         if ((err = mu_url_parse (u)) != 0)
-           {
-             /* FIXME: See above */
-             mu_url_destroy (&u);
-             continue;
-           }
-         
-         if (!mu_url_is_ticket (u, url))
+         /* Skip erroneous entry */
+         /* FIXME: Error message */
+         continue;
+       }
+      if ((err = mu_url_parse (u)) != 0)
+       {
+         /* FIXME: See above */
+         mu_url_destroy (&u);
+         continue;
+       }
+      
+      if (!mu_url_is_ticket (u, url))
+       {
+         mu_url_destroy (&u);
+         continue;
+       }
+      
+      if (ft->user)
+       {
+         if (u->name && strcmp (u->name, "*") != 0
+             && strcmp (ft->user, u->name) != 0)
            {
              mu_url_destroy (&u);
              continue;
            }
-         
-         if (ft->user)
-           {
-             if (u->name && strcmp (u->name, "*") != 0
-                 && strcmp (ft->user, u->name) != 0)
-               {
-                 mu_url_destroy (&u);
-                 continue;
-               }
-           }
-         
-         break;
        }
-      mu_stream_close (stream);
-      free (buf);
+      
+      break;
     }
+  mu_stream_close (stream);
+  free (buf);
+    
   mu_stream_destroy (&stream);
 
   if (rc == 0)
diff --git a/libmailutils/xscript-stream.c b/libmailutils/xscript-stream.c
index b8639c2..ff5d796 100644
--- a/libmailutils/xscript-stream.c
+++ b/libmailutils/xscript-stream.c
@@ -402,7 +402,8 @@ mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t 
transport,
   struct _mu_xscript_stream *sp;
 
   mu_stream_get_flags (transport, &flags);
-  sp = (struct _mu_xscript_stream *) _mu_stream_create (sizeof (*sp), flags);
+  sp = (struct _mu_xscript_stream *) _mu_stream_create (sizeof (*sp),
+                                                        flags | _MU_STR_OPEN);
   if (!sp)
     return ENOMEM;
 
diff --git a/libmu_argp/muinit.c b/libmu_argp/muinit.c
index 5471116..85b65ed 100644
--- a/libmu_argp/muinit.c
+++ b/libmu_argp/muinit.c
@@ -133,7 +133,6 @@ mu_app_init (struct argp *myargp, const char **capa,
       char *canonical_name = get_canonical_name ();
       mu_stream_t stream;
       mu_stdio_stream_create (&stream, MU_STDOUT_FD, 0);
-      mu_stream_open (stream);
       asprintf (&comment,
                "Configuration file structure for %s utility.",
                mu_program_name);
diff --git a/libmu_auth/ldap.c b/libmu_auth/ldap.c
index 5ced397..419ea6c 100644
--- a/libmu_auth/ldap.c
+++ b/libmu_auth/ldap.c
@@ -597,7 +597,6 @@ chk_md5 (const char *db_pass, const char *pass)
   mu_memory_stream_create (&str, 0);
   mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE,
                    MU_STREAM_READ | MU_STREAM_AUTOCLOSE);
-  mu_stream_open (str);
   mu_stream_write (str, db_pass, strlen (db_pass), NULL);
 
   mu_stream_read (flt, (char*) d1, sizeof d1, NULL);
@@ -620,7 +619,6 @@ chk_smd5 (const char *db_pass, const char *pass)
   mu_memory_stream_create (&str, 0);
   mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE,
                    MU_STREAM_READ | MU_STREAM_AUTOCLOSE);
-  mu_stream_open (str);
   size = strlen (db_pass);
   mu_stream_write (str, db_pass, size, NULL);
 
@@ -666,7 +664,6 @@ chk_sha (const char *db_pass, const char *pass)
   mu_memory_stream_create (&str, 0);
   mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE,
                    MU_STREAM_READ | MU_STREAM_AUTOCLOSE);
-  mu_stream_open (str);
   mu_stream_write (str, db_pass, strlen (db_pass), NULL);
 
   mu_stream_read (flt, (char*) d1, sizeof d1, NULL);
@@ -689,7 +686,6 @@ chk_ssha (const char *db_pass, const char *pass)
   mu_memory_stream_create (&str, 0);
   mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE,
                    MU_STREAM_READ | MU_STREAM_AUTOCLOSE);
-  mu_stream_open (str);
   size = strlen (db_pass);
   mu_stream_write (str, db_pass, size, NULL);
 
diff --git a/libmu_auth/tls.c b/libmu_auth/tls.c
index e31b856..e6e4551 100644
--- a/libmu_auth/tls.c
+++ b/libmu_auth/tls.c
@@ -292,7 +292,7 @@ _mu_tls_io_stream_create (mu_stream_t *pstream,
   struct _mu_tls_io_stream *sp;
 
   sp = (struct _mu_tls_io_stream *)
-    _mu_stream_create (sizeof (*sp), flags & MU_STREAM_RDWR);
+    _mu_stream_create (sizeof (*sp), (flags & MU_STREAM_RDWR) | _MU_STR_OPEN);
   if (!sp)
     return ENOMEM;
 
@@ -617,6 +617,7 @@ _mu_tls_stream_create (mu_stream_t *pstream,
   struct _mu_tls_stream *sp;
   int autoclose = flags & MU_STREAM_AUTOCLOSE;
   int rc;
+  mu_stream_t stream;
   
   sp = (struct _mu_tls_stream *)
     _mu_stream_create (sizeof (*sp), MU_STREAM_RDWR);
@@ -653,9 +654,14 @@ _mu_tls_stream_create (mu_stream_t *pstream,
       return rc;
     }
 
-  mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 0);
-  *pstream = (mu_stream_t) sp;
-  return 0;
+  stream = (mu_stream_t) sp;
+  mu_stream_set_buffer (stream, mu_buffer_line, 0);
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+  return rc;
 }
 
 int
diff --git a/libmu_sieve/extensions/pipe.c b/libmu_sieve/extensions/pipe.c
index 1378461..664997d 100644
--- a/libmu_sieve/extensions/pipe.c
+++ b/libmu_sieve/extensions/pipe.c
@@ -94,9 +94,6 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
       rc = mu_prog_stream_create (&pstr, cmd, MU_STREAM_WRITE);
       ONERR (rc, _("cannot create command stream"), cmd);
 
-      rc = mu_stream_open (pstr);
-      ONERR (rc, _("cannot open command stream"), cmd);
-
       if (mu_sieve_tag_lookup (tags, "envelope", &val))
        {
          char *p;
diff --git a/libmu_sieve/extensions/spamd.c b/libmu_sieve/extensions/spamd.c
index e620e58..b679cd3 100644
--- a/libmu_sieve/extensions/spamd.c
+++ b/libmu_sieve/extensions/spamd.c
@@ -52,12 +52,6 @@ spamd_connect_tcp (mu_sieve_machine_t mach, mu_stream_t 
*stream,
       mu_sieve_error (mach, "mu_tcp_stream_create: %s", mu_strerror (rc));
       return rc;
     }
-  rc = mu_stream_open (*stream);
-  if (rc)
-    {
-      mu_sieve_error (mach, "opening tcp stream: %s", mu_strerror (rc));
-      mu_stream_destroy (stream);
-    }
   return rc;
 }
 
@@ -70,13 +64,6 @@ spamd_connect_socket (mu_sieve_machine_t mach, mu_stream_t 
*stream, char *path)
       mu_sieve_error (mach, "mu_socket_stream_create: %s", mu_strerror (rc));
       return rc;
     }
-  rc = mu_stream_open (*stream);
-  if (rc)
-    {
-      mu_sieve_error (mach, "opening socket stream: %s", mu_strerror (rc));
-      mu_stream_destroy (stream);
-    }
-
   return rc;
 }
 
diff --git a/libmu_sieve/extensions/vacation.c 
b/libmu_sieve/extensions/vacation.c
index 6b220df..a41103a 100644
--- a/libmu_sieve/extensions/vacation.c
+++ b/libmu_sieve/extensions/vacation.c
@@ -71,17 +71,6 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, 
mu_mime_t *pmime,
       return 1;
     }
 
-  if ((rc = mu_stream_open (input)))
-    {
-      mu_sieve_error (mach,
-                     _("cannot open temporary stream: %s"),
-                     mu_strerror (rc));
-      mu_mime_destroy (&mime);
-      mu_message_destroy (&newmsg, NULL);
-      mu_stream_destroy (&input);
-      return 1;
-    }
-  
   mu_stream_write (input, text, strlen (text), NULL);
 
   if (mu_sieve_tag_lookup (tags, "mime", NULL))
diff --git a/libproto/imap/folder.c b/libproto/imap/folder.c
index 4f27c49..e555c12 100644
--- a/libproto/imap/folder.c
+++ b/libproto/imap/folder.c
@@ -661,7 +661,6 @@ folder_imap_open (mu_folder_t folder, int flags)
             }
          status = mu_memory_stream_create (&f_imap->string.stream, NULL, 
MU_STREAM_RDWR);
           CHECK_ERROR (f_imap, status);
-         mu_stream_open (f_imap->string.stream);
         }
       else
         {
@@ -684,10 +683,6 @@ folder_imap_open (mu_folder_t folder, int flags)
            {
              mu_stream_t newstr;
 
-             status = mu_stream_open (folder->stream);
-             CHECK_EAGAIN (f_imap, status);
-             CHECK_ERROR_CLOSE (folder, f_imap, status);
-
              status = mu_tls_client_stream_create (&newstr, 
                                                    folder->stream,
                                                    folder->stream, 0);
@@ -712,10 +707,13 @@ folder_imap_open (mu_folder_t folder, int flags)
 
     case IMAP_OPEN_CONNECTION:
       /* Establish the connection.  */
-      status = mu_stream_open (folder->stream);
-      CHECK_EAGAIN (f_imap, status);
-      /* Can't recover bailout.  */
-      CHECK_ERROR_CLOSE (folder, f_imap, status);
+      if (!mu_stream_is_open (folder->stream))
+        {
+          status = mu_stream_open (folder->stream);
+          CHECK_EAGAIN (f_imap, status);
+          /* Can't recover bailout.  */
+          CHECK_ERROR_CLOSE (folder, f_imap, status);
+        }
       f_imap->state = IMAP_GREETINGS;
 
     case IMAP_GREETINGS:
diff --git a/libproto/mailer/smtp.c b/libproto/mailer/smtp.c
index 742f95d..ae78cae 100644
--- a/libproto/mailer/smtp.c
+++ b/libproto/mailer/smtp.c
@@ -17,10 +17,6 @@
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301 USA */
 
-/** @file smtp.c
address@hidden an SMTP mailer
-*/
-/* FIXME: Bufferization stuff is spurious. Remove it */
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -175,9 +171,6 @@ smtp_open (mu_mailer_t mailer, int flags)
       if (rc)
        return rc;
       mu_stream_set_buffer (mailer->stream, mu_buffer_line, 0);
-      rc = mu_stream_open (mailer->stream);
-      if (rc)
-       return rc;
     }
   mu_smtp_set_carrier (smtp_mailer->smtp, mailer->stream);
   /* FIXME: Unref the stream */
diff --git a/libproto/mailer/smtp_gsasl.c b/libproto/mailer/smtp_gsasl.c
index f957c87..d43631f 100644
--- a/libproto/mailer/smtp_gsasl.c
+++ b/libproto/mailer/smtp_gsasl.c
@@ -148,8 +148,8 @@ insert_gsasl_stream (mu_smtp_t smtp, Gsasl_session 
*sess_ctx)
 {
   mu_stream_t stream[2], newstream[2];
   int rc;
-  
-  rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_GET_STREAM, stream);
+
+  rc = _mu_smtp_get_streams (smtp, stream);
   if (rc)
     {
       mu_error ("%s failed: %s", "MU_IOCTL_GET_STREAM",
@@ -158,7 +158,7 @@ insert_gsasl_stream (mu_smtp_t smtp, Gsasl_session 
*sess_ctx)
     }
 
   rc = gsasl_encoder_stream (&newstream[0], stream[0], sess_ctx,
-                          MU_STREAM_READ);
+                            MU_STREAM_READ);
   if (rc)
     {
       mu_error ("%s failed: %s", "gsasl_encoder_stream",
@@ -179,10 +179,9 @@ insert_gsasl_stream (mu_smtp_t smtp, Gsasl_session 
*sess_ctx)
   mu_stream_flush (stream[1]);
   mu_stream_unref (stream[0]);
   mu_stream_unref (stream[1]);
+
+  rc = _mu_smtp_set_streams (smtp, newstream);
   
-  rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SET_STREAM, newstream);
-  mu_stream_unref (newstream[0]);
-  mu_stream_unref (newstream[1]);
   if (rc)
     {
       mu_error ("%s failed when it should not: %s",
diff --git a/libproto/mailer/smtp_starttls.c b/libproto/mailer/smtp_starttls.c
index 0e4c7f1..8c0662c 100644
--- a/libproto/mailer/smtp_starttls.c
+++ b/libproto/mailer/smtp_starttls.c
@@ -27,8 +27,8 @@
 #include <mailutils/sys/smtp.h>
 #include <mailutils/tls.h>
 
-static int
-smtp_get_streams (mu_smtp_t smtp, mu_stream_t *streams)
+int
+_mu_smtp_get_streams (mu_smtp_t smtp, mu_stream_t *streams)
 {
   int rc;
   
@@ -45,8 +45,8 @@ smtp_get_streams (mu_smtp_t smtp, mu_stream_t *streams)
   return rc;
 }
 
-static int
-smtp_set_streams (mu_smtp_t smtp, mu_stream_t *streams)
+int
+_mu_smtp_set_streams (mu_smtp_t smtp, mu_stream_t *streams)
 {
   int rc;
   
@@ -100,7 +100,7 @@ mu_smtp_starttls (mu_smtp_t smtp)
     return MU_ERR_FAILURE;
 
   mu_stream_flush (smtp->carrier);
-  status = smtp_get_streams (smtp, streams);
+  status = _mu_smtp_get_streams (smtp, streams);
   MU_SMTP_CHECK_ERROR (smtp, status);
   
   status = mu_tls_client_stream_create (&tlsstream,
@@ -108,14 +108,8 @@ mu_smtp_starttls (mu_smtp_t smtp)
   mu_stream_unref (streams[0]);
   mu_stream_unref (streams[1]);
   MU_SMTP_CHECK_ERROR (smtp, status);
-  status = mu_stream_open (tlsstream);
-  if (status)
-    {
-      mu_stream_destroy (&tlsstream);
-      return status;
-    }
   streams[0] = streams[1] = tlsstream;
-  status = smtp_set_streams (smtp, streams);
+  status = _mu_smtp_set_streams (smtp, streams);
   mu_stream_unref (streams[0]);
   mu_stream_unref (streams[1]);
   MU_SMTP_CHECK_ERROR (smtp, status);
diff --git a/libproto/mbox/mbox.c b/libproto/mbox/mbox.c
index 04e548a..6250765 100644
--- a/libproto/mbox/mbox.c
+++ b/libproto/mbox/mbox.c
@@ -99,24 +99,10 @@ mbox_open (mu_mailbox_t mailbox, int flags)
 
       if (status)
        return status;
-      mu_stream_set_buffer (mailbox->stream, mu_buffer_full, 0);
-      
-      status = mu_stream_open (mailbox->stream);
-      if (status)
-       {
-         mu_stream_destroy (&mailbox->stream);
-         return status;
-       }
-      
-      /* FIXME: Set up buffering */
-    }
-  else
-    {
-      status = mu_stream_open (mailbox->stream);
-      if (status != 0)
-       return status;
     }
 
+  mu_stream_set_buffer (mailbox->stream, mu_buffer_full, 0);
+
   MU_DEBUG2 (mailbox->debug, MU_DEBUG_TRACE1, "mbox_open (%s, 0x%x)\n",
             mud->name, mailbox->flags);
 
@@ -1416,35 +1402,31 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted)
   status = mu_temp_file_stream_create (&tempstr, NULL);
   if (status == 0)
     {
-      status = mu_stream_open (tempstr);
-      if (status == 0)
-       {
-         sigset_t signalset;
+      sigset_t signalset;
 #ifdef WITH_PTHREAD
-         int state;
-         pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
+      int state;
+      pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
 #endif
-         sigemptyset (&signalset);
-         sigaddset (&signalset, SIGTERM);
-         sigaddset (&signalset, SIGHUP);
-         sigaddset (&signalset, SIGTSTP);
-         sigaddset (&signalset, SIGINT);
-         sigaddset (&signalset, SIGWINCH);
-         sigprocmask (SIG_BLOCK, &signalset, 0);
-         
-         status = mbox_expunge_unlocked (mailbox, dirty, remove_deleted,
-                                         tempstr);
+      sigemptyset (&signalset);
+      sigaddset (&signalset, SIGTERM);
+      sigaddset (&signalset, SIGHUP);
+      sigaddset (&signalset, SIGTSTP);
+      sigaddset (&signalset, SIGINT);
+      sigaddset (&signalset, SIGWINCH);
+      sigprocmask (SIG_BLOCK, &signalset, 0);
+      
+      status = mbox_expunge_unlocked (mailbox, dirty, remove_deleted,
+                                     tempstr);
 
 #ifdef WITH_PTHREAD
-         pthread_setcancelstate (state, &state);
+      pthread_setcancelstate (state, &state);
 #endif
-         sigprocmask (SIG_UNBLOCK, &signalset, 0);
+      sigprocmask (SIG_UNBLOCK, &signalset, 0);
       
-         mu_stream_destroy (&tempstr);
-
-         if (status == 0)
-           mbox_reset (mailbox, dirty, remove_deleted);
-       }
+      mu_stream_destroy (&tempstr);
+      
+      if (status == 0)
+       mbox_reset (mailbox, dirty, remove_deleted);
     }
   if (mailbox->locker)
     mu_locker_unlock (mailbox->locker);
diff --git a/libproto/nntp/nntp_connect.c b/libproto/nntp/nntp_connect.c
index d6b9741..959f0b4 100644
--- a/libproto/nntp/nntp_connect.c
+++ b/libproto/nntp/nntp_connect.c
@@ -55,8 +55,11 @@ mu_nntp_connect (mu_nntp_t nntp)
 
     case MU_NNTP_CONNECT:
       /* Establish the connection.  */
-      status = mu_stream_open (nntp->carrier);
-      MU_NNTP_CHECK_EAGAIN (nntp, status);
+      if (!mu_stream_is_open (nntp->carrier))
+        {
+          status = mu_stream_open (nntp->carrier);
+          MU_NNTP_CHECK_EAGAIN (nntp, status);
+        }
       nntp->acknowledge = 0;
       nntp->state = MU_NNTP_GREETINGS;
 
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index 0bf17fa..eb25bcc 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -129,13 +129,6 @@ pop_open (mu_mailbox_t mbox, int flags)
     {
       mu_stream_t newstr;
       
-      status = mu_stream_open (stream);
-      if (status)
-       {
-         mu_stream_destroy (&stream);
-         return status;
-       }
-      
       status = mu_tls_client_stream_create (&newstr, stream, stream, 0);
       mu_stream_unref (stream);
       if (status)
@@ -373,12 +366,6 @@ _pop_message_get_stream (struct _pop3_message *mpm, 
mu_stream_t *pstr)
                /* FIXME: Try to recover first */
                break;
 
-             status = mu_stream_open (mpd->cache);
-             if (status)
-               {
-                 mu_stream_destroy (&mpd->cache);
-                 break;
-               }
              mu_stream_set_buffer (mpd->cache, mu_buffer_full, 8192);
            }
 
diff --git a/libproto/pop/pop3_connect.c b/libproto/pop/pop3_connect.c
index 9377e84..5b9ffab 100644
--- a/libproto/pop/pop3_connect.c
+++ b/libproto/pop/pop3_connect.c
@@ -69,9 +69,12 @@ mu_pop3_connect (mu_pop3_t pop3)
 
     case MU_POP3_CONNECT:
       /* Establish the connection.  */
-      status = mu_stream_open (pop3->carrier);
-      MU_POP3_CHECK_EAGAIN (pop3, status);
-      MU_POP3_FCLR (pop3, MU_POP3_ACK);
+      if (!mu_stream_is_open (pop3->carrier))
+        {
+          status = mu_stream_open (pop3->carrier);
+          MU_POP3_CHECK_EAGAIN (pop3, status);
+          MU_POP3_FCLR (pop3, MU_POP3_ACK);
+        }
       pop3->state = MU_POP3_GREETINGS;
 
     case MU_POP3_GREETINGS:
diff --git a/libproto/pop/pop3_stls.c b/libproto/pop/pop3_stls.c
index f9cc278..0cf617d 100644
--- a/libproto/pop/pop3_stls.c
+++ b/libproto/pop/pop3_stls.c
@@ -114,8 +114,6 @@ mu_pop3_stls (mu_pop3_t pop3)
       mu_stream_unref (streams[0]);
       mu_stream_unref (streams[1]);
       MU_POP3_CHECK_EAGAIN (pop3, status);
-      status = mu_stream_open (tlsstream);
-      MU_POP3_CHECK_EAGAIN (pop3, status);
       streams[0] = streams[1] = tlsstream;
       status = pop3_set_streams (pop3, streams);
       mu_stream_unref (streams[0]);
diff --git a/libproto/pop/pop3_stream.c b/libproto/pop/pop3_stream.c
index 446e5eb..6df096c 100644
--- a/libproto/pop/pop3_stream.c
+++ b/libproto/pop/pop3_stream.c
@@ -173,7 +173,8 @@ mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream)
   int status;
   
   sp = (struct mu_pop3_stream *) _mu_stream_create (sizeof (*sp),
-                                                   MU_STREAM_READ);
+                                                   MU_STREAM_READ |
+                                                   _MU_STR_OPEN);
   if (!sp)
     return ENOMEM;
   sp->stream.read = _mu_pop3_read; 
diff --git a/maidag/mailtmp.c b/maidag/mailtmp.c
index f81bc30..d981673 100644
--- a/maidag/mailtmp.c
+++ b/maidag/mailtmp.c
@@ -49,13 +49,6 @@ mail_tmp_begin (struct mail_tmp **pmtmp, const char *from)
       return status;
     }
 
-  if ((status = mu_stream_open (mtmp->stream)))
-    {
-      free (mtmp);
-      maidag_error (_("unable to open temporary file: %s"),
-                   mu_strerror (status));
-      return status;
-    }
   mtmp->from = from;
   *pmtmp = mtmp;
   return 0;
diff --git a/mail/decode.c b/mail/decode.c
index cd1d159..f508faf 100644
--- a/mail/decode.c
+++ b/mail/decode.c
@@ -418,12 +418,6 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg)
              break;
            }
 
-         status = mu_stream_open (pstr);
-         if (status)
-           {
-             mu_error ("mu_stream_open: %s", mu_strerror (status));
-             break;
-           }
          mu_stream_copy (pstr, stream, 0, NULL);
          mu_stream_close (pstr);
          mu_stream_destroy (&pstr);
diff --git a/mail/pipe.c b/mail/pipe.c
index f139edf..d057450 100644
--- a/mail/pipe.c
+++ b/mail/pipe.c
@@ -41,8 +41,6 @@ mail_pipe (int argc, char **argv)
     return 1;
 
   rc = mu_prog_stream_create (&outstr, cmd, MU_STREAM_WRITE);
-  if (rc == 0)
-    rc = mu_stream_open (outstr);
   if (rc)
     {
       mu_error (_("cannot open `%s': %s"), cmd, mu_strerror (rc));
diff --git a/mail/send.c b/mail/send.c
index fd14900..3f095b2 100644
--- a/mail/send.c
+++ b/mail/send.c
@@ -568,8 +568,6 @@ mail_send0 (compose_env_t * env, int save_to)
       mu_stream_t instr;
 
       rc = mu_file_stream_create (&instr, filename, MU_STREAM_READ);
-      if (rc == 0)
-       rc = mu_stream_open (instr);
       if (rc)
        mu_error (_("cannot open temporary stream `%s' for reading: %s"),
                  filename, mu_strerror (rc));
diff --git a/mail/write.c b/mail/write.c
index d7e017d..13ad960 100644
--- a/mail/write.c
+++ b/mail/write.c
@@ -72,8 +72,6 @@ mail_write (int argc, char **argv)
 
   rc = mu_file_stream_create (&output, filename,
                              MU_STREAM_APPEND|MU_STREAM_CREAT);
-  if (rc == 0)
-    rc = mu_stream_open (output);
   if (rc)
     {
       util_error (_("can't open %s: %s"), filename, mu_strerror (rc));
diff --git a/mh/burst.c b/mh/burst.c
index 1bd99c3..b413c07 100644
--- a/mh/burst.c
+++ b/mh/burst.c
@@ -239,9 +239,7 @@ flush_stream (mu_stream_t *pstr, char *buf, size_t size)
 
   if (size == 0)
     return;
-  if (!*pstr
-      && ((rc = mu_temp_file_stream_create (pstr, NULL)) != 0
-         || (rc = mu_stream_open (*pstr))))
+  if ((rc = mu_temp_file_stream_create (pstr, NULL))) 
     {
       mu_error (_("Cannot open temporary file: %s"),
                mu_strerror (rc));
@@ -485,8 +483,7 @@ msg_copy (size_t num, const char *file)
   
   if ((rc = mu_file_stream_create (&ostream,
                                   file,
-                                  MU_STREAM_WRITE|MU_STREAM_CREAT)) != 0
-      || (rc = mu_stream_open (ostream)))
+                                  MU_STREAM_WRITE|MU_STREAM_CREAT))) 
     {
       mu_error (_("Cannot open output file `%s': %s"),
                file, mu_strerror (rc));
diff --git a/mh/comp.c b/mh/comp.c
index 935f114..f65fab2 100644
--- a/mh/comp.c
+++ b/mh/comp.c
@@ -158,8 +158,7 @@ copy_message (mu_mailbox_t mbox, size_t n, const char *file)
   mu_message_get_streamref (msg, &in);
   
   if ((rc = mu_file_stream_create (&out,
-                                  file, MU_STREAM_RDWR|MU_STREAM_CREAT)) != 0
-      || (rc = mu_stream_open (out)))
+                                  file, MU_STREAM_RDWR|MU_STREAM_CREAT)))
     {
       mu_error (_("cannot open output file \"%s\": %s"),
                file, mu_strerror (rc));
diff --git a/mh/compcommon.c b/mh/compcommon.c
index 666ef17..e85da11 100644
--- a/mh/compcommon.c
+++ b/mh/compcommon.c
@@ -54,8 +54,7 @@ mh_comp_draft (const char *formfile, const char *defformfile,
          
          if ((rc = mu_file_stream_create (&stream,
                                        draftfile,
-                                       MU_STREAM_WRITE|MU_STREAM_CREAT)) != 0
-             || (rc = mu_stream_open (stream)))
+                                       MU_STREAM_WRITE|MU_STREAM_CREAT)))
            {
              mu_error (_("cannot open output file \"%s\": %s"),
                        draftfile, mu_strerror (rc));
diff --git a/mh/forw.c b/mh/forw.c
index 8d331ec..6e63d23 100644
--- a/mh/forw.c
+++ b/mh/forw.c
@@ -332,8 +332,7 @@ finish_draft ()
   
   if ((rc = mu_file_stream_create (&stream,
                                   wh_env.file,
-                                  MU_STREAM_WRITE|MU_STREAM_CREAT)) != 0
-      || (rc = mu_stream_open (stream)))
+                                  MU_STREAM_WRITE|MU_STREAM_CREAT)))
     {
       mu_error (_("cannot open output file `%s': %s"),
                wh_env.file, mu_strerror (rc));
diff --git a/mh/mh_init.c b/mh/mh_init.c
index 776e450..7043d1a 100644
--- a/mh/mh_init.c
+++ b/mh/mh_init.c
@@ -597,8 +597,7 @@ mh_file_copy (const char *from, const char *to)
   if (!bufsize)
     mh_err_memory (1);
 
-  if ((rc = mu_file_stream_create (&in, from, MU_STREAM_READ)) != 0
-      || (rc = mu_stream_open (in)))
+  if ((rc = mu_file_stream_create (&in, from, MU_STREAM_READ)))
     {
       mu_error (_("cannot open input file `%s': %s"),
                from, mu_strerror (rc));
@@ -606,8 +605,7 @@ mh_file_copy (const char *from, const char *to)
       return 1;
     }
 
-  if ((rc = mu_file_stream_create (&out, to, MU_STREAM_RDWR|MU_STREAM_CREAT)) 
!= 0
-      || (rc = mu_stream_open (out)))
+  if ((rc = mu_file_stream_create (&out, to, MU_STREAM_RDWR|MU_STREAM_CREAT)))
     {
       mu_error (_("cannot open output file `%s': %s"),
                to, mu_strerror (rc));
@@ -660,14 +658,6 @@ _file_to_message (const char *file_name)
       return NULL;
     }
   
-  if ((rc = mu_stream_open (instream)))
-    {
-      mu_error (_("cannot open input stream (file %s): %s"),
-               file_name, mu_strerror (rc));
-      mu_stream_destroy (&instream);
-      return NULL;
-    }
-
   return mh_stream_to_message (instream);
 }
 
diff --git a/mh/mh_whatnow.c b/mh/mh_whatnow.c
index 8652fc0..3ec4533 100644
--- a/mh/mh_whatnow.c
+++ b/mh/mh_whatnow.c
@@ -198,12 +198,6 @@ display_file (const char *name)
          mu_error ("mu_file_stream_create: %s", mu_strerror (rc));
          return;
        }
-      rc = mu_stream_open (stream);
-      if (rc)
-       {
-         mu_error ("mu_stream_open: %s", mu_strerror (rc));
-         return;
-       } 
 
       mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
       while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0
diff --git a/mh/mhl.c b/mh/mhl.c
index 6a7024d..030fe42 100644
--- a/mh/mhl.c
+++ b/mh/mhl.c
@@ -161,11 +161,6 @@ open_output ()
       exit (1);
     }
 
-  if ((rc = mu_stream_open (output)))
-    {
-      mu_error (_("cannot open output stream: %s"), mu_strerror (rc));
-      exit (1);
-    }
   return output;
 }
 
@@ -186,13 +181,6 @@ list_message (char *name, mu_stream_t output)
       return;
     }
 
-  if ((rc = mu_stream_open (input)))
-    {
-      mu_error (_("cannot open input stream: %s"), mu_strerror (rc));
-      mu_stream_destroy (&input);
-      return;
-    }
-
   msg = mh_stream_to_message (input);
   if (!msg)
     {
diff --git a/mh/mhn.c b/mh/mhn.c
index 356f886..d25932f 100644
--- a/mh/mhn.c
+++ b/mh/mhn.c
@@ -1273,13 +1273,6 @@ mhn_exec (mu_stream_t *str, const char *cmd, int flags)
       mu_error (_("cannot create proc stream (command %s): %s"),
                cmd, mu_strerror (rc));
     }
-  else
-    {
-      rc = mu_stream_open (*str);
-      if (rc)
-       mu_error (_("cannot open proc stream (command %s): %s"),
-                 cmd, mu_strerror (rc));
-    }
   return rc;
 }
 
@@ -1330,15 +1323,6 @@ mhn_run_command (mu_message_t msg, msg_part_t part,
          mu_argcv_free (argc, argv);
          return rc;
        }
-      rc = mu_stream_open (tmp);
-      if (rc)
-       {
-         mu_error (_("cannot open temporary stream (file %s): %s"),
-                   tempfile, mu_strerror (rc));
-         mu_stream_destroy (&tmp);
-         mu_argcv_free (argc, argv);
-         return rc;
-       }
       show_internal (msg, part, encoding, tmp);      
       mu_stream_destroy (&tmp);
       rc = mu_spawnvp (argv[0], argv, &status);
@@ -1462,12 +1446,6 @@ mhn_show ()
       mu_error (_("cannot create output stream: %s"), mu_strerror (rc));
       exit (1);
     }
-  rc = mu_stream_open (ostr);
-  if (rc)
-    {
-      mu_error (_("cannot open output stream: %s"), mu_strerror (rc));
-      exit (1);
-    }
   
   if (formfile)
     {
@@ -1642,15 +1620,6 @@ store_handler (mu_message_t msg, msg_part_t part, char 
*type, char *encoding,
       free (name);
       return rc;
     }
-  rc = mu_stream_open (out);
-  if (rc)
-    {
-      mu_error (_("cannot open output stream (file %s): %s"),
-               name, mu_strerror (rc));
-      free (name);
-      mu_stream_destroy (&out);
-      return rc;
-    }
   show_internal (msg, part, encoding, out);      
 
   mu_stream_destroy (&out);
@@ -2246,14 +2215,6 @@ edit_mime (char *cmd, struct compose_env *env, 
mu_message_t *msg, int level)
                    cmd, mu_strerror (rc));
          return rc;
        }
-      rc = mu_stream_open (in);
-      if (rc)
-       {
-         mu_error (_("cannot open input stream (file %s): %s"),
-                   cmd, mu_strerror (rc));
-         mu_stream_destroy (&in);
-         return rc;
-       }
     }
   
   /* Create filter */
@@ -2285,14 +2246,6 @@ edit_mime (char *cmd, struct compose_env *env, 
mu_message_t *msg, int level)
     }
   free (encoding);
 
-  rc = mu_stream_open (fstr);
-  if (rc)
-    {
-      mu_error (_("cannot open filter stream: %s"),
-               mu_strerror (rc));
-      return rc;
-    }
-  
   mu_message_get_body (*msg, &body);
   mu_body_get_streamref (body, &out);
   mu_stream_copy (out, fstr, 0, NULL);
@@ -2647,15 +2600,6 @@ mhn_compose ()
       free (name);
       return rc;
     }
-  rc = mu_stream_open (stream);
-  if (rc)
-    {
-      mu_error (_("cannot open output stream (file %s): %s"),
-               name, mu_strerror (rc));
-      free (name);
-      mu_stream_destroy (&stream);
-      return rc;
-    }
 
   mhn_header (message, msg);
   copy_header_to_stream (message, stream);
diff --git a/mh/repl.c b/mh/repl.c
index 9f0f5e5..afb9233 100644
--- a/mh/repl.c
+++ b/mh/repl.c
@@ -336,13 +336,6 @@ make_draft (mu_mailbox_t mbox, int disp, struct 
mh_whatnow_env *wh)
          exit (1);
        }
 
-      if ((rc = mu_stream_open (str)))
-       {
-         mu_error (_("cannot open draft file %s: %s"),
-                   wh->file, mu_strerror (rc));
-         exit (1);
-       }         
-
       if (has_fcc)
        {
          mu_message_t tmp_msg;
diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c
index ed90703..8b32311 100644
--- a/mimeview/mimeview.c
+++ b/mimeview/mimeview.c
@@ -260,7 +260,6 @@ display_file (const char *type)
          mu_stdio_stream_create (&stream, fileno (mimeview_fp),
                                  MU_STREAM_READ|
                                  MU_STREAM_SEEK);
-         mu_stream_open (stream);
          
          display_stream_mailcap (mimeview_file, stream, hdr,
                                  no_ask_types, interactive, dry_run,
diff --git a/mu/.gitignore b/mu/.gitignore
new file mode 100644
index 0000000..92cfbd6
--- /dev/null
+++ b/mu/.gitignore
@@ -0,0 +1 @@
+mu
diff --git a/mu/Makefile.am b/mu/Makefile.am
new file mode 100644
index 0000000..0a3c50e
--- /dev/null
+++ b/mu/Makefile.am
@@ -0,0 +1,43 @@
+## This file is part of GNU Mailutils.
+## Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2010 Free
+## Software Foundation, Inc.
+##
+## GNU Mailutils is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+bin_PROGRAMS = mu
+mu_SOURCES = \
+ info.c\
+ mu.h\
+ mu.c\
+ filter.c\
+ flt2047.c\
+ pop.c\
+ query.c\
+ shell.c
+
+mu_LDADD = \
+ ${MU_APP_LIBRARIES}\
+ ${MU_LIB_MBOX}\
+ ${MU_LIB_IMAP}\
+ ${MU_LIB_POP}\
+ ${MU_LIB_NNTP}\
+ ${MU_LIB_MH}\
+ ${MU_LIB_MAILDIR}\
+ ${MU_LIB_MAILER}\
+ ${MU_LIB_AUTH}\
+ @address@hidden
+ ${MU_LIB_MAILUTILS}\
+ @READLINE_LIBS@ @MU_COMMON_LIBRARIES@
+
+INCLUDES = @MU_APP_COMMON_INCLUDES@ @MU_AUTHINCS@
diff --git a/mu/filter.c b/mu/filter.c
new file mode 100644
index 0000000..373eb0d
--- /dev/null
+++ b/mu/filter.c
@@ -0,0 +1,159 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+#include "argp.h"
+#include "mu.h"
+
+static char filter_doc[] = N_("mu filter");
+static char filter_args_doc[] = N_("[OPTIONS] NAME");
+
+static struct argp_option filter_options[] = {
+  { "encode", 'e', NULL, 0, N_("encode the input (default)") },
+  { "decode", 'd', NULL, 0, N_("decode the input") },
+  { "line-length", 'l', NULL, 0, N_("limit output line length") },
+  { "newline", 'n', NULL, 0, N_("print additional newline") },
+  { NULL }
+};
+
+static int filter_mode = MU_FILTER_ENCODE;
+static int newline_option = 0;
+static size_t line_length;
+static int line_length_option = 0;
+
+static error_t
+filter_parse_opt (int key, char *arg, struct argp_state *state)
+{
+  char *p;
+  
+  switch (key)
+    {
+    case 'e':
+      filter_mode = MU_FILTER_ENCODE;
+      break;
+
+    case 'd':
+      filter_mode = MU_FILTER_DECODE;
+      break;
+
+    case 'n':
+      newline_option = 1;
+      break;
+
+    case 'l':
+      line_length = strtoul (arg, &p, 10);
+      if (*p)
+       argp_error (state, N_("not a number"));
+      line_length_option = 1;
+      break;
+      
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp filter_argp = {
+  filter_options,
+  filter_parse_opt,
+  filter_args_doc,
+  filter_doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+/* FIXME: This is definitely a kludge. The API should provide a function
+   for that. */
+static void
+reset_line_length (const char *name, size_t length)
+{
+  mu_list_t list;
+  int status;
+  mu_filter_record_t frec;
+  
+  mu_filter_get_list (&list);
+  status = mu_list_locate (list, (void*)name, (void**)&frec);
+  if (status == 0)
+    frec->max_line_length = length;
+  /* don't bail out, leave that to mu_filter_create */
+}
+
+int
+mutool_filter (int argc, char **argv)
+{
+  int rc, index;
+  mu_stream_t in, out, flt;
+  const char *fltname;
+  
+  if (argp_parse (&filter_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
+    return 1;
+
+  argc -= index;
+  argv += index;
+
+  if (argc != 1)
+    {
+      mu_error (_("what filter do you want?"));
+      return 1;
+    }
+
+  fltname = argv[0];
+  
+  rc = mu_stdio_stream_create (&in, MU_STDIN_FD, 0);
+  if (rc)
+    {
+      mu_error (_("cannot open input stream: %s"), mu_strerror (rc));
+      return 1;
+    }
+  
+  rc = mu_stdio_stream_create (&out, MU_STDOUT_FD, 0);
+  if (rc)
+    {
+      mu_error (_("cannot open output stream: %s"), mu_strerror (rc));
+      return 1;
+    }
+
+  if (line_length_option)
+    reset_line_length (fltname, line_length);
+
+  rc = mu_filter_create (&flt, in, fltname, filter_mode, MU_STREAM_READ);
+  if (rc)
+    {
+      mu_error (_("cannot open filter stream: %s"), mu_strerror (rc));
+      return 1;
+    }
+
+  rc = mu_stream_copy (out, flt, 0, NULL);
+
+  if (rc)
+    {
+      mu_error ("%s", mu_strerror (rc));
+      return 1;
+    }
+
+  if (newline_option)
+    mu_stream_write (out, "\n", 1, NULL);
+
+  mu_stream_flush (out);
+  
+  return 0;
+}
diff --git a/mu/flt2047.c b/mu/flt2047.c
new file mode 100644
index 0000000..f2ec974
--- /dev/null
+++ b/mu/flt2047.c
@@ -0,0 +1,153 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+#include "argp.h"
+#include "mu.h"
+
+static char flt2047_doc[] = N_("mu 2047 - decode/encode message headers");
+static char flt2047_args_doc[] = N_("[OPTIONS] [text]");
+
+static struct argp_option flt2047_options[] = {
+  { "encode", 'e', NULL, 0, N_("encode the input (default)") },
+  { "decode", 'd', NULL, 0, N_("decode the input") },
+  { "newline", 'n', NULL, 0, N_("print additional newline") },
+  { "charset", 'c', NULL, 0, N_("set charset (default: iso-8859-1)") },
+  { "encoding", 'E', NULL, 0, N_("set encoding (default: quoted-printable)") },
+  { NULL }
+};
+  
+static int decode_mode = 0;
+static int newline_option = 0;
+static const char *charset = "iso-8859-1";
+static const char *encoding = "quoted-printable";
+
+static error_t
+flt2047_parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'c':
+      charset = arg;
+      break;
+      
+    case 'e':
+      decode_mode = 0;
+      break;
+
+    case 'E':
+      encoding = arg;
+      break;
+
+    case 'd':
+      decode_mode = 1;
+      break;
+
+    case 'n':
+      newline_option = 0;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp flt2047_argp = {
+  flt2047_options,
+  flt2047_parse_opt,
+  flt2047_args_doc,
+  flt2047_doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+int
+mutool_flt2047 (int argc, char **argv)
+{
+  int rc, index;
+  mu_stream_t in, out;
+  char *p;
+  
+  if (argp_parse (&flt2047_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
+    return 1;
+
+  argc -= index;
+  argv += index;
+
+  rc = mu_stdio_stream_create (&in, MU_STDIN_FD, 0);
+  if (rc)
+    {
+      mu_error (_("cannot open input stream: %s"), mu_strerror (rc));
+      return 1;
+    }
+  
+  rc = mu_stdio_stream_create (&out, MU_STDOUT_FD, 0);
+  if (rc)
+    {
+      mu_error (_("cannot open output stream: %s"), mu_strerror (rc));
+      return 1;
+    }
+      
+  if (argc)
+    {
+      char *p;
+
+      while (argc--)
+       {
+         const char *text = *argv++;
+         if (decode_mode)
+           rc = mu_rfc2047_decode (charset, text, &p);
+         else
+           rc = mu_rfc2047_encode (charset, encoding, text, &p);
+         if (rc)
+           {
+             mu_error ("%s", mu_strerror (rc));
+             return 1;
+           }
+         mu_stream_printf (out, "%s\n", p);
+       }
+    }
+  else
+    {
+      size_t size = 0, n;
+      char *buf = NULL;
+
+      while ((rc = mu_stream_getline (in, &buf, &size, &n)) == 0 && n > 0)
+       {
+         mu_rtrim_class (buf, MU_CTYPE_SPACE);
+         if (decode_mode)
+           rc = mu_rfc2047_decode (charset, buf, &p);
+         else
+           rc = mu_rfc2047_encode (charset, encoding, buf, &p);
+         if (rc)
+           {
+             mu_error ("%s", mu_strerror (rc));
+             return 1;
+           }
+         mu_stream_printf (out, "%s\n", p);
+       }
+    }
+  mu_stream_flush (out);
+  
+  return 0;
+}
diff --git a/mu/info.c b/mu/info.c
new file mode 100644
index 0000000..56d5b12
--- /dev/null
+++ b/mu/info.c
@@ -0,0 +1,93 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+#include "argp.h"
+#include "mu.h"
+
+static char info_doc[] = N_("mu info - print a list of configuration\
+options used to build mailutils; optional arguments are interpreted\
+ as a list of configuration options to check for.");
+static char info_args_doc[] = N_("[OPTIONS] [capa...]");
+
+static struct argp_option info_options[] = {
+  { "verbose", 'v', NULL, 0,
+    N_("increase output verbosity"), 0},
+  { NULL }
+};
+
+static int verbose;
+
+static error_t
+info_parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'v':
+      verbose++;
+      break;
+      
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp info_argp = {
+  info_options,
+  info_parse_opt,
+  info_args_doc,
+  info_doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+int
+mutool_info (int argc, char **argv)
+{
+  int index;
+  
+  if (argp_parse (&info_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
+    return 1;
+
+  argc -= index;
+  argv += index;
+
+  if (argc == 0)
+    mu_fprint_options (stdout, verbose);
+  else
+    {
+      int i, found = 0;
+      
+      for (i = 0; i < argc; i++)
+       {
+         const struct mu_conf_option *opt = mu_check_option (argv[i]);
+         if (opt)
+           {
+             found++;
+             mu_fprint_conf_option (stdout, opt, verbose);
+           }
+       }
+      return found == argc ? 0 : 1;
+    }
+  return 0;
+}
diff --git a/mu/mu.c b/mu/mu.c
new file mode 100644
index 0000000..cff6a12
--- /dev/null
+++ b/mu/mu.c
@@ -0,0 +1,150 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+#include <mailutils/tls.h>
+#include "mailutils/libargp.h"
+#include "mu.h"
+
+static char args_doc[] = N_("[OPTIONS] COMMAND [CMDOPTS]");
+static char doc[] = N_("mu -- GNU Mailutils test tool.\n\
+Commands are:\n\
+    mu info   - show Mailutils configuration\n\
+    mu query  - query configuration values\n\
+    mu pop    - POP3 client program\n\
+    mu filter - filter program\n\
+    mu 2047   - decode/encode message headers as per RFC 2047\n\
+\n\
+Try `mu COMMAND --help' to get help on a particular COMMAND\n\
+\n\
+Options are:\n");
+/* FIXME: add
+    mu imap
+    mu send [opts]
+ */
+
+static struct argp_option options[] = {
+  { NULL }
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp argp = {
+  options,
+  parse_opt,
+  args_doc,
+  doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+static const char *mu_tool_capa[] = {
+  "common",
+  "debug",
+  "license",
+  "locking",
+  "mailbox",
+  "auth",
+  NULL 
+};
+
+struct mu_cfg_param mu_tool_param[] = {
+  { NULL }
+};
+
+struct mutool_action_tab
+{
+  const char *name;
+  mutool_action_t action;
+};
+
+struct mutool_action_tab mutool_action_tab[] = {
+  { "info", mutool_info },
+  { "pop", mutool_pop },
+  { "filter", mutool_filter },
+  { "2047", mutool_flt2047 },
+  { "query", mutool_query },
+  { NULL }
+};
+
+static mutool_action_t
+find_action (const char *name)
+{
+  struct mutool_action_tab *p;
+
+  for (p = mutool_action_tab; p->name; p++)
+    if (strcmp (p->name, name) == 0)
+      return p->action;
+  return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+  int index;
+  mutool_action_t action;
+  
+  /* Native Language Support */
+  MU_APP_INIT_NLS ();
+  MU_AUTH_REGISTER_ALL_MODULES ();
+  
+  /* Register the desired mailbox formats.  */
+  mu_register_all_mbox_formats ();
+
+#ifdef WITH_TLS
+  mu_gocs_register ("tls", mu_tls_module_init);
+#endif
+  mu_argp_init (NULL, NULL);
+  if (mu_app_init (&argp, mu_tool_capa, mu_tool_param, 
+                  argc, argv, ARGP_IN_ORDER, &index, NULL))
+    exit (1);
+
+  argc -= index;
+  argv += index;
+
+  if (argc < 1)
+    {
+      mu_error (_("what do you want me to do?"));
+      exit (1);
+    }
+       
+  action = find_action (argv[0]);
+  if (!action)
+    {
+      mu_error (_("don't know what %s is"), argv[0]);
+      exit (1);
+    }
+
+  exit (action (argc, argv));
+}
+
+  
+  
diff --git a/mu/mu.h b/mu/mu.h
new file mode 100644
index 0000000..5fe3097
--- /dev/null
+++ b/mu/mu.h
@@ -0,0 +1,40 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+typedef int (*mutool_action_t) (int argc, char **argv);
+
+struct mutool_command
+{
+  const char *name;    /* User printable name of the function. */
+  int argmin;           /* Min. acceptable number of arguments (-1 means
+                          pass all arguments as a single string */ 
+  int argmax;           /* Max. allowed number of arguments (-1 means not
+                          limited */
+  mutool_action_t func;        /* Function to call to do the job. */
+  const char *doc;     /* Documentation for this function.  */
+};
+
+
+int mutool_pop (int argc, char **argv);
+int mutool_filter (int argc, char **argv);
+int mutool_flt2047 (int argc, char **argv);
+int mutool_info (int argc, char **argv);
+int mutool_query (int argc, char **argv);
+
+extern char *mutool_shell_prompt;
+extern mu_vartab_t mutool_prompt_vartab;
+
+int mutool_shell (const char *name, struct mutool_command *cmd);
diff --git a/mu/pop.c b/mu/pop.c
new file mode 100644
index 0000000..8375776
--- /dev/null
+++ b/mu/pop.c
@@ -0,0 +1,778 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <mailutils/mailutils.h>
+#include "mu.h"
+#include "argp.h"
+#include "xalloc.h"
+
+static char pop_doc[] = N_("mu pop - POP3 client shell");
+static char pop_args_doc[] = "";
+
+static struct argp_option pop_options[] = {
+  { NULL }
+};
+
+static error_t
+pop_parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp pop_argp = {
+  pop_options,
+  pop_parse_opt,
+  pop_args_doc,
+  pop_doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+int
+get_bool (const char *str, int *pb)
+{
+  if (mu_c_strcasecmp (str, "yes") == 0
+      || mu_c_strcasecmp (str, "on") == 0
+      || mu_c_strcasecmp (str, "true") == 0)
+    *pb = 1;
+  else if (mu_c_strcasecmp (str, "no") == 0
+      || mu_c_strcasecmp (str, "off") == 0
+      || mu_c_strcasecmp (str, "false") == 0)
+    *pb = 0;
+  else
+    return 1;
+
+  return 0;
+}
+
+int
+get_port (const char *port_str, int *pn)
+{
+  short port_num;
+  long num;
+  char *p;
+  
+  num = port_num = strtol (port_str, &p, 0);
+  if (*p == 0)
+    {
+      if (num != port_num)
+       {
+         mu_error ("bad port number: %s", port_str);
+         return 1;
+       }
+    }
+  else
+    {
+      struct servent *sp = getservbyname (port_str, "tcp");
+      if (!sp)
+       {
+         mu_error ("unknown port name");
+         return 1;
+       }
+      port_num = ntohs (sp->s_port);
+    }
+  *pn = port_num;
+  return 0;
+}
+
+
+/* Global handle for pop3.  */
+mu_pop3_t pop3;
+
+/* Flag if verbosity is needed.  */
+int verbose;
+#define VERBOSE_MASK(n) (1<<((n)+1))
+#define SET_VERBOSE_MASK(n) (verbose |= VERBOSE_MASK (n))
+#define CLR_VERBOSE_MASK(n) (verbose &= VERBOSE_MASK (n))
+#define QRY_VERBOSE_MASK(n) (verbose & VERBOSE_MASK (n))
+#define HAS_VERBOSE_MASK(n) (verbose & ~1)
+#define SET_VERBOSE() (verbose |= 1)
+#define CLR_VERBOSE() (verbose &= ~1)
+#define QRY_VERBOSE() (verbose & 1)
+
+enum pop_session_status
+  {
+    pop_session_disconnected,
+    pop_session_connected,
+    pop_session_logged_in
+  };
+
+enum pop_session_status pop_session_status;
+
+int connect_argc;
+char **connect_argv;
+
+/* Host we are connected to. */
+#define host connect_argv[0]
+int port = 110;
+char *username;
+
+const char *
+pop_session_str (enum pop_session_status stat)
+{
+  switch (stat)
+    {
+    case pop_session_disconnected:
+      return "disconnected";
+      
+    case pop_session_connected:
+      return "connected";
+      
+    case pop_session_logged_in:
+      return "logged in";
+    }
+  return "unknown";
+}
+
+static void
+pop_prompt_vartab ()
+{
+  mu_vartab_t vtab;
+  
+  if (mu_vartab_create (&vtab))
+    return;
+  mu_vartab_define (vtab, "user",
+                   (pop_session_status == pop_session_logged_in) ?
+                     username : "not logged in", 1);
+  mu_vartab_define (vtab, "host",
+                   (pop_session_status != pop_session_disconnected) ?
+                     host : "not connected", 1);
+  mu_vartab_define (vtab, "program-name", mu_program_name, 1);
+  mu_vartab_define (vtab, "canonical-program-name", "mu", 1);
+  mu_vartab_define (vtab, "package", PACKAGE, 1);
+  mu_vartab_define (vtab, "version", PACKAGE_VERSION, 1);
+  mu_vartab_define (vtab, "status", pop_session_str (pop_session_status), 1);
+  
+  mu_vartab_destroy (&mutool_prompt_vartab);
+  mutool_prompt_vartab = vtab;
+}
+
+
+static int
+string_to_xlev (const char *name, int *pv)
+{
+  if (strcmp (name, "secure") == 0)
+    *pv = MU_XSCRIPT_SECURE;
+  else if (strcmp (name, "payload") == 0)
+    *pv = MU_XSCRIPT_PAYLOAD;
+  else
+    return 1;
+  return 0;
+}
+
+static int
+change_verbose_mask (int set, int argc, char **argv)
+{
+  int i;
+  
+  for (i = 0; i < argc; i++)
+    {
+      int lev;
+      
+      if (string_to_xlev (argv[i], &lev))
+       {
+         mu_error ("unknown level: %s", argv[i]);
+         return 1;
+       }
+      if (set)
+       SET_VERBOSE_MASK (lev);
+      else
+       CLR_VERBOSE_MASK (lev);
+    }
+  return 0;
+}
+
+void
+set_verbose (mu_pop3_t p)
+{
+  if (p)
+    {
+      if (QRY_VERBOSE ())
+       {
+         mu_pop3_trace (p, MU_POP3_TRACE_SET);
+       }
+      else
+       mu_pop3_trace (p, MU_POP3_TRACE_CLR);
+    }
+}
+
+void
+set_verbose_mask (mu_pop3_t p)
+{
+  if (p)
+    {
+      mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE)
+                                 ? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR,
+                             MU_XSCRIPT_SECURE);
+      mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD)
+                                 ? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR,
+                             MU_XSCRIPT_PAYLOAD);
+    }
+}
+
+static int
+com_verbose (int argc, char **argv)
+{
+  if (argc == 1)
+    {
+      if (QRY_VERBOSE ())
+       {
+         printf ("verbose is on");
+         if (HAS_VERBOSE_MASK ())
+           {
+             char *delim = " (";
+           
+             if (QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE))
+               {
+                 printf("%ssecure", delim);
+                 delim = ", ";
+               }
+             if (QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD))
+               printf("%spayload", delim);
+             printf (")");
+           }
+         printf ("\n");
+       }
+      else
+       printf ("verbose is off\n");
+    }
+  else
+    {
+      int bv;
+
+      if (get_bool (argv[1], &bv) == 0)
+       {
+         verbose |= bv;
+         if (argc > 2)
+           change_verbose_mask (verbose, argc - 2, argv + 2);
+         set_verbose (pop3);
+       }
+      else if (strcmp (argv[1], "mask") == 0)
+       change_verbose_mask (1, argc - 2, argv + 2);
+      else if (strcmp (argv[1], "unmask") == 0)
+       change_verbose_mask (0, argc - 2, argv + 2);
+      else
+       mu_error ("unknown subcommand");
+      set_verbose_mask (pop3);
+    }
+
+  return 0;
+}
+
+static int
+com_user (int argc, char **argv)
+{
+  int status;
+  
+  status = mu_pop3_user (pop3, argv[1]);
+  if (status == 0)
+    {
+      username = strdup (argv[1]);
+      pop_prompt_vartab ();
+    }
+  return status;
+}
+
+static int
+com_apop (int argc, char **argv)
+{
+  int status;
+
+  status = mu_pop3_apop (pop3, argv[1], argv[2]);
+  if (status == 0)
+    {
+      username = strdup (argv[1]);
+      pop_session_status = pop_session_logged_in;
+    }
+  return status;
+}
+
+static int
+com_capa (int argc, char **argv)
+{
+  mu_iterator_t iterator = NULL;
+  int status = 0;
+  int reread = 0;
+  int i = 1;
+  
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-reread") == 0)
+       reread = 1;
+      else
+       break;
+    }
+
+  if (i < argc)
+    {
+      if (reread)
+       {
+         status = mu_pop3_capa (pop3, 1, NULL);
+         if (status)
+           return status;
+       }
+      for (; i < argc; i++)
+       {
+         const char *elt;
+         int rc = mu_pop3_capa_test (pop3, argv[i], &elt);
+         switch (rc)
+           {
+           case 0:
+             if (*elt)
+               printf ("%s: %s\n", argv[i], elt);
+             else
+               printf ("%s is set\n", argv[i]);
+             break;
+
+           case MU_ERR_NOENT:
+             printf ("%s is not set\n", argv[i]);
+             break;
+
+           default:
+             return rc;
+           }
+       }
+    }
+  else
+    {
+      status = mu_pop3_capa (pop3, reread, &iterator);
+
+      if (status == 0)
+       {
+         for (mu_iterator_first (iterator);
+              !mu_iterator_is_done (iterator); mu_iterator_next (iterator))
+           {
+             char *capa = NULL;
+             mu_iterator_current (iterator, (void **) &capa);
+             printf ("CAPA: %s\n", capa ? capa : "");
+           }
+         mu_iterator_destroy (&iterator);
+       }
+    }
+  return status;
+}
+
+static int
+com_uidl (int argc, char **argv)
+{
+  int status = 0;
+  if (argc == 1)
+    {
+      mu_iterator_t uidl_iterator = NULL;
+      status = mu_pop3_uidl_all (pop3, &uidl_iterator);
+      if (status == 0)
+       {
+         for (mu_iterator_first (uidl_iterator);
+              !mu_iterator_is_done (uidl_iterator);
+              mu_iterator_next (uidl_iterator))
+           {
+             char *uidl = NULL;
+             mu_iterator_current (uidl_iterator, (void **) &uidl);
+             printf ("UIDL: %s\n", uidl ? uidl : "");
+           }
+         mu_iterator_destroy (&uidl_iterator);
+       }
+    }
+  else
+    {
+      char *uidl = NULL;
+      unsigned int msgno = strtoul (argv[1], NULL, 10);
+      status = mu_pop3_uidl (pop3, msgno, &uidl);
+      if (status == 0)
+       printf ("Msg: %d UIDL: %s\n", msgno, uidl ? uidl : "");
+      free (uidl);
+    }
+  return status;
+}
+
+static int
+com_list (int argc, char **argv)
+{
+  int status = 0;
+  if (argc == 1)
+    {
+      mu_iterator_t list_iterator;
+      status = mu_pop3_list_all (pop3, &list_iterator);
+      if (status == 0)
+       {
+         for (mu_iterator_first (list_iterator);
+              !mu_iterator_is_done (list_iterator);
+              mu_iterator_next (list_iterator))
+           {
+             char *list = NULL;
+             mu_iterator_current (list_iterator, (void **) &list);
+             printf ("LIST: %s\n", (list) ? list : "");
+           }
+         mu_iterator_destroy (&list_iterator);
+       }
+    }
+  else
+    {
+      size_t size = 0;
+      unsigned int msgno = strtoul (argv[1], NULL, 10);
+      status = mu_pop3_list (pop3, msgno, &size);
+      if (status == 0)
+       printf ("Msg: %u Size: %lu\n", msgno, (unsigned long) size);
+    }
+  return status;
+}
+
+static int
+com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  return mu_pop3_noop (pop3);
+}
+
+static void
+echo_off (struct termios *stored_settings)
+{
+  struct termios new_settings;
+  tcgetattr (0, stored_settings);
+  new_settings = *stored_settings;
+  new_settings.c_lflag &= (~ECHO);
+  tcsetattr (0, TCSANOW, &new_settings);
+}
+
+static void
+echo_on (struct termios *stored_settings)
+{
+  tcsetattr (0, TCSANOW, stored_settings);
+}
+
+static int
+com_pass (int argc, char **argv)
+{
+  int status;
+  char pass[256];
+  char *pwd;
+  
+  if (argc == 1)
+    {
+      struct termios stored_settings;
+
+      printf ("passwd:");
+      fflush (stdout);
+      echo_off (&stored_settings);
+      fgets (pass, sizeof pass, stdin);
+      echo_on (&stored_settings);
+      putchar ('\n');
+      fflush (stdout);
+      pass[strlen (pass) - 1] = '\0';  /* nuke the trailing line.  */
+      pwd = pass;
+    }
+  else
+    pwd = argv[1];
+  status = mu_pop3_pass (pop3, pwd);
+  if (status == 0)
+    {
+      pop_session_status = pop_session_logged_in;
+      pop_prompt_vartab ();
+    }
+  return status;
+}
+
+static int
+com_stat (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  size_t count = 0;
+  mu_off_t size = 0;
+  int status = 0;
+
+  status = mu_pop3_stat (pop3, &count, &size);
+  printf ("Mesgs: %lu Size %lu\n",
+         (unsigned long) count, (unsigned long) size);
+  return status;
+}
+
+static int
+com_stls (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  return mu_pop3_stls (pop3);
+}
+
+static int
+com_dele (int argc, char **argv)
+{
+  unsigned msgno;
+  msgno = strtoul (argv[1], NULL, 10);
+  return mu_pop3_dele (pop3, msgno);
+}
+
+static int
+com_rset (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  return mu_pop3_rset (pop3);
+}
+
+static int
+com_top (int argc, char **argv)
+{
+  mu_stream_t stream;
+  unsigned int msgno;
+  unsigned int lines;
+  int status;
+
+  msgno = strtoul (argv[1], NULL, 10);
+  if (argc == 3)
+    lines = strtoul (argv[2], NULL, 10);
+  else
+    lines = 5;
+
+  status = mu_pop3_top (pop3, msgno, lines, &stream);
+
+  if (status == 0)
+    {
+      size_t n = 0;
+      char buf[128];
+      while ((mu_stream_readline (stream, buf, sizeof buf, &n) == 0) && n)
+       printf ("%s", buf);
+      mu_stream_destroy (&stream);
+    }
+  return status;
+}
+
+static int
+com_retr (int argc, char **argv)
+{
+  mu_stream_t stream;
+  unsigned int msgno;
+  int status;
+
+  msgno = strtoul (argv[1], NULL, 10);
+  status = mu_pop3_retr (pop3, msgno, &stream);
+
+  if (status == 0)
+    {
+      size_t n = 0;
+      char buf[128];
+      while ((mu_stream_readline (stream, buf, sizeof buf, &n) == 0) && n)
+       printf ("%s", buf);
+      mu_stream_destroy (&stream);
+    }
+  return status;
+}
+
+static int
+com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  if (pop3)
+    {
+      mu_pop3_disconnect (pop3);
+      mu_pop3_destroy (&pop3);
+      pop3 = NULL;
+      
+      mu_argcv_free (connect_argc, connect_argv);
+      connect_argc = 0;
+      connect_argv = NULL;
+      pop_session_status = pop_session_disconnected;
+      pop_prompt_vartab ();
+    }
+  return 0;
+}
+
+static int
+com_connect (int argc, char **argv)
+{
+  int status;
+  int n = 0;
+  int tls = 0;
+  int i = 1;
+  
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-tls") == 0)
+       {
+         if (WITH_TLS)
+           tls = 1;
+         else
+           {
+             mu_error ("TLS not supported");
+             return 0;
+           }
+       }
+      else
+       break;
+    }
+
+  argc -= i;
+  argv += i;
+  
+  if (argc >= 2)
+    {
+      if (get_port (argv[1], &n))
+       return 0;
+    }
+  else if (tls)
+    n = MU_POP3_DEFAULT_SSL_PORT;
+  else
+    n = MU_POP3_DEFAULT_PORT;
+  
+  if (pop_session_status != pop_session_disconnected)
+    com_disconnect (0, NULL);
+  
+  status = mu_pop3_create (&pop3);
+  if (status == 0)
+    {
+      mu_stream_t tcp;
+
+      if (QRY_VERBOSE ())
+       {
+         set_verbose (pop3);
+         set_verbose_mask (pop3);
+       }
+      status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ);
+      if (status == 0)
+       {
+#ifdef WITH_TLS
+         if (tls)
+           {
+             mu_stream_t tlsstream;
+             
+             status = mu_tls_client_stream_create (&tlsstream, tcp, tcp, 0);
+             mu_stream_unref (tcp);
+             if (status)
+               {
+                 mu_error ("cannot create TLS stream: %s",
+                           mu_strerror (status));
+                 return 0;
+               }
+             tcp = tlsstream;
+           }
+#endif
+         mu_pop3_set_carrier (pop3, tcp);
+         status = mu_pop3_connect (pop3);
+       }
+      else
+       {
+         mu_pop3_destroy (&pop3);
+         pop3 = NULL;
+       }
+    }
+
+  if (status)
+    mu_error ("Failed to create pop3: %s", mu_strerror (status));
+  else
+    {
+      connect_argc = argc;
+      connect_argv = xcalloc (argc, sizeof (*connect_argv));
+      for (i = 0; i < argc; i++)
+       connect_argv[i] = xstrdup (argv[i]);
+      connect_argv[i] = NULL;
+      port = n;
+      pop_session_status = pop_session_connected;
+
+      pop_prompt_vartab ();
+    }
+  
+  return status;
+}
+
+static int
+com_quit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  int status = 0;
+  if (pop3)
+    {
+      if (mu_pop3_quit (pop3) == 0)
+       {
+         status = com_disconnect (0, NULL);
+       }
+      else
+       {
+         printf ("Try 'exit' to leave %s\n", mu_program_name);
+       }
+    }
+  else
+    printf ("Try 'exit' to leave %s\n", mu_program_name);
+  return status;
+}
+
+struct mutool_command pop_comtab[] = {
+  { "apop",       3,  3, com_apop,
+    "Authenticate with APOP: APOP user secret" },
+  { "capa",       1, -1, com_capa,
+    "List capabilities: capa [-reread] [names...]" },
+  { "disconnect", 1, 1,
+    com_disconnect, "Close connection: disconnect" },
+  { "dele",       2, 2, com_dele,
+    "Mark message: DELE msgno" },
+  { "list",       1, 2, com_list,
+    "List messages: LIST [msgno]" },
+  { "noop",       1, 1, com_noop,
+    "Send no operation: NOOP" },
+  { "pass",       1, 2, com_pass,
+    "Send passwd: PASS [passwd]" },
+  { "connect",    1, 4, com_connect,
+    "Open connection: connect [-tls] hostname port" },
+  { "quit",       1, 1, com_quit,
+    "Go to Update state : QUIT" },
+  { "retr",       2, 2, com_retr,
+    "Dowload message: RETR msgno" },
+  { "rset",       1, 1, com_rset,
+    "Unmark all messages: RSET" },
+  { "stat",       1, 1, com_stat,
+    "Get the size and count of mailbox : STAT" },
+  { "stls",       1, 1, com_stls,
+    "Start TLS negotiation" },
+  { "top",        2, 3, com_top,
+    "Get the header of message: TOP msgno [lines]" },
+  { "uidl",       1, 2, com_uidl,
+    "Get the unique id of message: UIDL [msgno]" },
+  { "user",       2, 2, com_user,
+    "send login: USER user" },
+  { "verbose",    1, 4, com_verbose,
+    "Enable Protocol tracing: verbose [on|off|mask|unmask] [x1 [x2]]" },
+  { NULL }
+};
+
+
+int
+mutool_pop (int argc, char **argv)
+{
+  int index;
+
+  if (argp_parse (&pop_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
+    return 1;
+
+  argc -= index;
+  argv += index;
+
+  if (argc)
+    {
+      mu_error (_("too many arguments"));
+      return 1;
+    }
+
+  /* Command line prompt */
+  mutool_shell_prompt = xstrdup ("pop> ");
+  pop_prompt_vartab ();
+  mutool_shell ("pop", pop_comtab);
+  return 0;
+}
diff --git a/mu/query.c b/mu/query.c
new file mode 100644
index 0000000..74b6aaf
--- /dev/null
+++ b/mu/query.c
@@ -0,0 +1,121 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+#include <mailutils/libcfg.h>
+#include "argp.h"
+#include "mu.h"
+
+static char query_doc[] = N_("mu query - query configuration values.");
+static char query_args_doc[] = N_("[OPTIONS]");
+
+char *file_name;
+int verbose_option;
+
+static struct argp_option query_options[] = {
+  { "file", 'f', N_("FILE"), 0,
+    N_("query configuration values from FILE (default mailutils.rc)"),
+    0 },
+  { "verbose", 'v', NULL, 0,
+    N_("increase output verbosity"), 0},
+  { NULL }
+};
+
+static error_t
+query_parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'f':
+      file_name = arg;
+      break;
+
+    case 'v':
+      verbose_option++;
+      break;
+      
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp query_argp = {
+  query_options,
+  query_parse_opt,
+  query_args_doc,
+  query_doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+int
+mutool_query (int argc, char **argv)
+{
+  int rc, index;
+  mu_cfg_tree_t *tree = NULL;
+  int fmtflags = 0;
+  mu_stream_t stream;
+  
+  if (argp_parse (&query_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
+    return 1;
+
+  argc -= index;
+  argv += index;
+
+  if (argc == 0)
+    {
+      mu_error (_("query what?"));
+      return 1;
+    }
+
+  if (file_name)
+    {
+      mu_load_site_rcfile = 0;
+      mu_load_user_rcfile = 0;
+      mu_load_rcfile = file_name;
+    }
+  
+  if (mu_libcfg_parse_config (&tree))
+    return 1;
+  if (!tree)
+    return 0;
+  rc = mu_stdio_stream_create (&stream, MU_STDOUT_FD, 0);
+  if (rc)
+    {
+      mu_error ("mu_stdio_stream_create: %s", mu_strerror (rc));
+      return 1;
+    }
+  if (verbose_option)
+    fmtflags = MU_CFG_FMT_LOCUS;
+  for ( ; argc > 0; argc--, argv++)
+    {
+      char *path = *argv;
+      mu_cfg_node_t *node;
+
+      if (mu_cfg_find_node (tree, path, &node) == 0)
+       mu_cfg_format_node (stream, node, fmtflags);
+    }
+  return 0;
+}
+ 
+  
diff --git a/mu/shell.c b/mu/shell.c
new file mode 100644
index 0000000..6a04fb3
--- /dev/null
+++ b/mu/shell.c
@@ -0,0 +1,492 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+#include <mailutils/tls.h>
+#include "mailutils/libargp.h"
+#include "mu.h"
+#include "xalloc.h"
+
+#ifdef WITH_READLINE
+# include <readline/readline.h>
+# include <readline/history.h>
+#endif
+
+char *mutool_shell_prompt;
+mu_vartab_t mutool_prompt_vartab;
+
+static char *
+expand_prompt ()
+{
+  char *str;
+  
+  if (!mutool_prompt_vartab
+      || mu_vartab_expand (mutool_prompt_vartab, mutool_shell_prompt, &str))
+    str = strdup (mutool_shell_prompt);
+  return str;
+}
+
+
+static int shell_exit (int, char **);
+static int shell_help (int, char **);
+static int shell_prompt (int, char **);
+#ifdef WITH_READLINE
+static int shell_history (int, char **);
+#endif
+
+struct mutool_command default_comtab[] = {
+  { "prompt",   -1, -1, shell_prompt,  "set command prompt" },
+  { "exit",       1, 1, shell_exit,    "exit program" },
+  { "help",       1, 2, shell_help,    "display this text" },
+  { "?",          1, 1, shell_help,    "synonym for `help'" },
+#ifdef WITH_READLINE
+  { "history",    1, 1, shell_history, "show command history" },
+#endif
+  { NULL }
+};
+
+/* Print a single comtab entry */
+static void
+print_comtab (struct mutool_command *tab)
+{
+  printf ("%s\t\t%s\n", tab->name, tab->doc);
+}  
+
+/* Print a single comtab entry.
+   FIXME: Way too primitive. Rewrite. */
+int
+print_help (struct mutool_command *tab, size_t n)
+{
+  if (n)
+    {
+      for (; n > 0 && tab->name; tab++, n--)
+       print_comtab (tab);
+    }
+  else
+    {
+      for (; tab->name; tab++)
+       print_comtab (tab);
+    }
+  return 0;
+}
+
+/* Print all commands from TAB matching NAME.
+   FIXME: Way too primitive. Rewrite. */
+void
+list_commands (struct mutool_command *tab, const char *name)
+{
+  size_t namelen = strlen (name);
+  int printed = 0;
+  
+  for (; tab->name; tab++)
+    {
+      /* Print in six columns. */
+      if (printed == 6)
+       {
+         printed = 0;
+         printf ("\n");
+       }
+      if (mu_c_strncasecmp (tab->name, name, namelen) == 0)
+       {
+         printf ("%s\t", tab->name);
+         printed++;
+       }
+    }
+  if (printed && printed < 6)
+    printf ("\n");
+}
+
+static struct mutool_command *
+simple_find_command (struct mutool_command *cp, const char *name)
+{
+  for (; cp->name; cp++)
+    if (strcmp (cp->name, name) == 0)
+      return cp;
+  return NULL;
+}
+
+
+static struct mutool_command *shell_comtab;
+static size_t user_command_count;
+
+static struct mutool_command *
+find_command (const char *name)
+{
+  return simple_find_command (shell_comtab, name);
+}
+
+/* Print out help for ARG, or for all of the commands if ARG is
+   not present. */
+int
+shell_help (int argc, char **argv)
+{
+  char *name = argv[1];
+  if (name)
+    {
+      struct mutool_command *com = find_command (argv[1]);
+
+      if (com)
+       print_comtab (com);
+      else
+       {
+         printf ("No commands match `%s'.  Possibilties are:\n", name);
+         list_commands (shell_comtab, name);
+       }
+    }
+  else
+    {
+      print_help (shell_comtab, user_command_count);
+      printf ("\n");
+      print_help (shell_comtab + user_command_count, 0);
+    }
+  return 0;
+}
+
+static int
+shell_prompt (int argc, char **argv)
+{
+  int quote;
+  size_t size;
+  
+  free (mutool_shell_prompt);
+  size = mu_argcv_quoted_length (argv[1], &quote);
+  mutool_shell_prompt = xmalloc (size + 1);
+  mu_argcv_unquote_copy (mutool_shell_prompt, argv[1], size);
+  return 0;
+}
+
+
+
+#ifdef WITH_READLINE
+#define HISTFILE_PREFIX "~/.mu_"
+#define HISTFILE_SUFFIX "_history"
+
+static char *
+get_history_file_name ()
+{
+  static char *filename = NULL;
+
+  if (!filename)
+    {
+      char *hname;
+      
+      hname = xmalloc(sizeof HISTFILE_PREFIX + strlen (rl_readline_name) +
+                     sizeof HISTFILE_SUFFIX - 1);
+      strcpy (hname, "~/.mu_");
+      strcat (hname, rl_readline_name);
+      strcat (hname, HISTFILE_SUFFIX);
+      filename = mu_tilde_expansion (hname, "/", NULL);
+      free(hname);
+    }
+  return filename;
+}
+
+/* Interface to Readline Completion */
+
+static char *shell_command_generator (const char *, int);
+static char **shell_completion (char *, int, int);
+
+/* Tell the GNU Readline library how to complete.  We want to try to complete
+   on command names if this is the first word in the line, or on filenames
+   if not. */
+void
+mutool_initialize_readline (const char *name)
+{
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = (char *) name;
+  rl_attempted_completion_function = (CPPFunction *) shell_completion;
+  read_history (get_history_file_name ());
+}
+
+static void
+finish_readline ()
+{
+  write_history (get_history_file_name());
+}
+
+/* Attempt to complete on the contents of TEXT.  START and END bound the
+   region of rl_line_buffer that contains the word to complete.  TEXT is
+   the word to complete.  We can use the entire contents of rl_line_buffer
+   in case we want to do some simple parsing.  Return the array of matches,
+   or NULL if there aren't any. */
+static char **
+shell_completion (char *text, int start, int end MU_ARG_UNUSED)
+{
+  char **matches;
+
+  matches = (char **) NULL;
+
+  /* If this word is at the start of the line, then it is a command
+     to complete.  Otherwise it is the name of a file in the current
+     directory. */
+  if (start == 0)
+    matches = rl_completion_matches (text, shell_command_generator);
+
+  return (matches);
+}
+
+/* Generator function for command completion.  STATE lets us know whether
+   to start from scratch; without any state (i.e. STATE == 0), then we
+   start at the top of the list. */
+static char *
+shell_command_generator (const char *text, int state)
+{
+  const char *name;
+  static int len;
+  static struct mutool_command *cmd;
+
+  /* If this is a new word to complete, initialize now.  This includes
+     saving the length of TEXT for efficiency, and initializing the index
+     variable to 0. */
+  if (!state)
+    {
+      cmd = shell_comtab;
+      len = strlen (text);
+    }
+
+  if (!cmd->name)
+    return NULL;
+    
+  
+  /* Return the next name which partially matches from the command list. */
+  while ((name = cmd->name))
+    {
+      cmd++;
+      if (strncmp (name, text, len) == 0)
+       return xstrdup (name);
+    }
+
+  /* If no names matched, then return NULL. */
+  return NULL;
+}
+
+static char *pre_input_line;
+
+static int
+pre_input (void)
+{
+  rl_insert_text (pre_input_line);
+  free (pre_input_line);
+  rl_pre_input_hook = NULL;
+  rl_redisplay ();
+  return 0;
+}
+
+static int
+retrieve_history (char *str)
+{
+  char *out;
+  int rc;
+
+  rc = history_expand (str, &out);
+  switch (rc)
+    {
+    case -1:
+      mu_error ("%s", out);
+      free (out);
+      return 1;
+
+    case 0:
+      break;
+
+    case 1:
+      pre_input_line = out;
+      rl_pre_input_hook = pre_input;
+      return 1;
+
+    case 2:
+      printf ("%s\n", out);
+      free (out);
+      return 1;
+    }
+  return 0;
+}
+
+static int
+shell_history (int argc, char **argv)
+{
+  int i;
+  HIST_ENTRY **hlist;
+
+  hlist = history_list ();
+  for (i = 0; i < history_length; i++)
+    printf ("%4d) %s\n", i + 1, hlist[i]->line);
+
+  return 0;
+}
+
+#else
+# define finish_readline()
+# define mutool_initialize_readline (const char *name)
+
+char *
+readline (char *prompt)
+{
+  static size_t size = 0;
+  static char *buf = NULL;
+
+  if (prompt)
+    {
+      printf ("%s", prompt);
+      fflush (stdout);
+    }
+  if (getline (&buf, &size, stdin) <= 0)
+    return NULL;
+  return buf;
+}
+
+void
+add_history (const char *s MU_ARG_UNUSED)
+{
+}
+#endif
+
+/* Parse and execute a command line. */
+int
+execute_line (char *line)
+{
+  int argc;
+  char **argv;
+  int status = 0;
+
+  if (mu_argcv_get (line, NULL, "#", &argc, &argv))
+    {
+      mu_error("cannot parse input line");
+      return 0;
+    }
+
+  if (argc >= 0)
+    {
+      struct mutool_command *cmd = find_command (argv[0]);
+      
+      if (!cmd)
+       mu_error ("%s: no such command.", argv[0]);
+      else if (cmd->argmin > 0 && argc < cmd->argmin)
+       mu_error ("%s: too few arguments", argv[0]);
+      else if (cmd->argmax > 0 && argc > cmd->argmax)
+       mu_error ("%s: too many arguments", argv[0]);
+      else
+       {
+         if (cmd->argmin <= 0 && argc != 2)
+           {
+             char *word = mu_str_skip_class (line, MU_CTYPE_SPACE);
+             char *arg = mu_str_skip_class_comp (word, MU_CTYPE_SPACE);
+             if (*arg)
+               {
+                 *arg++ = 0;
+                 arg = mu_str_skip_class (arg, MU_CTYPE_SPACE);
+               }
+             
+             mu_argcv_free (argc, argv);
+             argc = 2;
+             argv = xcalloc (argc + 1, sizeof (argv[0]));
+             argv[0] = xstrdup (word);
+             argv[1] = xstrdup (arg);
+             argv[2] = NULL;
+           }
+         status = cmd->func (argc, argv);
+       }
+    }
+  mu_argcv_free (argc, argv);
+  return status;
+}
+
+static char *
+input_line_interactive ()
+{
+  char *p = expand_prompt ();
+  char *line = readline (p);
+  free (p);
+  return line;
+}
+
+static char *
+input_line_script ()
+{
+  size_t size = 0;
+  char *buf = NULL;
+  if (getline (&buf, &size, stdin) <= 0)
+    return NULL;
+  return buf;
+}
+
+static int done;
+
+static int
+shell_exit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
+{
+  done = 1;
+  return 0;
+}
+  
+int
+mutool_shell (const char *name, struct mutool_command *cmd)
+{
+  size_t n;
+  int interactive = isatty (0);
+  char *(*input_line) () = interactive ?
+                             input_line_interactive : input_line_script;
+
+  for (n = 0; cmd[n].name; n++)
+    ;
+
+  user_command_count = n;
+  shell_comtab = xcalloc (n + MU_ARRAY_SIZE (default_comtab),
+                         sizeof (shell_comtab[0]));
+  memcpy (shell_comtab, cmd, n * sizeof (shell_comtab[0]));
+  memcpy (shell_comtab + n, default_comtab, sizeof (default_comtab));
+
+  mutool_initialize_readline (name);
+  while (!done)
+    {
+      char *s, *line = input_line ();
+      if (!line)
+       break;
+
+      /* Remove leading and trailing whitespace from the line.
+         Then, if there is anything left, add it to the history list
+         and execute it. */
+      s = mu_str_stripws (line);
+
+      if (*s)
+       {
+         int status;
+
+#ifdef WITH_READLINE
+         if (interactive)
+           {
+             if (retrieve_history (s))
+               continue;
+             add_history (s);
+           }
+#endif
+
+         status = execute_line (s);
+         if (status != 0)
+           mu_error ("Error: %s", mu_strerror (status));
+       }
+
+      free (line);
+    }
+  if (interactive)
+    finish_readline ();
+  return 0;
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index aa42c6f..a00a3c2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -197,5 +197,13 @@ sieve/sieve.c
 
 sql/mysql.c
 
+mu/filter.c
+mu/flt2047.c
+mu/info.c
+mu/mu.c
+mu/pop.c
+mu/query.c
+mu/shell.c
+
 # EOF
 
diff --git a/pop3d/extra.c b/pop3d/extra.c
index 26935d6..a52fee2 100644
--- a/pop3d/extra.c
+++ b/pop3d/extra.c
@@ -206,17 +206,7 @@ pop3d_init_tls_server ()
   if (rc)
     return 1;
 
-  rc = mu_stream_open (tlsstream);
-  if (rc)
-    {
-      mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"),
-                     mu_stream_strerror (tlsstream, rc));
-      mu_stream_destroy (&tlsstream);
-      return 1;
-    }
-  else
-    stream[0] = stream[1] = tlsstream;
-
+  stream[0] = stream[1] = tlsstream;
   rc = mu_stream_ioctl (iostream, MU_IOCTL_SET_STREAM, stream);
   mu_stream_unref (stream[0]);
   mu_stream_unref (stream[1]);
diff --git a/sieve/sieve.c b/sieve/sieve.c
index 1e1d395..22374da 100644
--- a/sieve/sieve.c
+++ b/sieve/sieve.c
@@ -365,12 +365,6 @@ sieve_message (mu_sieve_machine_t mach)
       mu_error (_("cannot create stream: %s"), mu_strerror (rc));
       return EX_SOFTWARE;
     }
-  rc = mu_stream_open (instr);
-  if (rc)
-    {
-      mu_error (_("cannot open stream: %s"), mu_strerror (rc));
-      return EX_SOFTWARE;
-    }
   rc = mu_stream_to_message (instr, &msg);
   if (rc)
     {
diff --git a/testsuite/smtpsend.c b/testsuite/smtpsend.c
index bb1112b..1b843e3 100644
--- a/testsuite/smtpsend.c
+++ b/testsuite/smtpsend.c
@@ -185,16 +185,12 @@ main (int argc, char **argv)
   if (!raw)
     flags = MU_STREAM_SEEK;
   if (infile)
-    {
-      MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags));
-      MU_ASSERT (mu_stream_open (instr));
-    }
+    MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags));
   else
     MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags));
   
   host = argv[1];
   MU_ASSERT (mu_tcp_stream_create (&stream, host, port, MU_STREAM_RDWR));
-  MU_ASSERT (mu_stream_open (stream));
   mu_smtp_set_carrier (smtp, stream);
   mu_stream_unref (stream);
   


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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