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-529-gf675ddc


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-529-gf675ddc
Date: Wed, 14 Dec 2011 09:52:14 +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=f675ddc76948a39c4b6dd4a47460a63e731e927a

The branch, master has been updated
       via  f675ddc76948a39c4b6dd4a47460a63e731e927a (commit)
       via  bc02e5c2d416789b39aa538c3213b3365f3fab75 (commit)
       via  31459010ef8c1bf790b769260788982c714624d7 (commit)
      from  7e78c6af4aa397ff422db07489850d40a9360a8c (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 f675ddc76948a39c4b6dd4a47460a63e731e927a
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Dec 14 11:50:04 2011 +0200

    Imap client: implement LSUB.
    
    LSUB is pretty similar to LIST, therefore it is implemented as a
    wrapper over the latter.
    
    * include/mailutils/imap.h (mu_imap_genlist,mu_imap_genlist_new)
    (mu_imap_lsub,mu_imap_lsub_new): New protos.
    * include/mailutils/sys/imap.h (MU_IMAP_CLIENT_LSUB_RX): New state.
    * libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Add new files.
    * libproto/imap/genlist.c: New file.
    * libproto/imap/list.c: Rewrite using generalized list functions.
    * libproto/imap/lsub.c: New file.
    * mu/imap.c: Implement lsub.

commit bc02e5c2d416789b39aa538c3213b3365f3fab75
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Dec 14 11:31:37 2011 +0200

    Imap client: Implement SUBSCRIBE and UNSUBSCRIBE.
    
    * include/mailutils/imap.h (mu_imap_subscribe)
    (mu_imap_unsubscribe): New protos.
    * include/mailutils/sys/imap.h (MU_IMAP_CLIENT_SUBSCRIBE_RX)
    (MU_IMAP_CLIENT_UNSUBSCRIBE_RX): New states.
    * libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Add
    subscribe.c and unsubscribe.c
    * libproto/imap/subscribe.c: New file.
    * libproto/imap/unsubscribe.c: New file.
    * mu/imap.c: Implement subscribe/unsubscribe.

commit 31459010ef8c1bf790b769260788982c714624d7
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Dec 14 11:10:38 2011 +0200

    Imap client: quote command arguments as necessary.
    
    * include/mailutils/imapio.h (mu_imapio_send_command)
    (mu_imapio_send_command_e,mu_imapio_send_command_v)
    (mu_imapio_last_error,mu_imapio_clearerr): New protos.
    * include/mailutils/sys/imap.h (imap_command)<uid>: Remove.
    <extra>: New member.
    * libmailutils/imapio/Makefile.am (libimapio_la_SOURCES): Add new files.
    * libmailutils/imapio/qstring.c (mu_imapio_send_qstring_unfold): Improve
    functionality.
    * libmailutils/imapio/sendcmd.c: New file.
    * libmailutils/imapio/sendcmde.c: New file.
    * libmailutils/imapio/sendcmdv.c: New file.
    * libmailutils/imapio/errstate.c: New file.
    
    * libproto/imap/gencom.c (mu_imap_gencom): Use mu_imapio_send_command_v
    * libproto/imap/appstrsiz.c: Quote command arguments as necessary.
    * libproto/imap/capability.c: Likewise.
    * libproto/imap/check.c: Likewise.
    * libproto/imap/close.c: Likewise.
    * libproto/imap/copy.c: Likewise.
    * libproto/imap/delete.c: Likewise.
    * libproto/imap/expunge.c: Likewise.
    * libproto/imap/fetch.c: Likewise.
    * libproto/imap/list.c: Likewise.
    * libproto/imap/login.c: Likewise.
    * libproto/imap/mbcreate.c: Likewise.
    * libproto/imap/noop.c: Likewise.
    * libproto/imap/rename.c: Likewise.
    * libproto/imap/select.c: Likewise.
    * libproto/imap/store.c: Likewise.
    * libproto/imap/unselect.c: Likewise.

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

Summary of changes:
 include/mailutils/imap.h                        |   19 +++-
 include/mailutils/imapio.h                      |   10 ++
 include/mailutils/sys/imap.h                    |    5 +-
 libmailutils/imapio/Makefile.am                 |    4 +
 libmailutils/imapio/{send.c => errstate.c}      |   16 ++-
 libmailutils/imapio/qstring.c                   |   74 ++++++++----
 libmailutils/imapio/{printf.c => sendcmd.c}     |   22 +++-
 libmailutils/imapio/{litstring.c => sendcmde.c} |   42 ++++---
 libmailutils/imapio/{litstring.c => sendcmdv.c} |   37 +++---
 libproto/imap/Makefile.am                       |    6 +-
 libproto/imap/appstrsiz.c                       |    5 +-
 libproto/imap/capability.c                      |    4 +-
 libproto/imap/check.c                           |    1 -
 libproto/imap/close.c                           |    2 +-
 libproto/imap/copy.c                            |   16 ++-
 libproto/imap/delete.c                          |    2 +-
 libproto/imap/expunge.c                         |    1 -
 libproto/imap/fetch.c                           |   13 ++-
 libproto/imap/gencom.c                          |   13 +--
 libproto/imap/{list.c => genlist.c}             |   22 ++--
 libproto/imap/list.c                            |  142 +----------------------
 libproto/imap/login.c                           |    4 +-
 libproto/imap/{check.c => lsub.c}               |   26 ++---
 libproto/imap/mbcreate.c                        |    2 +-
 libproto/imap/noop.c                            |    1 -
 libproto/imap/rename.c                          |    2 +-
 libproto/imap/select.c                          |    7 +-
 libproto/imap/store.c                           |   13 ++-
 libproto/imap/{delete.c => subscribe.c}         |   11 +-
 libproto/imap/unselect.c                        |    2 +-
 libproto/imap/{delete.c => unsubscribe.c}       |   11 +-
 mu/imap.c                                       |   49 ++++++++
 32 files changed, 291 insertions(+), 293 deletions(-)
 copy libmailutils/imapio/{send.c => errstate.c} (80%)
 copy libmailutils/imapio/{printf.c => sendcmd.c} (61%)
 copy libmailutils/imapio/{litstring.c => sendcmde.c} (52%)
 copy libmailutils/imapio/{litstring.c => sendcmdv.c} (54%)
 copy libproto/imap/{list.c => genlist.c} (87%)
 copy libproto/imap/{check.c => lsub.c} (72%)
 copy libproto/imap/{delete.c => subscribe.c} (85%)
 copy libproto/imap/{delete.c => unsubscribe.c} (85%)

diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index bdce14c..93d9ea3 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -87,10 +87,25 @@ int mu_imap_append_message (mu_imap_t imap, const char 
*mailbox, int flags,
                            struct tm *tm, struct mu_timezone *tz,
                            mu_message_t msg);
   
+int mu_imap_genlist (mu_imap_t imap, int lsub,
+                    const char *refname, const char *mboxname,
+                    mu_list_t retlist);
+int mu_imap_genlist_new (mu_imap_t imap, int lsub,
+                        const char *refname, const char *mboxname,
+                        mu_list_t *plist);
+  
 int mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname,
                  mu_list_t retlist);
-int mu_imap_list_new (mu_imap_t imap, const char *refname, const char 
*mboxname,
-                     mu_list_t *plist);
+int mu_imap_list_new (mu_imap_t imap, const char *refname,
+                     const char *mboxname, mu_list_t *plist);
+
+int mu_imap_lsub (mu_imap_t imap, const char *refname, const char *mboxname,
+                 mu_list_t retlist);
+int mu_imap_lsub_new (mu_imap_t imap, const char *refname,
+                     const char *mboxname, mu_list_t *plist);
+
+int mu_imap_subscribe (mu_imap_t imap, const char *mailbox);
+int mu_imap_unsubscribe (mu_imap_t imap, const char *mailbox);
   
 int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier);
 int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier);
diff --git a/include/mailutils/imapio.h b/include/mailutils/imapio.h
index e6d7594..f637fb9 100644
--- a/include/mailutils/imapio.h
+++ b/include/mailutils/imapio.h
@@ -45,6 +45,13 @@ int mu_imapio_send_qstring (struct _mu_imapio *io, const 
char *buffer);
 int mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer,
                                   int unfold);
 
+int mu_imapio_send_command_v (struct _mu_imapio *io, const char *tag,
+                             int argc, char const **argv, const char *extra);
+int mu_imapio_send_command (struct _mu_imapio *io, const char *tag,
+                       char const *cmd, ...);
+int mu_imapio_send_command_e (struct _mu_imapio *io, const char *tag,
+                             char const *cmd, ...);
+  
 int mu_imapio_send_flags (struct _mu_imapio *io, int flags);
 int mu_imapio_send_time (struct _mu_imapio *io, struct tm *tm,
                         struct mu_timezone *tz);
@@ -59,6 +66,9 @@ int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t 
*psize);
 
 int mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf);
 
+int mu_imapio_last_error (struct _mu_imapio *io);
+void mu_imapio_clearerr (struct _mu_imapio *io);
+  
 int mu_imap_flag_to_attribute (const char *item, int *attr);
 int mu_imap_format_flags (mu_stream_t str, int flags);
 
diff --git a/include/mailutils/sys/imap.h b/include/mailutils/sys/imap.h
index 9c50e84..40c23a5 100644
--- a/include/mailutils/sys/imap.h
+++ b/include/mailutils/sys/imap.h
@@ -67,6 +67,9 @@ enum mu_imap_client_state
     MU_IMAP_CLIENT_EXPUNGE_RX,
     MU_IMAP_CLIENT_APPEND_RX,
     MU_IMAP_CLIENT_LIST_RX,
+    MU_IMAP_CLIENT_SUBSCRIBE_RX,
+    MU_IMAP_CLIENT_UNSUBSCRIBE_RX,
+    MU_IMAP_CLIENT_LSUB_RX,
     MU_IMAP_CLIENT_CLOSING
   };
 
@@ -144,9 +147,9 @@ struct imap_command
   int session_state;
   char *capa;
   int rx_state;
-  int uid;
   int argc;
   char const **argv;
+  char const *extra;
   void (*tagged_handler) (mu_imap_t);
   mu_imap_response_action_t untagged_handler;
   void *untagged_handler_data;
diff --git a/libmailutils/imapio/Makefile.am b/libmailutils/imapio/Makefile.am
index d3ce8a1..f0736b4 100644
--- a/libmailutils/imapio/Makefile.am
+++ b/libmailutils/imapio/Makefile.am
@@ -19,6 +19,7 @@ noinst_LTLIBRARIES = libimapio.la
 
 libimapio_la_SOURCES = \
  create.c\
+ errstate.c\
  flags.c\
  getline.c\
  litstream.c\
@@ -27,6 +28,9 @@ libimapio_la_SOURCES = \
  qstring.c\
  replstr.c\
  send.c\
+ sendcmd.c\
+ sendcmdv.c\
+ sendcmde.c\
  time.c\
  trace.c\
  words.c\
diff --git a/libmailutils/imapio/send.c b/libmailutils/imapio/errstate.c
similarity index 80%
copy from libmailutils/imapio/send.c
copy to libmailutils/imapio/errstate.c
index 11ee049..98fa0a6 100644
--- a/libmailutils/imapio/send.c
+++ b/libmailutils/imapio/errstate.c
@@ -15,15 +15,19 @@
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <stdarg.h>
-#include <mailutils/types.h>
-#include <mailutils/imapio.h>
 #include <mailutils/stream.h>
 #include <mailutils/sys/imapio.h>
 
 int
-mu_imapio_send (mu_imapio_t io, const char *buf, size_t bytes)
+mu_imapio_last_error (struct _mu_imapio *io)
 {
-  return mu_stream_write (io->_imap_stream, buf, bytes, NULL);
+  return mu_stream_last_error (io->_imap_stream);
 }
-    
+
+void
+mu_imapio_clearerr (struct _mu_imapio *io)
+{
+  mu_stream_clearerr (io->_imap_stream);
+}
+
+
diff --git a/libmailutils/imapio/qstring.c b/libmailutils/imapio/qstring.c
index e4e7ea5..8cbeadc 100644
--- a/libmailutils/imapio/qstring.c
+++ b/libmailutils/imapio/qstring.c
@@ -19,50 +19,80 @@
 #include <mailutils/types.h>
 #include <mailutils/imapio.h>
 #include <mailutils/stream.h>
+#include <mailutils/cstr.h>
+#include <mailutils/cctype.h>
 #include <mailutils/sys/imapio.h>
 
-/* Send NIL if empty string, change the quoted string to a literal if the
-   string contains: double quotes, CR, LF, or \. */
+/* If string is NULL, send NIL.
+   If it contains \r\n, send it as a literal, replacing 
+   contiguous sequences of \r\n by a single space, if UNFOLD is set.
+   If string contains " or \, quote it,
+   Otherwise send it as is. */
 
 int
 mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer,
                               int unfold)
 {
-  if (buffer == NULL || *buffer == '\0')
+  int len;
+  
+  if (buffer == NULL)
     return mu_imapio_printf (io, "NIL");
-  if (strchr (buffer, '"') ||
-      strchr (buffer, '\r') ||
-      strchr (buffer, '\n') ||
-      strchr (buffer, '\\'))
+
+  if (buffer[len = strcspn (buffer, "\r\n")])
     {
       if (unfold)
        {
          int rc;
-         size_t len = strlen (buffer);
+         size_t size = strlen (buffer);
 
          rc = mu_stream_printf (io->_imap_stream,
-                                "{%lu}\n", (unsigned long) strlen (buffer));
+                                "{%lu}\n", (unsigned long) size);
          if (rc)
            return rc;
-         for (;;)
+         while (1)
            {
-             size_t s = strcspn (buffer, "\r\n");
-             rc = mu_stream_write (io->_imap_stream, buffer, s, NULL);
-             if (rc)
-               return rc;
-             len -= s;
-             if (len == 0)
+             mu_stream_write (io->_imap_stream, buffer, len, NULL);
+             buffer += len;
+             if (*buffer)
+               {
+                 mu_stream_write (io->_imap_stream, " ", 1, NULL);
+                 buffer = mu_str_skip_class (buffer, MU_CTYPE_ENDLN);
+                 len = strcspn (buffer, "\r\n");
+               }
+             else
                break;
-             buffer += s;
-             rc = mu_stream_write (io->_imap_stream, " ", 1, NULL);
-             if (rc)
-               return rc;
            }
        }
       else
-       return mu_imapio_send_literal_string (io, buffer);
+       mu_imapio_send_literal_string (io, buffer);
+    }
+  else if (buffer[len = strcspn (buffer, io->_imap_ws.ws_escape)])
+    {
+      int rc;
+      
+      rc = mu_stream_write (io->_imap_stream, "\"", 1, NULL);
+      while (1)
+       {
+         mu_stream_write (io->_imap_stream, buffer, len, NULL);
+         buffer += len;
+         if (*buffer)
+           {
+             mu_stream_write (io->_imap_stream, "\\", 1, NULL);
+             mu_stream_write (io->_imap_stream, buffer, 1, NULL);
+             buffer++;
+             len = strcspn (buffer, io->_imap_ws.ws_escape);
+           }
+         else
+           break;
+       }
+      mu_stream_write (io->_imap_stream, "\"", 1, NULL);
     }
-  return mu_imapio_printf (io, "\"%s\"", buffer);
+  else if (buffer[0] == 0 || buffer[strcspn (buffer, io->_imap_ws.ws_delim)])
+    mu_stream_printf (io->_imap_stream, "\"%s\"", buffer);
+  else
+    mu_stream_write (io->_imap_stream, buffer, len, NULL);
+      
+  return mu_stream_last_error (io->_imap_stream);
 }
 
 int
diff --git a/libmailutils/imapio/printf.c b/libmailutils/imapio/sendcmd.c
similarity index 61%
copy from libmailutils/imapio/printf.c
copy to libmailutils/imapio/sendcmd.c
index 801e82a..bf4c5f6 100644
--- a/libmailutils/imapio/printf.c
+++ b/libmailutils/imapio/sendcmd.c
@@ -16,20 +16,28 @@
 
 #include <config.h>
 #include <stdarg.h>
-#include <mailutils/types.h>
+#include <string.h>
 #include <mailutils/imapio.h>
 #include <mailutils/stream.h>
 #include <mailutils/sys/imapio.h>
 
+/* Send a IMAP command to the server, quoting its arguments as necessary.
+   TAG is the command tag, CMD is the command verb.  Command arguments are
+   given in variadic list terminated with NULL. */
 int
-mu_imapio_printf (mu_imapio_t io, const char *fmt, ...)
+mu_imapio_send_command (struct _mu_imapio *io, const char *tag,
+                       char const *cmd, ...)
 {
   va_list ap;
-  int status;
   
-  va_start (ap, fmt);
-  status = mu_stream_vprintf (io->_imap_stream, fmt, ap);
+  va_start (ap, cmd);
+  mu_imapio_printf (io, "%s %s", tag, cmd);
+  while ((cmd = va_arg (ap, char *)))
+    {
+      mu_imapio_send (io, " ", 1);
+      mu_imapio_send_qstring (io, cmd);
+    }
   va_end (ap);
-  return status;
+  mu_imapio_send (io, "\r\n", 2);
+  return mu_stream_last_error (io->_imap_stream);
 }
-    
diff --git a/libmailutils/imapio/litstring.c b/libmailutils/imapio/sendcmde.c
similarity index 52%
copy from libmailutils/imapio/litstring.c
copy to libmailutils/imapio/sendcmde.c
index 5ccd5fa..1618c52 100644
--- a/libmailutils/imapio/litstring.c
+++ b/libmailutils/imapio/sendcmde.c
@@ -15,29 +15,37 @@
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
-#include <mailutils/types.h>
-#include <mailutils/errno.h>
 #include <mailutils/imapio.h>
-#include <mailutils/sys/imapio.h>
 #include <mailutils/stream.h>
+#include <mailutils/sys/imapio.h>
 
+/* Send a IMAP command to the server, quoting its arguments as necessary.
+   TAG is the command tag, CMD is the command verb.  Command arguments are
+   given in variadic list terminated with NULL. The last argument is sent
+   over the wire as is, without quoting. */
 int
-mu_imapio_send_literal_string (struct _mu_imapio *io, const char *buffer)
+mu_imapio_send_command_e (struct _mu_imapio *io, const char *tag,
+                         char const *cmd, ...)
 {
-  size_t len = strlen (buffer);
-
-  mu_stream_printf (io->_imap_stream, "{%lu}\r\n", (unsigned long) len);
-
-  if (!io->_imap_server)
+  va_list ap;
+  
+  va_start (ap, cmd);
+  mu_imapio_printf (io, "%s %s", tag, cmd);
+  cmd = va_arg (ap, char *);
+  while (cmd)
     {
-      int rc = mu_imapio_getline (io);
-      if (rc)
-       return rc;
-      if (!(io->_imap_reply_ready && io->_imap_ws.ws_wordv[0][0] == '+'))
-       return MU_ERR_BADREPLY;
+      char const *next = va_arg (ap, char *);
+      
+      mu_imapio_send (io, " ", 1);
+      if (next)
+       mu_imapio_send_qstring (io, cmd);
+      else
+       mu_imapio_send (io, cmd, strlen (cmd));
+      cmd = next;
     }
-
-  return mu_stream_write (io->_imap_stream, buffer, len, NULL);
+  va_end (ap);
+  mu_imapio_send (io, "\r\n", 2);
+  return mu_stream_last_error (io->_imap_stream);
 }
diff --git a/libmailutils/imapio/litstring.c b/libmailutils/imapio/sendcmdv.c
similarity index 54%
copy from libmailutils/imapio/litstring.c
copy to libmailutils/imapio/sendcmdv.c
index 5ccd5fa..af9fa8d 100644
--- a/libmailutils/imapio/litstring.c
+++ b/libmailutils/imapio/sendcmdv.c
@@ -15,29 +15,32 @@
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <stdlib.h>
 #include <string.h>
-#include <mailutils/types.h>
-#include <mailutils/errno.h>
 #include <mailutils/imapio.h>
-#include <mailutils/sys/imapio.h>
 #include <mailutils/stream.h>
+#include <mailutils/sys/imapio.h>
 
+/* Send a IMAP command to the server, quoting its arguments as necessary.
+   TAG is the command tag, ARGV contains ARGC elements and supplies the
+   command (in ARGV[0]) and its arguments. EXTRA (if not NULL) supplies
+   additional arguments that will be sent as is. */
 int
-mu_imapio_send_literal_string (struct _mu_imapio *io, const char *buffer)
+mu_imapio_send_command_v (struct _mu_imapio *io, const char *tag,
+                         int argc, char const **argv, const char *extra)
 {
-  size_t len = strlen (buffer);
-
-  mu_stream_printf (io->_imap_stream, "{%lu}\r\n", (unsigned long) len);
-
-  if (!io->_imap_server)
+  int i;
+  
+  mu_imapio_printf (io, "%s %s", tag, argv[0]);
+  for (i = 1; i < argc; i++)
     {
-      int rc = mu_imapio_getline (io);
-      if (rc)
-       return rc;
-      if (!(io->_imap_reply_ready && io->_imap_ws.ws_wordv[0][0] == '+'))
-       return MU_ERR_BADREPLY;
+      mu_imapio_send (io, " ", 1);
+      mu_imapio_send_qstring (io, argv[i]);
     }
-
-  return mu_stream_write (io->_imap_stream, buffer, len, NULL);
+  if (extra)
+    {
+      mu_imapio_send (io, " ", 1);
+      mu_imapio_send (io, extra, strlen (extra));
+    }
+  mu_imapio_send (io, "\r\n", 2);
+  return mu_stream_last_error (io->_imap_stream);
 }
diff --git a/libproto/imap/Makefile.am b/libproto/imap/Makefile.am
index dfed78c..d422419 100644
--- a/libproto/imap/Makefile.am
+++ b/libproto/imap/Makefile.am
@@ -33,6 +33,7 @@ libmu_imap_la_SOURCES = \
  fake-folder.c\
  fetch.c\
  gencom.c\
+ genlist.c\
  callback.c\
  capability.c\
  capatst.c\
@@ -51,6 +52,7 @@ libmu_imap_la_SOURCES = \
  list.c\
  login.c\
  logout.c\
+ lsub.c\
  mbcreate.c\
  noop.c\
  rename.c\
@@ -61,7 +63,9 @@ libmu_imap_la_SOURCES = \
  state.c\
  status.c\
  store.c\
+ subscribe.c\
  tag.c\
  trace.c\
- unselect.c
+ unselect.c\
+ unsubscribe.c
 
diff --git a/libproto/imap/appstrsiz.c b/libproto/imap/appstrsiz.c
index d42b616..37b7a4e 100644
--- a/libproto/imap/appstrsiz.c
+++ b/libproto/imap/appstrsiz.c
@@ -80,8 +80,9 @@ mu_imap_append_stream_size (mu_imap_t imap, const char 
*mailbox, int flags,
       
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_imapio_printf (imap->io, "%s APPEND %s",
-                                imap->tag_str, mailbox);
+      status = mu_imapio_printf (imap->io, "%s APPEND ", imap->tag_str);
+      MU_IMAP_CHECK_ERROR (imap, status);
+      status = mu_imapio_send_qstring (imap->io, mailbox);
       MU_IMAP_CHECK_ERROR (imap, status);
       if (flags)
        {
diff --git a/libproto/imap/capability.c b/libproto/imap/capability.c
index e4bb4b7..f85321d 100644
--- a/libproto/imap/capability.c
+++ b/libproto/imap/capability.c
@@ -109,8 +109,8 @@ mu_imap_capability (mu_imap_t imap, int reread, 
mu_iterator_t *piter)
     case MU_IMAP_CLIENT_READY:
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_imapio_printf (imap->io, "%s CAPABILITY\r\n",
-                                imap->tag_str); 
+      status = mu_imapio_send_command (imap->io, imap->tag_str,
+                                      "CAPABILITY", NULL); 
       MU_IMAP_CHECK_EAGAIN (imap, status);
       MU_IMAP_FCLR (imap, MU_IMAP_RESP);
       imap->client_state = MU_IMAP_CLIENT_CAPABILITY_RX;
diff --git a/libproto/imap/check.c b/libproto/imap/check.c
index 0346906..d5db25b 100644
--- a/libproto/imap/check.c
+++ b/libproto/imap/check.c
@@ -30,7 +30,6 @@ mu_imap_check (mu_imap_t imap)
     MU_IMAP_SESSION_SELECTED,
     NULL,
     MU_IMAP_CLIENT_CHECK_RX,
-    0,
     1,
     &command,
     NULL
diff --git a/libproto/imap/close.c b/libproto/imap/close.c
index a92d598..50bf1c5 100644
--- a/libproto/imap/close.c
+++ b/libproto/imap/close.c
@@ -37,9 +37,9 @@ mu_imap_close (mu_imap_t imap)
     MU_IMAP_SESSION_SELECTED,
     NULL,
     MU_IMAP_CLIENT_CLOSE_RX,
-    0,
     1,
     &command,
+    NULL,
     _mu_close_handler
   };
   return mu_imap_gencom (imap, &com);
diff --git a/libproto/imap/copy.c b/libproto/imap/copy.c
index 507b701..5598c20 100644
--- a/libproto/imap/copy.c
+++ b/libproto/imap/copy.c
@@ -26,19 +26,23 @@
 int
 mu_imap_copy (mu_imap_t imap, int uid, const char *msgset, const char *mailbox)
 {
-  char const *argv[3];
+  char const *argv[4];
+  int i;
   static struct imap_command com;
 
-  argv[0] = "COPY";
-  argv[1] = msgset;
-  argv[2] = mailbox;
+  i = 0;
+  if (uid)
+    argv[i++] = "UID";
+  argv[i++] = "COPY";
+  argv[i++] = msgset;
+  argv[i++] = mailbox;
 
   com.session_state = MU_IMAP_SESSION_SELECTED;
   com.capa = NULL;
   com.rx_state = MU_IMAP_CLIENT_COPY_RX;
-  com.uid = 0;
-  com.argc = 3;
+  com.argc = i;
   com.argv = argv;
+  com.extra = NULL;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/delete.c b/libproto/imap/delete.c
index 6f986e9..0818c4b 100644
--- a/libproto/imap/delete.c
+++ b/libproto/imap/delete.c
@@ -37,9 +37,9 @@ mu_imap_delete (mu_imap_t imap, const char *mailbox)
   com.session_state = MU_IMAP_SESSION_AUTH;
   com.capa = NULL;
   com.rx_state = MU_IMAP_CLIENT_DELETE_RX;
-  com.uid = 0;
   com.argc = 2;
   com.argv = argv;
+  com.extra = NULL;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/expunge.c b/libproto/imap/expunge.c
index 376ee4b..1643c01 100644
--- a/libproto/imap/expunge.c
+++ b/libproto/imap/expunge.c
@@ -30,7 +30,6 @@ mu_imap_expunge (mu_imap_t imap)
     MU_IMAP_SESSION_SELECTED,
     NULL,
     MU_IMAP_CLIENT_EXPUNGE_RX,
-    0,
     1,
     &command,
     NULL
diff --git a/libproto/imap/fetch.c b/libproto/imap/fetch.c
index cecf794..f32ed3a 100644
--- a/libproto/imap/fetch.c
+++ b/libproto/imap/fetch.c
@@ -32,18 +32,21 @@ int
 mu_imap_fetch (mu_imap_t imap, int uid, const char *msgset, const char *items)
 {
   char const *argv[3];
+  int i;
   static struct imap_command com;
 
-  argv[0] = "FETCH";
-  argv[1] = msgset;
-  argv[2] = items;
+  i = 0;
+  if (uid)
+    argv[i++] = "UID";
+  argv[i++] = "FETCH";
+  argv[i++] = msgset;
   
   com.session_state = MU_IMAP_SESSION_SELECTED;
   com.capa = NULL;
   com.rx_state = MU_IMAP_CLIENT_FETCH_RX;
-  com.uid = uid;
-  com.argc = 3;
+  com.argc = i;
   com.argv = argv;
+  com.extra = items;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/gencom.c b/libproto/imap/gencom.c
index ce4b350..57e8643 100644
--- a/libproto/imap/gencom.c
+++ b/libproto/imap/gencom.c
@@ -28,7 +28,6 @@ int
 mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd)
 {
   int status;
-  int i;
   
   if (imap == NULL || !cmd || cmd->argc < 1)
     return EINVAL;
@@ -57,16 +56,8 @@ mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd)
     {
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_imapio_printf (imap->io, "%s", imap->tag_str);
-      if (status == 0 && cmd->uid)
-       status = mu_imapio_printf (imap->io, " UID");
-      MU_IMAP_CHECK_ERROR (imap, status);
-      for (i = 0; i < cmd->argc; i++)
-       {
-         status = mu_imapio_printf (imap->io, " %s", cmd->argv[i]);
-         MU_IMAP_CHECK_ERROR (imap, status);
-       }
-      status = mu_imapio_send (imap->io, "\r\n", 2);
+      status = mu_imapio_send_command_v (imap->io, imap->tag_str,
+                                        cmd->argc, cmd->argv, cmd->extra);
       MU_IMAP_CHECK_ERROR (imap, status);
       MU_IMAP_FCLR (imap, MU_IMAP_RESP);
       imap->client_state = cmd->rx_state;
diff --git a/libproto/imap/list.c b/libproto/imap/genlist.c
similarity index 87%
copy from libproto/imap/list.c
copy to libproto/imap/genlist.c
index 9fb9696..5931963 100644
--- a/libproto/imap/list.c
+++ b/libproto/imap/genlist.c
@@ -33,6 +33,7 @@ struct list_closure
 {
   int error_code;
   mu_list_t retlist;
+  const char *command;
 };
 
 static int
@@ -74,7 +75,7 @@ list_untagged_handler (mu_imap_t imap, mu_list_t resp, void 
*data)
 
   mu_list_count (resp, &count);
   if (count == 4 &&
-      _mu_imap_list_nth_element_is_string (resp, 0, "LIST"))
+      _mu_imap_list_nth_element_is_string (resp, 0, clos->command))
     {
       struct mu_list_response *rp;
 
@@ -121,27 +122,29 @@ list_untagged_handler (mu_imap_t imap, mu_list_t resp, 
void *data)
 }
   
 int
-mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname,
-             mu_list_t retlist)
+mu_imap_genlist (mu_imap_t imap, int lsub,
+                const char *refname, const char *mboxname,
+                mu_list_t retlist)
 {
   char const *argv[3];
   static struct imap_command com;
   struct list_closure clos;
   int rc;
 
-  argv[0] = "LIST";
+  argv[0] = lsub ? "LSUB" : "LIST";
   argv[1] = refname;
   argv[2] = mboxname;
 
   clos.error_code = 0;
   clos.retlist = retlist;
+  clos.command = argv[0];
   
   com.session_state = MU_IMAP_SESSION_AUTH;
   com.capa = NULL;
-  com.rx_state = MU_IMAP_CLIENT_LIST_RX;
-  com.uid = 0;
+  com.rx_state = lsub ? MU_IMAP_CLIENT_LSUB_RX : MU_IMAP_CLIENT_LIST_RX;
   com.argc = 3;
   com.argv = argv;
+  com.extra = NULL;
   com.tagged_handler = NULL;
   com.untagged_handler = list_untagged_handler;
   com.untagged_handler_data = &clos;
@@ -154,15 +157,16 @@ mu_imap_list (mu_imap_t imap, const char *refname, const 
char *mboxname,
 }
 
 int
-mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname,
-                 mu_list_t *plist)
+mu_imap_genlist_new (mu_imap_t imap, int lsub,
+                    const char *refname, const char *mboxname,
+                    mu_list_t *plist)
 {
   mu_list_t list;
   int rc = mu_list_create (&list);
   if (rc == 0)
     {
       mu_list_set_destroy_item (list, mu_list_response_free);
-      rc = mu_imap_list (imap, refname, mboxname, list);
+      rc = mu_imap_genlist (imap, lsub, refname, mboxname, list);
       if (rc)
        mu_list_destroy (&list);
       else
diff --git a/libproto/imap/list.c b/libproto/imap/list.c
index 9fb9696..3fd7f59 100644
--- a/libproto/imap/list.c
+++ b/libproto/imap/list.c
@@ -19,154 +19,20 @@
 # include <config.h>
 #endif
 
-#include <stdlib.h>
-#include <string.h>
-#include <mailutils/errno.h>
-#include <mailutils/address.h>
-#include <mailutils/cstr.h>
-#include <mailutils/cctype.h>
-#include <mailutils/list.h>
 #include <mailutils/imap.h>
-#include <mailutils/sys/imap.h>
 
-struct list_closure
-{
-  int error_code;
-  mu_list_t retlist;
-};
-
-static int
-count_level (const char *name, int delim)
-{
-  int level = 0;
-
-  while (*name)
-    if (*name++ == delim)
-      level++;
-  return level;
-}
-
-static int
-list_attr_conv (void *item, void *data)
-{
-  struct imap_list_element *elt = item;
-  struct mu_list_response *rp = data;
-  
-  if (elt->type != imap_eltype_string)
-    return 0;
-  if (mu_c_strcasecmp (elt->v.string, "\\Noinferiors"))
-    rp->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
-  if (mu_c_strcasecmp (elt->v.string, "\\Noselect"))
-    rp->type |= MU_FOLDER_ATTRIBUTE_FILE;
-  /* FIXME: \Marked nad \Unmarked have no correspondence in flags. */
-  return 0;
-}
-  
-static void
-list_untagged_handler (mu_imap_t imap, mu_list_t resp, void *data)
-{
-  struct list_closure *clos = data;
-  struct imap_list_element *elt;
-  size_t count;
-  
-  if (clos->error_code)
-    return;
-
-  mu_list_count (resp, &count);
-  if (count == 4 &&
-      _mu_imap_list_nth_element_is_string (resp, 0, "LIST"))
-    {
-      struct mu_list_response *rp;
-
-      rp = calloc (1, sizeof (*rp));
-      if (!rp)
-       {
-         clos->error_code = ENOMEM;
-         return;
-       }
-         
-      elt = _mu_imap_list_at (resp, 1);
-      if (!(elt && elt->type == imap_eltype_list))
-       return;
-      rp->type = 0;
-      mu_list_foreach (elt->v.list, list_attr_conv, rp);
-
-      elt = _mu_imap_list_at (resp, 3);
-      if (!(elt && elt->type == imap_eltype_string))
-       return;
-      rp->name = strdup (elt->v.string);
-      if (!rp->name)
-       {
-         free (rp);
-         clos->error_code = ENOMEM;
-         return;
-       }
-
-      elt = _mu_imap_list_at (resp, 2);
-      if (!(elt && elt->type == imap_eltype_string))
-       return;
-      if (mu_c_strcasecmp (elt->v.string, "NIL") == 0)
-       {
-         rp->separator = 0;
-         rp->level = 0;
-       }
-      else
-       {
-         rp->separator = elt->v.string[0];
-         rp->level = count_level (rp->name, rp->separator);
-       }
-      if ((clos->error_code = mu_list_append (clos->retlist, rp)))
-       mu_list_response_free (rp);
-    }
-}
-  
 int
 mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname,
              mu_list_t retlist)
 {
-  char const *argv[3];
-  static struct imap_command com;
-  struct list_closure clos;
-  int rc;
-
-  argv[0] = "LIST";
-  argv[1] = refname;
-  argv[2] = mboxname;
-
-  clos.error_code = 0;
-  clos.retlist = retlist;
-  
-  com.session_state = MU_IMAP_SESSION_AUTH;
-  com.capa = NULL;
-  com.rx_state = MU_IMAP_CLIENT_LIST_RX;
-  com.uid = 0;
-  com.argc = 3;
-  com.argv = argv;
-  com.tagged_handler = NULL;
-  com.untagged_handler = list_untagged_handler;
-  com.untagged_handler_data = &clos;
-
-  rc = mu_imap_gencom (imap, &com);
-  if (rc == 0)
-    rc = clos.error_code;
-
-  return rc;
+  return mu_imap_genlist (imap, 0, refname, mboxname, retlist);
 }
 
 int
 mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname,
                  mu_list_t *plist)
 {
-  mu_list_t list;
-  int rc = mu_list_create (&list);
-  if (rc == 0)
-    {
-      mu_list_set_destroy_item (list, mu_list_response_free);
-      rc = mu_imap_list (imap, refname, mboxname, list);
-      if (rc)
-       mu_list_destroy (&list);
-      else
-       *plist = list;
-    }
-  return rc;
+  return mu_imap_genlist_new (imap, 0, refname, mboxname, plist);
 }
+
+
diff --git a/libproto/imap/login.c b/libproto/imap/login.c
index 2a8f363..807d7b4 100644
--- a/libproto/imap/login.c
+++ b/libproto/imap/login.c
@@ -43,8 +43,8 @@ mu_imap_login (mu_imap_t imap, const char *user, const char 
*pass)
        _mu_imap_xscript_level (imap, MU_XSCRIPT_SECURE);
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_imapio_printf (imap->io, "%s LOGIN \"%s\" \"%s\"\r\n",
-                                imap->tag_str, user, pass);
+      status = mu_imapio_send_command (imap->io, imap->tag_str,
+                                      "LOGIN", user, pass, NULL);
       _mu_imap_xscript_level (imap, MU_XSCRIPT_NORMAL);
       /* FIXME: how to obscure the passwd in the stream buffer? */
       MU_IMAP_CHECK_EAGAIN (imap, status);
diff --git a/libproto/imap/check.c b/libproto/imap/lsub.c
similarity index 72%
copy from libproto/imap/check.c
copy to libproto/imap/lsub.c
index 0346906..106f70a 100644
--- a/libproto/imap/check.c
+++ b/libproto/imap/lsub.c
@@ -20,21 +20,19 @@
 #endif
 
 #include <mailutils/imap.h>
-#include <mailutils/sys/imap.h>
 
 int
-mu_imap_check (mu_imap_t imap)
+mu_imap_lsub (mu_imap_t imap, const char *refname, const char *mboxname,
+             mu_list_t retlist)
 {
-  static char const *command = "CHECK";
-  static struct imap_command com = {
-    MU_IMAP_SESSION_SELECTED,
-    NULL,
-    MU_IMAP_CLIENT_CHECK_RX,
-    0,
-    1,
-    &command,
-    NULL
-  };
-  return mu_imap_gencom (imap, &com);
+  return mu_imap_genlist (imap, 1, refname, mboxname, retlist);
 }
-      
+
+int
+mu_imap_lsub_new (mu_imap_t imap, const char *refname, const char *mboxname,
+                 mu_list_t *plist)
+{
+  return mu_imap_genlist_new (imap, 1, refname, mboxname, plist);
+}
+
+
diff --git a/libproto/imap/mbcreate.c b/libproto/imap/mbcreate.c
index b7b9063..a9b7edd 100644
--- a/libproto/imap/mbcreate.c
+++ b/libproto/imap/mbcreate.c
@@ -37,9 +37,9 @@ mu_imap_mailbox_create (mu_imap_t imap, const char *mailbox)
   com.session_state = MU_IMAP_SESSION_AUTH;
   com.capa = NULL;
   com.rx_state = MU_IMAP_CLIENT_DELETE_RX;
-  com.uid = 0;
   com.argc = 2;
   com.argv = argv;
+  com.extra = 0;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/noop.c b/libproto/imap/noop.c
index 62d5035..b5676f8 100644
--- a/libproto/imap/noop.c
+++ b/libproto/imap/noop.c
@@ -30,7 +30,6 @@ mu_imap_noop (mu_imap_t imap)
     MU_IMAP_SESSION_INIT,
     NULL,
     MU_IMAP_CLIENT_NOOP_RX,
-    0,
     1,
     &command,
     NULL
diff --git a/libproto/imap/rename.c b/libproto/imap/rename.c
index 44d0773..334df7d 100644
--- a/libproto/imap/rename.c
+++ b/libproto/imap/rename.c
@@ -36,9 +36,9 @@ mu_imap_rename (mu_imap_t imap, const char *mailbox, const 
char *new_mailbox)
   com.session_state = MU_IMAP_SESSION_AUTH;
   com.capa = NULL;
   com.rx_state = MU_IMAP_CLIENT_DELETE_RX;
-  com.uid = 0;
   com.argc = 3;
   com.argv = argv;
+  com.extra = NULL;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/select.c b/libproto/imap/select.c
index be19668..05dd550 100644
--- a/libproto/imap/select.c
+++ b/libproto/imap/select.c
@@ -101,10 +101,9 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int 
writable,
     case MU_IMAP_CLIENT_READY:
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_imapio_printf (imap->io, "%s %s %s\r\n",
-                                imap->tag_str,
-                                writable ? "SELECT" : "EXAMINE",
-                                mbox);
+      status = mu_imapio_send_command (imap->io, imap->tag_str,
+                                      writable ? "SELECT" : "EXAMINE",
+                                      mbox, NULL);
       MU_IMAP_CHECK_ERROR (imap, status);
       MU_IMAP_FCLR (imap, MU_IMAP_RESP);
       imap->client_state = MU_IMAP_CLIENT_SELECT_RX;
diff --git a/libproto/imap/store.c b/libproto/imap/store.c
index 8faecac..be1349f 100644
--- a/libproto/imap/store.c
+++ b/libproto/imap/store.c
@@ -29,18 +29,21 @@ int
 mu_imap_store (mu_imap_t imap, int uid, const char *msgset, const char *items)
 {
   char const *argv[3];
+  int i;
   static struct imap_command com;
 
-  argv[0] = "STORE";
-  argv[1] = msgset;
-  argv[2] = items;
+  i = 0;
+  if (uid)
+    argv[i++] = "UID";
+  argv[i++] = "STORE";
+  argv[i++] = msgset;
   
   com.session_state = MU_IMAP_SESSION_SELECTED;
   com.capa = NULL;
   com.rx_state = MU_IMAP_CLIENT_STORE_RX;
-  com.uid = uid;
-  com.argc = 3;
+  com.argc = i;
   com.argv = argv;
+  com.extra = items;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/delete.c b/libproto/imap/subscribe.c
similarity index 85%
copy from libproto/imap/delete.c
copy to libproto/imap/subscribe.c
index 6f986e9..3cf71a6 100644
--- a/libproto/imap/delete.c
+++ b/libproto/imap/subscribe.c
@@ -19,27 +19,24 @@
 # include <config.h>
 #endif
 
-#include <stdlib.h>
-#include <string.h>
-#include <mailutils/errno.h>
 #include <mailutils/imap.h>
 #include <mailutils/sys/imap.h>
 
 int
-mu_imap_delete (mu_imap_t imap, const char *mailbox)
+mu_imap_subscribe (mu_imap_t imap, const char *mailbox)
 {
   char const *argv[2];
   static struct imap_command com;
 
-  argv[0] = "DELETE";
+  argv[0] = "SUBSCRIBE";
   argv[1] = mailbox;
 
   com.session_state = MU_IMAP_SESSION_AUTH;
   com.capa = NULL;
-  com.rx_state = MU_IMAP_CLIENT_DELETE_RX;
-  com.uid = 0;
+  com.rx_state = MU_IMAP_CLIENT_SUBSCRIBE_RX;
   com.argc = 2;
   com.argv = argv;
+  com.extra = NULL;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/libproto/imap/unselect.c b/libproto/imap/unselect.c
index f45c4aa..c1ac499 100644
--- a/libproto/imap/unselect.c
+++ b/libproto/imap/unselect.c
@@ -30,9 +30,9 @@ mu_imap_unselect (mu_imap_t imap)
     MU_IMAP_SESSION_SELECTED,
     NULL,
     MU_IMAP_CLIENT_UNSELECT_RX,
-    0,
     1,
     &command,
+    NULL,
     _mu_close_handler
   };
   return mu_imap_gencom (imap, &com);
diff --git a/libproto/imap/delete.c b/libproto/imap/unsubscribe.c
similarity index 85%
copy from libproto/imap/delete.c
copy to libproto/imap/unsubscribe.c
index 6f986e9..4831829 100644
--- a/libproto/imap/delete.c
+++ b/libproto/imap/unsubscribe.c
@@ -19,27 +19,24 @@
 # include <config.h>
 #endif
 
-#include <stdlib.h>
-#include <string.h>
-#include <mailutils/errno.h>
 #include <mailutils/imap.h>
 #include <mailutils/sys/imap.h>
 
 int
-mu_imap_delete (mu_imap_t imap, const char *mailbox)
+mu_imap_unsubscribe (mu_imap_t imap, const char *mailbox)
 {
   char const *argv[2];
   static struct imap_command com;
 
-  argv[0] = "DELETE";
+  argv[0] = "UNSUBSCRIBE";
   argv[1] = mailbox;
 
   com.session_state = MU_IMAP_SESSION_AUTH;
   com.capa = NULL;
-  com.rx_state = MU_IMAP_CLIENT_DELETE_RX;
-  com.uid = 0;
+  com.rx_state = MU_IMAP_CLIENT_UNSUBSCRIBE_RX;
   com.argc = 2;
   com.argv = argv;
+  com.extra = NULL;
   com.tagged_handler = NULL;
   com.untagged_handler = NULL;
 
diff --git a/mu/imap.c b/mu/imap.c
index 699e270..ffa7d68 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -818,6 +818,24 @@ com_create (int argc, char **argv)
 }
 
 static int
+com_subscribe (int argc, char **argv)
+{
+  int status = mu_imap_subscribe (imap, argv[1]);
+  if (status)
+    report_failure ("subscribe", status);
+  return 0;
+}
+
+static int
+com_unsubscribe (int argc, char **argv)
+{
+  int status = mu_imap_unsubscribe (imap, argv[1]);
+  if (status)
+    report_failure ("unsubscribe", status);
+  return 0;
+}
+
+static int
 com_append (int argc, char **argv)
 {
   struct tm tmbuf, *tm = NULL;
@@ -931,6 +949,25 @@ com_list (int argc, char **argv)
   return 0;
 }
 
+static int
+com_lsub (int argc, char **argv)
+{
+  mu_list_t list;
+  int rc;
+  mu_stream_t out;
+  
+  rc = mu_imap_lsub_new (imap, argv[1], argv[2], &list);
+  if (rc)
+    {
+      report_failure ("lsub", rc);
+      return 0;
+    }
+
+  out = mutool_open_pager ();
+  mu_list_foreach (list, print_list_item, out);
+  mu_stream_unref (out);
+  return 0;
+}
 
 struct mutool_command imap_comtab[] = {
   { "capability",   1, -1, 0,
@@ -1023,6 +1060,18 @@ struct mutool_command imap_comtab[] = {
     com_list,
     N_("REF MBOX"),
     N_("List matching mailboxes") },
+  { "lsub",         3, 3, 0,
+    com_lsub,
+    N_("REF MBOX"),
+    N_("List subscribed mailboxes") },
+  { "subscribe",    2, 2, 0,
+    com_subscribe,
+    N_("MBOX"),
+    N_("Subscribe to a mailbox") },
+  { "unsubscribe",    2, 2, 0,
+    com_unsubscribe,
+    N_("MBOX"),
+    N_("Remove mailbox from subscription list") },
   { "quit",         1, 1, 0,
     com_logout,
     NULL,


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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