commit-mailutils
[Top][All Lists]
Advanced

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

[SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-112-ga783f8


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-112-ga783f8c
Date: Mon, 30 Aug 2010 07:57:48 +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=a783f8c35ed0fc9a7a18dc82f43bbe34a37aae37

The branch, stream-cleanup has been updated
       via  a783f8c35ed0fc9a7a18dc82f43bbe34a37aae37 (commit)
      from  286657e78705d061fc68c000cd3823608c522c04 (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 a783f8c35ed0fc9a7a18dc82f43bbe34a37aae37
Author: Sergey Poznyakoff <address@hidden>
Date:   Mon Aug 30 10:48:54 2010 +0300

    Add a framework for printing I/O transcripts; modify pop3d to use it.
    
    * include/mailutils/stream.h (MU_STREAM_RDTHRU)
    (MU_STREAM_WRTHRU,MU_IOCTL_SET_TRANSPORT): New flags.
    (mu_xscript_stream_create, mu_iostream_create)
    (mu_dbgstream_create): New prototypes.
    * include/mailutils/sys/dbgstream.h: New header.
    * include/mailutils/sys/iostream.h: New header.
    * include/mailutils/sys/xscript-stream.h: New header.
    * include/mailutils/sys/Makefile.am (sysinclude_HEADERS): Add
    dbgstream.h, iostream.h and xscript-stream.h
    * mailbox/dbgstream.c: New file.
    * mailbox/iostream.c: New file.
    * mailbox/xscript-stream.c: New file.
    * mailbox/Makefile.am (libmailutils_la_SOURCES): Add dbgstream.c,
    iostream.c and xscript-stream.c
    * mailbox/filter_iconv.c (_icvt_ioctl): Simplify the declaration
    of ptrans.
    * mailbox/mapfile_stream.c (_mapfile_ioctl): Likewise.
    * mailbox/memory_stream.c (_memory_ioctl): Likewise.
    * mailbox/prog_stream.c (_prog_ioctl): Likewise.
    * mailbox/tcp.c (_tcp_ioctl): Likewise.
    * mailbox/fltstream.c (filter_ctl): Likewise.
    (filter_read_through, filter_write_through): New methods.
    (mu_filter_stream_create): Allow for use of MU_STREAM_RDTHRU
    and MU_STREAM_WRTHRU to create two-way filters (writing
    triggers filtering while reading is transparent or vice versa).
    * pop3d/extra.c (istream, ostream): Remove globals.
    (iostream): New variable.
    (real_istream, real_ostream): New variables.
    (pop3d_setio): Set transcript stream on top of the I/O one,
    if required.
    (pop3d_init_tls_server): Rewrite. Revert the meaning of the
    return code to match the usual convention (0 - success).
    (transcript): Removed.
    (pop3d_outf): Remove calls to transcript.
    * pop3d/pop3d.h (istream, ostream): Remove externs.
    (iostream): New extern.
    * pop3d/retr.c: Use iostream, instear of ostream.
    * pop3d/top.c: Likewise.
    * pop3d/stls.c: Update the call to pop3d_init_tls_server.
    
    * mailbox/stream_vprintf.c (mu_stream_vprintf): Fix return
    value to match the usual convention.

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

Summary of changes:
 include/mailutils/stream.h                         |   12 +
 include/mailutils/sys/Makefile.am                  |    5 +-
 .../mailutils/sys/{streamtrans.h => dbgstream.h}   |   18 +-
 .../mailutils/sys/{streamtrans.h => iostream.h}    |   21 +-
 .../sys/{streamtrans.h => xscript-stream.h}        |   20 +-
 mailbox/Makefile.am                                |    5 +-
 mailbox/dbgstream.c                                |   86 ++++++
 mailbox/file_stream.c                              |    6 +-
 mailbox/filter_iconv.c                             |    6 +-
 mailbox/fltstream.c                                |   45 +++-
 mailbox/iostream.c                                 |  249 ++++++++++++++++
 mailbox/mapfile_stream.c                           |    6 +-
 mailbox/memory_stream.c                            |    6 +-
 mailbox/prog_stream.c                              |    6 +-
 mailbox/stream_vprintf.c                           |    2 +-
 mailbox/tcp.c                                      |    6 +-
 mailbox/xscript-stream.c                           |  300 ++++++++++++++++++++
 pop3d/extra.c                                      |  111 ++++----
 pop3d/pop3d.h                                      |    2 +-
 pop3d/retr.c                                       |    2 +-
 pop3d/stls.c                                       |    2 +-
 pop3d/top.c                                        |    2 +-
 22 files changed, 816 insertions(+), 102 deletions(-)
 copy include/mailutils/sys/{streamtrans.h => dbgstream.h} (74%)
 copy include/mailutils/sys/{streamtrans.h => iostream.h} (70%)
 copy include/mailutils/sys/{streamtrans.h => xscript-stream.h} (70%)
 create mode 100644 mailbox/dbgstream.c
 create mode 100644 mailbox/iostream.c
 create mode 100644 mailbox/xscript-stream.c

diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index 1aee884..1b74651 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -47,6 +47,9 @@ enum mu_buffer_type
 /* FIXME: This one affects only mailboxes */  
 #define MU_STREAM_QACCESS     0x00000200
 
+#define MU_STREAM_RDTHRU      0x00000400
+#define MU_STREAM_WRTHRU      0x00000800
+
 #define MU_STREAM_IRGRP       0x00001000
 #define MU_STREAM_IWGRP       0x00002000
 #define MU_STREAM_IROTH       0x00004000
@@ -59,6 +62,7 @@ enum mu_buffer_type
 #define MU_IOCTL_SET_SEEK_LIMITS 4
 #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS
 #define MU_IOCTL_GET_SEEK_LIMITS 5
+#define MU_IOCTL_SET_TRANSPORT   6
 
 void mu_stream_ref (mu_stream_t stream);
 void mu_stream_unref (mu_stream_t stream);
@@ -145,4 +149,12 @@ int mu_tcp_stream_create_with_source_host (mu_stream_t 
*stream,
 int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port,
                          int flags);
 
+int mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport,
+                            mu_stream_t logstr,
+                            const char *prefix[]);
+int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out,
+                       int flags);
+int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug,
+                       mu_log_level_t level, int flags);
+
 #endif
diff --git a/include/mailutils/sys/Makefile.am 
b/include/mailutils/sys/Makefile.am
index 34f995b..ce37112 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -19,10 +19,12 @@
 
 sysincludedir=$(pkgincludedir)/sys
 sysinclude_HEADERS = \
+ dbgstream.h\
  file_stream.h\
  filter.h\
  header_stream.h\
  header.h\
+ iostream.h\
  mapfile_stream.h\
  memory_stream.h\
  message_stream.h\
@@ -36,4 +38,5 @@ sysinclude_HEADERS = \
  stream.h\
  tls-stream.h\
  pop3.h\
- nntp.h
+ nntp.h\
+ xscript-stream.h
diff --git a/include/mailutils/sys/streamtrans.h 
b/include/mailutils/sys/dbgstream.h
similarity index 74%
copy from include/mailutils/sys/streamtrans.h
copy to include/mailutils/sys/dbgstream.h
index 25bc0d9..6934372 100644
--- a/include/mailutils/sys/streamtrans.h
+++ b/include/mailutils/sys/dbgstream.h
@@ -14,14 +14,18 @@
    You should have received a copy of the GNU Lesser General Public License
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef _MAILUTILS_SYS_STREAMTRANS_H
-#define _MAILUTILS_SYS_STREAMTRANS_H
+#ifndef _MAILUTILS_SYS_DBGSTREAM_H
+# define _MAILUTILS_SYS_DBGSTREAM_H
 
-#include <mailutils/types.h>
-#include <mailutils/sys/stream.h>
+# include <mailutils/types.h>
+# include <mailutils/stream.h>
+# include <mailutils/sys/stream.h>
 
-struct _mu_streamtrans
+struct _mu_dbgstream
 {
-  struct _mu_stream base;      /* Superclass */
-  mu_stream_t transport;       /* Transport stream */
+  struct _mu_stream stream;
+  mu_debug_t debug;
+  mu_log_level_t level;
 };
+
+#endif
diff --git a/include/mailutils/sys/streamtrans.h 
b/include/mailutils/sys/iostream.h
similarity index 70%
copy from include/mailutils/sys/streamtrans.h
copy to include/mailutils/sys/iostream.h
index 25bc0d9..d8922f6 100644
--- a/include/mailutils/sys/streamtrans.h
+++ b/include/mailutils/sys/iostream.h
@@ -14,14 +14,21 @@
    You should have received a copy of the GNU Lesser General Public License
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef _MAILUTILS_SYS_STREAMTRANS_H
-#define _MAILUTILS_SYS_STREAMTRANS_H
+#ifndef _MAILUTILS_SYS_IOSTREAM_H
+# define _MAILUTILS_SYS_IOSTREAM_H
 
-#include <mailutils/types.h>
-#include <mailutils/sys/stream.h>
+# include <mailutils/types.h>
+# include <mailutils/stream.h>
+# include <mailutils/sys/stream.h>
 
-struct _mu_streamtrans
+# define _MU_STREAM_INPUT 0
+# define _MU_STREAM_OUTPUT 1
+
+struct _mu_iostream
 {
-  struct _mu_stream base;      /* Superclass */
-  mu_stream_t transport;       /* Transport stream */
+  struct _mu_stream stream;
+  mu_stream_t transport[2];
+  int last_err_str;
 };
+
+#endif
diff --git a/include/mailutils/sys/streamtrans.h 
b/include/mailutils/sys/xscript-stream.h
similarity index 70%
copy from include/mailutils/sys/streamtrans.h
copy to include/mailutils/sys/xscript-stream.h
index 25bc0d9..c6b4538 100644
--- a/include/mailutils/sys/streamtrans.h
+++ b/include/mailutils/sys/xscript-stream.h
@@ -14,14 +14,20 @@
    You should have received a copy of the GNU Lesser General Public License
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef _MAILUTILS_SYS_STREAMTRANS_H
-#define _MAILUTILS_SYS_STREAMTRANS_H
+#ifndef _MAILUTILS_SYS_XSCRIPT_STREAM_H
+# define _MAILUTILS_SYS_XSCRIPT_STREAM_H
 
-#include <mailutils/types.h>
-#include <mailutils/sys/stream.h>
+# include <mailutils/types.h>
+# include <mailutils/stream.h>
+# include <mailutils/sys/stream.h>
 
-struct _mu_streamtrans
+struct _mu_xscript_stream
 {
-  struct _mu_stream base;      /* Superclass */
-  mu_stream_t transport;       /* Transport stream */
+  struct _mu_stream stream;
+  mu_stream_t transport;
+  mu_stream_t logstr;
+  int flags;
+  char *prefix[2];
 };
+
+#endif
diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am
index 0d04930..1fd892d 100644
--- a/mailbox/Makefile.am
+++ b/mailbox/Makefile.am
@@ -69,6 +69,7 @@ libmailutils_la_SOURCES = \
  daemon.c\
  date.c\
  dbgstderr.c\
+ dbgstream.c\
  dbgsyslog.c\
  debug.c\
  diag.c\
@@ -84,6 +85,7 @@ libmailutils_la_SOURCES = \
  gocs.c\
  hdritr.c\
  header.c\
+ iostream.c\
  iterator.c\
  ipsrv.c\
  kwd.c\
@@ -150,7 +152,8 @@ libmailutils_la_SOURCES = \
  vartab.c\
  vasnprintf.c\
  version.c\
- wicket.c
+ wicket.c\
+ xscript-stream.c
  
 BUILT_SOURCES = parsedate.c muerrno.c cfg_parser.c cfg_parser.h cfg_lexer.c
 MOSTLYCLEANFILES=
diff --git a/mailbox/dbgstream.c b/mailbox/dbgstream.c
new file mode 100644
index 0000000..19c137d
--- /dev/null
+++ b/mailbox/dbgstream.c
@@ -0,0 +1,86 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2002, 2004, 
+   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This library 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mailutils/types.h>
+#include <mailutils/alloc.h>
+#include <mailutils/errno.h>
+
+#include <mailutils/nls.h>
+#include <mailutils/stream.h>
+#include <mailutils/sys/stream.h>
+#include <mailutils/sys/dbgstream.h>
+#include <mailutils/debug.h>
+
+static int
+_dbg_write (struct _mu_stream *str, const char *buf, size_t size,
+           size_t *pnwrite)
+{
+  struct _mu_dbgstream *sp = (struct _mu_dbgstream *)str;
+  if (pnwrite)
+    *pnwrite = size;
+  while (size > 0 && (buf[size-1] == '\n' || buf[size-1] == '\r'))
+    size--;
+  if (size)
+    mu_debug_printf (sp->debug, sp->level, "%.*s\n", size, buf);
+  return 0;
+}
+
+static int
+_dbg_flush (struct _mu_stream *str)
+{
+  struct _mu_dbgstream *sp = (struct _mu_dbgstream *)str;
+  mu_debug_printf (sp->debug, sp->level, "\n");
+  return 0;
+}
+
+static void
+_dbg_done (struct _mu_stream *str)
+{
+  struct _mu_dbgstream *sp = (struct _mu_dbgstream *)str;
+  if (!(str->flags & MU_STREAM_NO_CLOSE))
+    mu_debug_destroy (&sp->debug, NULL);
+}
+
+int
+mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, mu_log_level_t level,
+                   int flags)
+{
+  struct _mu_dbgstream *sp;
+
+  sp = (struct _mu_dbgstream *)
+    _mu_stream_create (sizeof (*sp), MU_STREAM_WRITE |
+                      (flags & MU_STREAM_NO_CLOSE));
+  if (!sp)
+    return ENOMEM;
+  sp->stream.write = _dbg_write;
+  sp->stream.flush = _dbg_flush;
+  sp->stream.done = _dbg_done;
+  
+  sp->debug = debug;
+  sp->level = level;
+  mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024);
+  *pref = (mu_stream_t) sp;
+  return 0;
+}
+  
diff --git a/mailbox/file_stream.c b/mailbox/file_stream.c
index c97075f..7dc8c90 100644
--- a/mailbox/file_stream.c
+++ b/mailbox/file_stream.c
@@ -192,7 +192,7 @@ static int
 fd_ioctl (struct _mu_stream *str, int code, void *ptr)
 {
   struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t *ptrans;
   
   switch (code)
     {
@@ -200,8 +200,8 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr)
       if (!ptr)
        return EINVAL;
       ptrans = ptr;
-      (*ptrans)[0] = (mu_transport_t) fstr->fd;
-      (*ptrans)[1] = NULL;
+      ptrans[0] = (mu_transport_t) fstr->fd;
+      ptrans[1] = NULL;
       break;
 
     default:
diff --git a/mailbox/filter_iconv.c b/mailbox/filter_iconv.c
index 6674ba4..c948df4 100644
--- a/mailbox/filter_iconv.c
+++ b/mailbox/filter_iconv.c
@@ -390,7 +390,7 @@ static int
 _icvt_ioctl (mu_stream_t stream, int code, void *ptr)
 {
   struct icvt_stream *s = (struct icvt_stream *)stream;
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t *ptrans;
   
   switch (code)
     {
@@ -398,8 +398,8 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr)
       if (!ptr)
        return EINVAL;
       ptrans = ptr;
-      (*ptrans)[0] = (mu_transport_t) s->transport;
-      (*ptrans)[1] = NULL;
+      ptrans[0] = (mu_transport_t) s->transport;
+      ptrans[1] = NULL;
       break;
 
     default:
diff --git a/mailbox/fltstream.c b/mailbox/fltstream.c
index 8f6260a..c759134 100644
--- a/mailbox/fltstream.c
+++ b/mailbox/fltstream.c
@@ -335,7 +335,7 @@ static int
 filter_ctl (struct _mu_stream *stream, int op, void *ptr)
 {
   struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream;
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t *ptrans;
 
   switch (op)
     {
@@ -343,8 +343,8 @@ filter_ctl (struct _mu_stream *stream, int op, void *ptr)
       if (!ptr)
        return EINVAL;
       ptrans = ptr;
-      (*ptrans)[0] = (mu_transport_t) fs->transport;
-      (*ptrans)[1] = NULL;
+      ptrans[0] = (mu_transport_t) fs->transport;
+      ptrans[1] = NULL;
       break;
 
     default:
@@ -390,6 +390,26 @@ filter_close (mu_stream_t stream)
   return mu_stream_close (fs->transport);
 }
 
+
+static int
+filter_read_through (struct _mu_stream *stream,
+                    char *buf, size_t bufsize,
+                    size_t *pnread)
+{
+  struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream;
+  return mu_stream_read (fs->transport, buf, bufsize, pnread);
+}
+
+static int
+filter_write_through (struct _mu_stream *stream,
+                     const char *buf, size_t bufsize,
+                     size_t *pnwrite)
+{
+  struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream;
+  return mu_stream_write (fs->transport, buf, bufsize, pnwrite);
+}
+
+
 int
 mu_filter_stream_create (mu_stream_t *pflt,
                         mu_stream_t str,
@@ -402,7 +422,14 @@ mu_filter_stream_create (mu_stream_t *pflt,
 
   if ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR
       || !(flags & MU_STREAM_RDWR)
-      || (flags & (MU_STREAM_WRITE|MU_STREAM_SEEK)) == 
(MU_STREAM_WRITE|MU_STREAM_SEEK))
+      || (flags & (MU_STREAM_WRITE|MU_STREAM_SEEK)) ==
+          (MU_STREAM_WRITE|MU_STREAM_SEEK)
+      || (flags & (MU_STREAM_RDTHRU|MU_STREAM_WRTHRU)) ==
+         (MU_STREAM_RDTHRU|MU_STREAM_WRTHRU)
+      || (flags & (MU_STREAM_READ|MU_STREAM_RDTHRU)) ==
+         (MU_STREAM_READ|MU_STREAM_RDTHRU)
+      || (flags & (MU_STREAM_WRITE|MU_STREAM_WRTHRU)) ==
+          (MU_STREAM_WRITE|MU_STREAM_WRTHRU))
     return EINVAL;
  
   fs = (struct _mu_filter_stream *) _mu_stream_create (sizeof (*fs), flags);
@@ -413,11 +440,21 @@ mu_filter_stream_create (mu_stream_t *pflt,
     {
       fs->stream.read = filter_read;
       fs->stream.flush = filter_rd_flush;
+      if (flags & MU_STREAM_WRTHRU)
+       {
+         flags |= MU_STREAM_WRITE;
+         fs->stream.write = filter_write_through;
+       }
     }
   else
     {
       fs->stream.write = filter_write;
       fs->stream.flush = filter_wr_flush;
+      if (flags & MU_STREAM_RDTHRU)
+       {
+         flags |= MU_STREAM_READ;
+         fs->stream.read = filter_read_through;
+       }
     }
   fs->stream.done = filter_done;
   fs->stream.close = filter_close;
diff --git a/mailbox/iostream.c b/mailbox/iostream.c
new file mode 100644
index 0000000..4b76d3a
--- /dev/null
+++ b/mailbox/iostream.c
@@ -0,0 +1,249 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This library 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mailutils/types.h>
+#include <mailutils/alloc.h>
+#include <mailutils/errno.h>
+
+#include <mailutils/nls.h>
+#include <mailutils/stream.h>
+#include <mailutils/sys/stream.h>
+#include <mailutils/sys/iostream.h>
+
+static int
+_iostream_read (struct _mu_stream *str, char *buf, size_t bufsize,
+               size_t *pnread)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc = mu_stream_read (sp->transport[_MU_STREAM_INPUT], buf, bufsize,
+                          pnread);
+  if (rc)
+    sp->last_err_str = _MU_STREAM_INPUT;
+  return rc;
+}
+
+static int
+_iostream_readdelim (struct _mu_stream *str, char *buf, size_t bufsize,
+                   int delim, size_t *pnread)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc = mu_stream_readdelim (sp->transport[_MU_STREAM_INPUT], buf,
+                               bufsize, delim, pnread);
+  if (rc)
+    sp->last_err_str = _MU_STREAM_INPUT;
+  return rc;
+}
+
+static int
+_iostream_write (struct _mu_stream *str, const char *buf, size_t bufsize,
+                 size_t *pnwrite)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc = mu_stream_write (sp->transport[_MU_STREAM_OUTPUT], buf, bufsize,
+                           pnwrite);
+  if (rc)
+    sp->last_err_str = _MU_STREAM_OUTPUT;
+  return rc;
+}
+
+static int
+_iostream_flush (struct _mu_stream *str)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc = mu_stream_flush (sp->transport[_MU_STREAM_INPUT]);
+  if (rc)
+    {
+      sp->last_err_str = _MU_STREAM_INPUT;
+      return rc;
+    }
+  if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT])
+    {
+      rc = mu_stream_flush (sp->transport[_MU_STREAM_OUTPUT]);
+      if (rc)
+       sp->last_err_str = _MU_STREAM_OUTPUT;
+    }
+  return rc;
+}
+
+static int
+_iostream_open (struct _mu_stream *str)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc;
+  rc = mu_stream_open (sp->transport[_MU_STREAM_INPUT]);
+  if (rc)
+    {
+      sp->last_err_str = _MU_STREAM_INPUT;
+      return rc;
+    }
+  if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT])
+    {
+      rc = mu_stream_open (sp->transport[_MU_STREAM_OUTPUT]);
+      if (rc)
+       {
+         sp->last_err_str = _MU_STREAM_OUTPUT;
+         mu_stream_close (sp->transport[_MU_STREAM_INPUT]);
+       }
+    }
+  return rc;
+}
+
+static int
+_iostream_close (struct _mu_stream *str)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  if (sp->stream.flags & MU_STREAM_NO_CLOSE)
+    return 0;
+  mu_stream_close (sp->transport[_MU_STREAM_INPUT]);
+  if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT])
+    mu_stream_close (sp->transport[_MU_STREAM_OUTPUT]);
+  return 0;
+}
+
+static void
+_iostream_done (struct _mu_stream *str)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  mu_stream_unref (sp->transport[_MU_STREAM_INPUT]);
+  if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT])
+    mu_stream_unref (sp->transport[_MU_STREAM_OUTPUT]);
+}
+
+static int
+_iostream_ctl (struct _mu_stream *str, int op, void *arg)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  mu_transport_t *ptrans;
+
+  switch (op)
+    {
+    case MU_IOCTL_GET_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      ptrans = arg;
+      ptrans[0] = (mu_transport_t) sp->transport[_MU_STREAM_INPUT];
+      ptrans[1] = (mu_transport_t) sp->transport[_MU_STREAM_OUTPUT];
+      break;
+
+    case MU_IOCTL_SET_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      ptrans = arg;
+      sp->transport[_MU_STREAM_INPUT] = (mu_stream_t) ptrans[0];
+      sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1];
+      break;
+      
+    default:
+      return EINVAL;
+    }
+  return 0;
+}
+
+static int
+_iostream_wait (struct _mu_stream *str, int *pflags, struct timeval *tvp)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc = EINVAL;
+  
+  if (*pflags == MU_STREAM_READY_RD)
+    {
+      rc = mu_stream_wait (sp->transport[_MU_STREAM_INPUT], pflags, tvp);
+      if (rc)
+       sp->last_err_str = _MU_STREAM_INPUT;
+    }
+  else if (*pflags == MU_STREAM_READY_WR)
+    {
+      rc = mu_stream_wait (sp->transport[_MU_STREAM_OUTPUT], pflags, tvp);
+      if (rc)
+       sp->last_err_str = _MU_STREAM_OUTPUT;
+    }
+  return rc;
+}
+
+static int
+_iostream_shutdown (struct _mu_stream *str, int how)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  int rc = EINVAL;
+  switch (how)
+    {
+    case MU_STREAM_READ:
+      rc = mu_stream_shutdown (sp->transport[_MU_STREAM_INPUT], how);
+      if (rc)
+       sp->last_err_str = _MU_STREAM_INPUT;
+      break;
+      
+    case MU_STREAM_WRITE:
+      rc = mu_stream_shutdown (sp->transport[_MU_STREAM_OUTPUT], how);
+      if (rc)
+       sp->last_err_str = _MU_STREAM_OUTPUT;
+    }
+  return rc;
+}
+
+static const char *
+_iostream_error_string (struct _mu_stream *str, int rc)
+{
+  struct _mu_iostream *sp = (struct _mu_iostream *)str;
+  mu_stream_t transport = sp->transport[sp->last_err_str];
+  if (transport)
+    return mu_stream_strerror (transport, rc);
+  return mu_strerror (rc);
+}
+
+int
+mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out,
+                   int flags)
+{
+  struct _mu_iostream *sp;
+
+  sp = (struct _mu_iostream *)
+    _mu_stream_create (sizeof (*sp),
+                      MU_STREAM_READ | MU_STREAM_WRITE |
+                      (flags & MU_STREAM_NO_CLOSE));
+  if (!sp)
+    return ENOMEM;
+
+  sp->stream.read = _iostream_read; 
+  sp->stream.readdelim = _iostream_readdelim; 
+  sp->stream.write = _iostream_write;
+  sp->stream.flush = _iostream_flush;
+  sp->stream.open = _iostream_open; 
+  sp->stream.close = _iostream_close;
+  sp->stream.done = _iostream_done; 
+  sp->stream.ctl = _iostream_ctl;
+  sp->stream.wait = _iostream_wait;
+  sp->stream.shutdown = _iostream_shutdown;
+  sp->stream.error_string = _iostream_error_string;
+
+  mu_stream_ref (in);
+  sp->transport[_MU_STREAM_INPUT] = in;
+  mu_stream_ref (out);
+  sp->transport[_MU_STREAM_OUTPUT] = out;
+
+  mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024);
+  *pref = (mu_stream_t) sp;
+  return 0;
+}
+
+
diff --git a/mailbox/mapfile_stream.c b/mailbox/mapfile_stream.c
index 89b3e47..aeb85e5 100644
--- a/mailbox/mapfile_stream.c
+++ b/mailbox/mapfile_stream.c
@@ -209,13 +209,13 @@ static int
 _mapfile_ioctl (struct _mu_stream *str, int code, void *ptr)
 {
   struct _mu_mapfile_stream *mfs = (struct _mu_mapfile_stream *) str;
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t ptrans[2];
   
   switch (code)
     {
     case MU_IOCTL_GET_TRANSPORT:
-      (*ptrans)[0] = (mu_transport_t) mfs->fd;
-      (*ptrans)[1] = NULL;
+      ptrans[0] = (mu_transport_t) mfs->fd;
+      ptrans[1] = NULL;
       break;
 
     default:
diff --git a/mailbox/memory_stream.c b/mailbox/memory_stream.c
index ecb091f..19d4590 100644
--- a/mailbox/memory_stream.c
+++ b/mailbox/memory_stream.c
@@ -147,7 +147,7 @@ static int
 _memory_ioctl (struct _mu_stream *stream, int code, void *ptr)
 {
   struct _mu_memory_stream *mfs = (struct _mu_memory_stream *) stream;
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t *ptrans;
   
   switch (code)
     {
@@ -155,8 +155,8 @@ _memory_ioctl (struct _mu_stream *stream, int code, void 
*ptr)
       if (!ptr)
        return EINVAL;
       ptrans = ptr;
-      (*ptrans)[0] = (mu_transport_t) mfs->ptr;
-      (*ptrans)[1] = NULL;
+      ptrans[0] = (mu_transport_t) mfs->ptr;
+      ptrans[1] = NULL;
       break;
 
     default:
diff --git a/mailbox/prog_stream.c b/mailbox/prog_stream.c
index 7c65940..4c0bb8e 100644
--- a/mailbox/prog_stream.c
+++ b/mailbox/prog_stream.c
@@ -367,7 +367,7 @@ _prog_ioctl (struct _mu_stream *str, int code, void *ptr)
 {
   struct _mu_prog_stream *fstr = (struct _mu_prog_stream *) str;
   mu_transport_t t[2];
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t *ptrans;
   
   switch (code)
     {
@@ -375,9 +375,9 @@ _prog_ioctl (struct _mu_stream *str, int code, void *ptr)
       if (!ptr)
        return EINVAL;
       mu_stream_ioctl (fstr->in, MU_IOCTL_GET_TRANSPORT, t);
-      (*ptrans)[0] = t[0];
+      ptrans[0] = t[0];
       mu_stream_ioctl (fstr->out, MU_IOCTL_GET_TRANSPORT, t);
-      (*ptrans)[1] = t[1];
+      ptrans[1] = t[1];
       break;
 
     case MU_IOCTL_GET_STATUS:
diff --git a/mailbox/stream_vprintf.c b/mailbox/stream_vprintf.c
index db0bff3..5bd9c09 100644
--- a/mailbox/stream_vprintf.c
+++ b/mailbox/stream_vprintf.c
@@ -37,6 +37,6 @@ mu_stream_vprintf (mu_stream_t str, const char *fmt, va_list 
ap)
   n = strlen (buf);
   rc = mu_stream_write (str, buf, n, NULL);
   free (buf);
-  return rc == 0 ? n : -1;
+  return rc;
 }
 
diff --git a/mailbox/tcp.c b/mailbox/tcp.c
index a03eedb..0810728 100644
--- a/mailbox/tcp.c
+++ b/mailbox/tcp.c
@@ -196,7 +196,7 @@ static int
 _tcp_ioctl (mu_stream_t stream, int code, void *ptr)
 {
   struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
-  mu_transport_t (*ptrans)[2];
+  mu_transport_t *ptrans;
 
   switch (code)
     {
@@ -204,8 +204,8 @@ _tcp_ioctl (mu_stream_t stream, int code, void *ptr)
       if (!ptr)
        return EINVAL;
       ptrans = ptr;
-      (*ptrans)[0] = (mu_transport_t) tcp->fd;
-      (*ptrans)[1] = NULL;
+      ptrans[0] = (mu_transport_t) tcp->fd;
+      ptrans[1] = NULL;
       break;
 
     default:
diff --git a/mailbox/xscript-stream.c b/mailbox/xscript-stream.c
new file mode 100644
index 0000000..c3a5c40
--- /dev/null
+++ b/mailbox/xscript-stream.c
@@ -0,0 +1,300 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2002, 2004, 
+   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This library 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mailutils/types.h>
+#include <mailutils/alloc.h>
+#include <mailutils/errno.h>
+
+#include <mailutils/nls.h>
+#include <mailutils/stream.h>
+#include <mailutils/sys/stream.h>
+#include <mailutils/sys/xscript-stream.h>
+
+/* A "transcript stream" transparently writes data to and reads data from
+   an underlying transport stream, writing each lineful of data to a "log
+   stream". Writes to log stream are prefixed with a string indicating
+   direction of the data (read/write). Default prefixes are those used in
+   RFCs -- "S: ", for data written ("Server"), and "C: ", for data read
+   ("Client"). */
+
+#define TRANS_READ 0x1
+#define TRANS_WRITE 0x2
+#define FLAG_TO_PFX(c) ((c) - 1)
+
+static void
+print_transcript (struct _mu_xscript_stream *str, int flag,
+                 const char *buf, size_t size)
+{
+    while (size)
+      {
+       const char *p;
+       size_t len;
+       
+       if (str->flags & flag)
+         {
+           mu_stream_write (str->logstr,
+                            str->prefix[FLAG_TO_PFX(flag)],
+                            strlen (str->prefix[FLAG_TO_PFX (flag)]),
+                            NULL);
+           str->flags &= ~flag;
+         }
+       p = memchr (buf, '\n', size);
+       if (p)
+         {
+           len = p - buf;
+           if (p > buf && p[-1] == '\r')
+             len--;
+           mu_stream_write (str->logstr, buf, len, NULL);
+           mu_stream_write (str->logstr, "\n", 1, NULL);
+           str->flags |= flag;
+
+           len = p - buf + 1;
+           buf = p + 1;
+           size -= len;
+         }
+       else
+         {
+           mu_stream_write (str->logstr, buf, size, NULL);
+           break;
+         }
+      }
+}
+
+static int
+_xscript_read (struct _mu_stream *str, char *buf, size_t bufsize,
+              size_t *pnread)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  size_t nbytes;
+  int rc = mu_stream_read (sp->transport, buf, bufsize, &nbytes);
+
+  if (rc == 0)
+    {
+      print_transcript (sp, TRANS_READ, buf, nbytes);
+      if (pnread)
+       *pnread = nbytes;
+    }
+  return rc;
+}
+
+static int
+_xscript_readdelim (struct _mu_stream *str, char *buf, size_t bufsize,
+                   int delim, size_t *pnread)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  size_t nread;
+  int rc = mu_stream_readdelim (sp->transport, buf, bufsize, delim, &nread);
+  if (rc == 0)
+    {
+      print_transcript (sp, TRANS_READ, buf, nread);
+      if (pnread)
+       *pnread = nread;
+    }
+  return rc;
+}
+
+static int
+_xscript_write (struct _mu_stream *str, const char *buf, size_t bufsize,
+                 size_t *pnwrite)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  int rc = mu_stream_write (sp->transport, buf, bufsize, pnwrite);
+
+  if (rc == 0)
+    print_transcript (sp, TRANS_WRITE, buf, pnwrite ? *pnwrite : bufsize);
+  return rc;
+}
+
+static int
+_xscript_flush (struct _mu_stream *str)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_flush (sp->transport);
+}
+
+static int
+_xscript_open (struct _mu_stream *str)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_open (sp->transport);
+}
+
+static int
+_xscript_close (struct _mu_stream *str)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  if (sp->stream.flags & MU_STREAM_NO_CLOSE)
+    return 0;
+  return mu_stream_close (sp->transport);
+}
+
+static void
+_xscript_done (struct _mu_stream *str)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  free (sp->prefix[0]);
+  free (sp->prefix[1]);
+  mu_stream_unref (sp->transport);
+  mu_stream_unref (sp->logstr);
+}
+
+static int
+_xscript_seek (struct _mu_stream *str, mu_off_t off, mu_off_t *ppos)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_seek (sp->transport, off, MU_SEEK_SET, ppos);
+}
+
+static int
+_xscript_size (struct _mu_stream *str, mu_off_t *psize)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_size (sp->transport, psize);
+}
+
+static int
+_xscript_ctl (struct _mu_stream *str, int op, void *arg)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  mu_transport_t *ptrans;
+
+  switch (op)
+    {
+    case MU_IOCTL_GET_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      ptrans = arg;
+      ptrans[0] = (mu_transport_t) sp->transport;
+      ptrans[1] = (mu_transport_t) sp->logstr;
+      break;
+
+    case MU_IOCTL_SET_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      ptrans = arg;
+      if (ptrans[0])
+       sp->transport = (mu_stream_t) ptrans[0];
+      if (ptrans[1])
+       sp->logstr = (mu_stream_t) ptrans[1];
+      break;
+      
+    default:
+      return mu_stream_ioctl (sp->transport, op, arg);
+    }
+  return 0;
+}
+
+static int
+_xscript_wait (struct _mu_stream *str, int *pflags, struct timeval *tvp)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_wait (sp->transport, pflags, tvp);
+}
+
+static int
+_xscript_truncate (struct _mu_stream *str, mu_off_t size)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_truncate (sp->transport, size);
+}
+
+static int
+_xscript_shutdown (struct _mu_stream *str, int how)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  return mu_stream_shutdown (sp->transport, how);
+}
+
+static const char *
+_xscript_error_string (struct _mu_stream *str, int rc)
+{
+  struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
+  const char *p = mu_stream_strerror (sp->transport, rc);
+  if (!p)
+    p = mu_strerror (rc);
+  return p;
+}
+
+const char *default_prefix[2] = {
+    "C: ", "S: "
+};
+
+int
+mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport,
+                        mu_stream_t logstr,
+                        const char *prefix[])
+{
+  int flags;
+  struct _mu_xscript_stream *sp;
+
+  mu_stream_get_flags (transport, &flags);
+  sp = (struct _mu_xscript_stream *) _mu_stream_create (sizeof (*sp), flags);
+  if (!sp)
+    return ENOMEM;
+
+  sp->stream.read = _xscript_read; 
+  sp->stream.readdelim = _xscript_readdelim; 
+  sp->stream.write = _xscript_write;
+  sp->stream.flush = _xscript_flush;
+  sp->stream.open = _xscript_open; 
+  sp->stream.close = _xscript_close;
+  sp->stream.done = _xscript_done; 
+  sp->stream.seek = _xscript_seek; 
+  sp->stream.size = _xscript_size; 
+  sp->stream.ctl = _xscript_ctl;
+  sp->stream.wait = _xscript_wait;
+  sp->stream.truncate = _xscript_truncate;
+  sp->stream.shutdown = _xscript_shutdown;
+  sp->stream.error_string = _xscript_error_string;
+
+  mu_stream_ref (transport);
+  sp->transport = transport;
+  mu_stream_ref (logstr);
+  sp->logstr = logstr;
+  
+  sp->flags = TRANS_READ | TRANS_WRITE;
+  if (prefix)
+    {
+      sp->prefix[0] = strdup(prefix[0] ? prefix[0] : default_prefix[0]);
+      sp->prefix[1] = strdup(prefix[1] ? prefix[1] : default_prefix[1]);
+    }
+  else
+    {
+      sp->prefix[0] = strdup(default_prefix[0]);
+      sp->prefix[1] = strdup(default_prefix[1]);
+    }
+
+  if (sp->prefix[0] == NULL || sp->prefix[1] == 0)
+    {
+      free (sp->prefix[0]);
+      free (sp->prefix[1]);
+      free (sp);
+      return ENOMEM;
+    }
+  mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024);
+  *pref = (mu_stream_t) sp;
+  return 0;
+}
+
+
diff --git a/pop3d/extra.c b/pop3d/extra.c
index 2ab0f8a..ea0929f 100644
--- a/pop3d/extra.c
+++ b/pop3d/extra.c
@@ -20,7 +20,7 @@
 #include "pop3d.h"
 #include "mailutils/libargp.h"
 
-mu_stream_t istream, ostream;
+mu_stream_t iostream;
 
 void
 pop3d_parse_command (char *cmd, char **pcmd, char **parg)
@@ -132,12 +132,12 @@ pop3d_abquit (int reason)
    FIXME: This is sorta kludge: we could use MU_IOCTL_GET_TRANSPORT call
    to retrieve the bottom-level stream, if filter streams supported it.
 */
-static mu_stream_t real_ostream;
+static mu_stream_t real_istream, real_ostream;
 
 void
 pop3d_setio (FILE *in, FILE *out)
 {
-  mu_stream_t str;
+  mu_stream_t str, istream, ostream;
   
   if (!in)
     pop3d_abquit (ERR_NO_IFILE);
@@ -147,6 +147,7 @@ pop3d_setio (FILE *in, FILE *out)
   if (mu_stdio_stream_create (&istream, fileno (in),
                              MU_STREAM_READ | MU_STREAM_NO_CLOSE))
     pop3d_abquit (ERR_NO_IFILE);
+  real_istream = istream;
   mu_stream_set_buffer (istream, mu_buffer_line, 1024);
   
   if (mu_stdio_stream_create (&str, fileno (out),
@@ -157,6 +158,32 @@ pop3d_setio (FILE *in, FILE *out)
                        MU_STREAM_WRITE | MU_STREAM_NO_CLOSE))
     pop3d_abquit (ERR_NO_IFILE);
   mu_stream_set_buffer (ostream, mu_buffer_line, 1024);
+
+  if (mu_iostream_create (&iostream, istream, ostream, 0))
+    pop3d_abquit (ERR_FILE);
+  if (pop3d_transcript)
+    {
+      int rc;
+      mu_debug_t debug;
+      mu_stream_t dstr, xstr;
+      
+      mu_diag_get_debug (&debug);
+      
+      rc = mu_dbgstream_create (&dstr, debug, MU_DIAG_DEBUG,
+                               MU_STREAM_NO_CLOSE);
+      if (rc)
+       mu_error (_("cannot create debug stream; transcript disabled: %s"),
+                 mu_strerror (rc));
+      else
+       {
+         rc = mu_xscript_stream_create (&xstr, iostream, dstr, NULL);
+         if (rc)
+           mu_error (_("cannot create transcript stream: %s"),
+                     mu_strerror (rc));
+         else
+           iostream = xstr;
+       }
+    }
 }
 
 #ifdef WITH_TLS
@@ -166,37 +193,44 @@ pop3d_init_tls_server ()
   mu_stream_t stream;
   int rc;
 
-  rc = mu_tls_server_stream_create (&stream, istream, real_ostream, 0);
+  rc = mu_tls_server_stream_create (&stream, real_istream, real_ostream,
+                                   MU_STREAM_NO_CLOSE);
   if (rc)
-    return 0;
+    return 1;
 
   rc = mu_stream_open (stream);
   if (rc)
     {
       mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"),
                      mu_stream_strerror (stream, rc));
-      return 0;
+      mu_stream_destroy (&stream);
+      return 1;
     }
-  
-  istream = stream;
-  mu_stream_destroy (&ostream);
-  if (mu_filter_create (&ostream, stream, "rfc822", MU_FILTER_ENCODE,
-                       MU_STREAM_WRITE | MU_STREAM_NO_CLOSE))
+
+  if (mu_filter_create (&stream, stream, "rfc822", MU_FILTER_ENCODE,
+                       MU_STREAM_WRITE | MU_STREAM_RDTHRU |
+                       MU_STREAM_NO_CLOSE))
     pop3d_abquit (ERR_NO_IFILE);
-  mu_stream_set_buffer (ostream, mu_buffer_line, 1024);
-  return 1;
+  
+  if (pop3d_transcript)
+    {
+      mu_transport_t trans[2];
+
+      trans[0] = (mu_transport_t) stream;
+      trans[1] = NULL;
+      mu_stream_ioctl (iostream, MU_IOCTL_SET_TRANSPORT, trans);
+    }
+  else
+    iostream = stream;
+  return 0;
 }
 #endif
 
 void
 pop3d_bye ()
 {
-  if (istream == ostream)
-    {
-      mu_stream_close (istream);
-      mu_stream_destroy (&istream);
-    }
-  /* There's no reason closing in/out streams otherwise */
+  mu_stream_close (iostream);
+  mu_stream_destroy (&iostream);
 #ifdef WITH_TLS
   if (tls_available)
     mu_deinit_tls_libs ();
@@ -206,53 +240,28 @@ pop3d_bye ()
 void
 pop3d_flush_output ()
 {
-  mu_stream_flush (ostream);
+  mu_stream_flush (iostream);
 }
 
 int
 pop3d_is_master ()
 {
-  return ostream == NULL;
-}
-
-static void
-transcript (const char *pfx, const char *buf)
-{
-  if (pop3d_transcript)
-    {
-      int len = strlen (buf);
-      if (len > 0 && buf[len-1] == '\n')
-       {
-         len--;
-         if (len > 0 && buf[len-1] == '\r')
-           len--;
-       }
-      mu_diag_output (MU_DIAG_DEBUG, "%s: %-.*s", pfx, len, buf);
-    }
+  return iostream == NULL;
 }
 
 void
 pop3d_outf (const char *fmt, ...)
 {
   va_list ap;
-  char *buf;
   int rc;
   
   va_start (ap, fmt);
-  vasprintf (&buf, fmt, ap);
+  rc = mu_stream_vprintf (iostream, fmt, ap);
   va_end (ap);
-
-  if (!buf)
-    pop3d_abquit (ERR_NO_MEM);
-  
-  transcript ("sent", buf);
-
-  rc = mu_stream_write (ostream, buf, strlen (buf), NULL);
-  free (buf);
   if (rc)
     {
       mu_diag_output (MU_DIAG_ERROR, _("Write failed: %s"),
-                     mu_stream_strerror (ostream, rc));
+                     mu_stream_strerror (iostream, rc));
       pop3d_abquit (ERR_IO);
     }
 }
@@ -265,13 +274,13 @@ pop3d_readline (char *buffer, size_t size)
   size_t nbytes;
   
   alarm (idle_timeout);
-  rc = mu_stream_readline (istream, buffer, size, &nbytes);
+  rc = mu_stream_readline (iostream, buffer, size, &nbytes);
   alarm (0);
 
   if (rc)
     {
       mu_diag_output (MU_DIAG_ERROR, _("Read failed: %s"),
-                     mu_stream_strerror (ostream, rc));
+                     mu_stream_strerror (iostream, rc));
       pop3d_abquit (ERR_IO);
     }
   else if (nbytes == 0)
@@ -285,8 +294,6 @@ pop3d_readline (char *buffer, size_t size)
       pop3d_abquit (ERR_PROTO);
     }
 
-  transcript ("recv", buffer);
-
   return buffer;
 }
 
diff --git a/pop3d/pop3d.h b/pop3d/pop3d.h
index b7e593b..f77652f 100644
--- a/pop3d/pop3d.h
+++ b/pop3d/pop3d.h
@@ -189,7 +189,7 @@ struct pop3d_command
   pop3d_command_handler_t handler;
 };
 
-extern mu_stream_t istream, ostream;
+extern mu_stream_t iostream;
 extern mu_pop_server_t pop3srv;
 extern mu_mailbox_t mbox;
 extern int state;
diff --git a/pop3d/retr.c b/pop3d/retr.c
index 53b25c0..5c30643 100644
--- a/pop3d/retr.c
+++ b/pop3d/retr.c
@@ -46,7 +46,7 @@ pop3d_retr (char *arg)
     return ERR_UNKNOWN;
   
   pop3d_outf ("+OK\n");
-  mu_stream_copy (ostream, stream, 0);
+  mu_stream_copy (iostream, stream, 0);
   mu_stream_destroy (&stream);
 
   if (!mu_attribute_is_read (attr))
diff --git a/pop3d/stls.c b/pop3d/stls.c
index 189bc7c..6a8bbf6 100644
--- a/pop3d/stls.c
+++ b/pop3d/stls.c
@@ -35,7 +35,7 @@ pop3d_stls (char *arg)
   pop3d_outf ("+OK Begin TLS negotiation\n");
   pop3d_flush_output ();
 
-  tls_done = pop3d_init_tls_server ();
+  tls_done = pop3d_init_tls_server () == 0;
 
   if (!tls_done)
     {
diff --git a/pop3d/top.c b/pop3d/top.c
index 73d6a27..3716875 100644
--- a/pop3d/top.c
+++ b/pop3d/top.c
@@ -62,7 +62,7 @@ pop3d_top (char *arg)
     return ERR_UNKNOWN;
   pop3d_outf ("+OK\n");
 
-  mu_stream_copy (ostream, stream, 0);
+  mu_stream_copy (iostream, stream, 0);
   pop3d_outf ("\n");
   mu_stream_destroy (&stream);
   


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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