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-468-g80b012f


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-468-g80b012f
Date: Thu, 24 Nov 2011 21:41:19 +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=80b012f7f89ca6acbf1191ef1b8073239509b941

The branch, master has been updated
       via  80b012f7f89ca6acbf1191ef1b8073239509b941 (commit)
       via  bbc46f0ca2ec67b0c20355ceba3b9e5349032b47 (commit)
       via  9a419c505d4e72bea50fe33de1aab1d82fde4f82 (commit)
       via  54eb06740c906c696749cd04c9afa6c43694f647 (commit)
       via  0e8d5bfe95e90df34616f780c9e11c076ca306c3 (commit)
       via  9316bc63c12f6caa0303bb0c89a5831a90e523b4 (commit)
       via  45ecec0da61992ea2add464da3be67078b8dbe0e (commit)
      from  424589b91c3f367e4c9926804df4bf73bf100e59 (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 80b012f7f89ca6acbf1191ef1b8073239509b941
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 23:32:26 2011 +0200

    Change callback handling in imap client.
    
    * include/mailutils/imap.h (MU_IMAP_CB_NO)
    (MU_IMAP_CB_BAD,MU_IMAP_CB_BYE)
    (MU_IMAP_CB_PREAUTH): New callbacks.
    (mu_imap_callback_t): Change signature.
    (mu_imap_callback): Change signature.
    * include/mailutils/sys/imap.h (mu_imap_client_state)
    <MU_IMAP_CLOSING>: New state.
    * libproto/imap/callback.c (mu_imap_callback): Change signature.
    Fix boundary check.
    (mu_imap_register_callback_function): Fix boundary check.
    * libproto/imap/connect.c (mu_imap_connect): Use mu_imap_foreach_response
    to parse response.
    * libproto/imap/response.c (_mu_imap_response): Check number of words
    before dereferencing them.
    * libproto/imap/resproc.c: Handle all server responses.
    * mu/imap.c (com_connect): Set POPAUTH callback.
    Set verbosity flags after I/O structure has been created.

commit bbc46f0ca2ec67b0c20355ceba3b9e5349032b47
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 21:30:07 2011 +0200

    list: new operations: head and tail.
    
    * include/mailutils/list.h (mu_list_head, mu_list_tail): New prototypes.
    * libmailutils/list/head.c: New file.
    * libmailutils/list/tail.c: New file.
    * libmailutils/list/Makefile.am (liblist_la_SOURCES): Add new files.
    * libmailutils/tests/listop.c (head,tail): New commands.
    * libmailutils/tests/list.at: Test head and tail.

commit 9a419c505d4e72bea50fe33de1aab1d82fde4f82
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 19:21:38 2011 +0200

    imap client: reflect changes to imapio parser.
    
    * include/mailutils/sys/imap.h (_mu_imap_seterrstrz): New proto.
    * libmailutils/imapio/replstr.c: Update.
    * libproto/imap/err.c (_mu_imap_seterrstrz): New function.
    * libproto/imap/id.c: Remove superfluous calls to _mu_imap_seterrstr.
    * libproto/imap/login.c: Likewise.
    * libproto/imap/select.c: Likewise.
    * libproto/imap/status.c: Likewise.
    * libproto/imap/response.c: Set human-readable text as errstr.
    * libproto/imap/resproc.c (ok_response): Reflect changes to
    mu_imapio_getline.

commit 54eb06740c906c696749cd04c9afa6c43694f647
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 17:09:45 2011 +0200

    imapio: improve getline parser
    
    * libmailutils/imapio/create.c (mu_imapio_create): Treat [ and ] as
    delimiters.
    Use MU_WRDSF_DQUOTE flag instead of MU_WRDSF_QUOTE.
    Use MU_WRDSF_APPEND
    * libmailutils/imapio/getline.c (mu_imapio_getline): Use incremental
    wordsplit mode.  Return human-readable part of status responses as a
    single token.

commit 0e8d5bfe95e90df34616f780c9e11c076ca306c3
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 16:58:47 2011 +0200

    wordsplit: minor fix in return_delims mode
    
    * libmailutils/string/wordsplit.c (scan_word): Return only one delimiter
    if MU_WRDSF_RETURN_DELIMS is on
    * libmailutils/tests/wordsplit.at: Reflect that.

commit 9316bc63c12f6caa0303bb0c89a5831a90e523b4
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 15:15:40 2011 +0200

    wordsplit: add incremental mode.
    
    * include/mailutils/wordsplit.h (MU_WRDSF_INCREMENTAL): New flag.
    (MU_WRDSE_NOINPUT): New error code.
    * libmailutils/string/wordsplit.c (mu_wordsplit_init0): New function.
    (mu_wordsplit_init): Call mu_wordsplit_init0.
    (expvar): Use MU_WRDSF_WS instead of MU_WRDSF_SQUEEZE_DELIMS in
    call to subordinate mu_wordsplit.
    (skip_delim): If both MU_WRDSF_RETURN_DELIMS and MU_WRDSF_SQUEEZE_DELIMS
    are given, squeeze only the same delimiter characters.
    * libmailutils/tests/wordsplit.at: Add tests for incremental mode.
    * libmailutils/tests/wsp.c: Support incremental mode.

commit 45ecec0da61992ea2add464da3be67078b8dbe0e
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Nov 23 14:10:54 2011 +0200

    tls: do not generate DH params.
    
    * libmu_auth/tls.c: Don't generate DH params at all.

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

Summary of changes:
 include/mailutils/imap.h              |   19 +++-
 include/mailutils/imapio.h            |    2 +-
 include/mailutils/list.h              |    5 +
 include/mailutils/sys/imap.h          |    4 +-
 include/mailutils/wordsplit.h         |    6 +-
 libmailutils/imapio/create.c          |    7 +-
 libmailutils/imapio/getline.c         |  120 +++++++++++++++++-
 libmailutils/imapio/replstr.c         |    3 +-
 libmailutils/list/Makefile.am         |    4 +-
 libmailutils/list/{count.c => head.c} |   11 +-
 libmailutils/list/{count.c => tail.c} |   11 +-
 libmailutils/string/wordsplit.c       |  179 +++++++++++++++++++--------
 libmailutils/tests/list.at            |   12 ++
 libmailutils/tests/listop.c           |   42 ++++++
 libmailutils/tests/wordsplit.at       |   63 ++++++++-
 libmailutils/tests/wsp.c              |   36 +++++-
 libmu_auth/tls.c                      |   10 --
 libproto/imap/callback.c              |   10 +-
 libproto/imap/connect.c               |   45 ++++---
 libproto/imap/err.c                   |    6 +
 libproto/imap/id.c                    |    6 -
 libproto/imap/login.c                 |    6 -
 libproto/imap/response.c              |   33 +++---
 libproto/imap/resproc.c               |  223 ++++++++++++++++++++++-----------
 libproto/imap/select.c                |    6 -
 libproto/imap/status.c                |    6 -
 mu/imap.c                             |   33 ++++--
 27 files changed, 661 insertions(+), 247 deletions(-)
 copy libmailutils/list/{count.c => head.c} (82%)
 copy libmailutils/list/{count.c => tail.c} (82%)

diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index e33ff08..01faba0 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -108,19 +108,30 @@ int mu_imap_foreach_response (mu_imap_t imap, 
mu_imap_response_action_t fun,
                              void *data);
   
 
+  /* The following five callbacks correspond to members of struct
+     mu_imap_stat and take a pointer to struct mu_imap_stat as their
+     only argument. */
 #define MU_IMAP_CB_PERMANENT_FLAGS  0
 #define MU_IMAP_CB_MESSAGE_COUNT    1
 #define MU_IMAP_CB_RECENT_COUNT     2
 #define MU_IMAP_CB_FIRST_UNSEEN     3
 #define MU_IMAP_CB_UIDNEXT          4 
 #define MU_IMAP_CB_UIDVALIDITY      5
+
+  /* The following callbacks correspond to server responses and take two
+     argument: a response code (see MU_IMAP_RESPONSE, below), and
+     human-readable text string as returned by the server.  The latter can
+     be NULL. */
 #define MU_IMAP_CB_OK               6
-#define _MU_IMAP_CB_MAX             7
+#define MU_IMAP_CB_NO               7
+#define MU_IMAP_CB_BAD              8
+#define MU_IMAP_CB_BYE              9
+#define MU_IMAP_CB_PREAUTH         10
+#define _MU_IMAP_CB_MAX            11
 
-typedef void (*mu_imap_callback_t) (void *, int code, mu_list_t resp,
-                                   va_list ap);
+typedef void (*mu_imap_callback_t) (void *, int code, va_list ap);
   
-void mu_imap_callback (mu_imap_t imap, int code, mu_list_t resp, ...);
+void mu_imap_callback (mu_imap_t imap, int code, ...);
 
 void mu_imap_register_callback_function (mu_imap_t imap, int code,
                                         mu_imap_callback_t callback,
diff --git a/include/mailutils/imapio.h b/include/mailutils/imapio.h
index f5ebb70..5f60545 100644
--- a/include/mailutils/imapio.h
+++ b/include/mailutils/imapio.h
@@ -48,7 +48,7 @@ int mu_imapio_reply_string (struct _mu_imapio *io, size_t 
start, char **pbuf);
 
 int mu_imap_flag_to_attribute (const char *item, int *attr);
 int mu_imap_format_flags (mu_stream_t str, int flags);
-  
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mailutils/list.h b/include/mailutils/list.h
index e695bb7..6d88819 100644
--- a/include/mailutils/list.h
+++ b/include/mailutils/list.h
@@ -86,6 +86,11 @@ int mu_list_count    (mu_list_t _list, size_t *_pcount);
   
   /* Get _indexth element from the list and store it in _pitem. */
 int mu_list_get      (mu_list_t _list, size_t _index, void **_pitem);
+  /* Retrieve first element of _list */
+int mu_list_head (mu_list_t _list, void **_pitem);
+  /* Retrieve last element of _list */
+int mu_list_tail (mu_list_t _list, void **_pitem);
+  
   /* Store at most _count first elements from _list in the _array.  Unless
      _pcount is NULL, fill it with the actual number of elements copied. */
 int mu_list_to_array (mu_list_t _list, void **_array, size_t _count,
diff --git a/include/mailutils/sys/imap.h b/include/mailutils/sys/imap.h
index de3d1bf..c7c9a35 100644
--- a/include/mailutils/sys/imap.h
+++ b/include/mailutils/sys/imap.h
@@ -45,7 +45,8 @@ enum mu_imap_client_state
     MU_IMAP_LOGOUT_RX,
     MU_IMAP_ID_RX,
     MU_IMAP_SELECT_RX,
-    MU_IMAP_STATUS_RX
+    MU_IMAP_STATUS_RX,
+    MU_IMAP_CLOSING
   };
 
 enum mu_imap_response
@@ -155,6 +156,7 @@ int _mu_imap_xscript_level (mu_imap_t imap, int xlev);
   while (0)
 
 int _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len);
+int _mu_imap_seterrstrz (mu_imap_t imap, const char *str);
 void _mu_imap_clrerrstr (mu_imap_t imap);
 
 int _mu_imap_tag_next (mu_imap_t imap);
diff --git a/include/mailutils/wordsplit.h b/include/mailutils/wordsplit.h
index 5129121..2538da6 100644
--- a/include/mailutils/wordsplit.h
+++ b/include/mailutils/wordsplit.h
@@ -46,7 +46,7 @@ struct mu_wordsplit
   struct mu_wordsplit_node *ws_head, *ws_tail;
 };
 
-/* Wordsplit flags.  Only 3 bits of a 32-bit word remain unused.
+/* Wordsplit flags.  Only 2 bits of a 32-bit word remain unused.
    It is getting crowded... */
 /* Append the words found to the array resulting from a previous
    call. */
@@ -120,6 +120,9 @@ struct mu_wordsplit
 /* ws_escape is set */
 #define MU_WRDSF_ESCAPE            0x10000000
 
+/* Incremental mode */
+#define MU_WRDSF_INCREMENTAL       0x20000000
+
 #define MU_WRDSF_DEFFLAGS             \
   (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \
    MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES)
@@ -131,6 +134,7 @@ struct mu_wordsplit
 #define MU_WRDSE_USAGE      4
 #define MU_WRDSE_CBRACE     5
 #define MU_WRDSE_UNDEF      6
+#define MU_WRDSE_NOINPUT    7
 
 int mu_wordsplit (const char *s, struct mu_wordsplit *p, int flags);
 int mu_wordsplit_len (const char *s, size_t len,
diff --git a/libmailutils/imapio/create.c b/libmailutils/imapio/create.c
index 4a3a9af..a28e742 100644
--- a/libmailutils/imapio/create.c
+++ b/libmailutils/imapio/create.c
@@ -28,15 +28,16 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str)
     return ENOMEM;
   io->_imap_stream = str;
   mu_stream_ref (str);
-  io->_imap_ws.ws_delim = " \t()";
+  io->_imap_ws.ws_delim = " \t()[]";
   io->_imap_ws.ws_escape = "\\\"";
   io->_imap_ws_flags = MU_WRDSF_DELIM |
                        MU_WRDSF_ESCAPE |
                        MU_WRDSF_NOVAR |
                        MU_WRDSF_NOCMD | 
-                       MU_WRDSF_QUOTE |
+                       MU_WRDSF_DQUOTE |
                        MU_WRDSF_RETURN_DELIMS |
-                       MU_WRDSF_WS;
+                       MU_WRDSF_WS |
+                       MU_WRDSF_APPEND;
   *iop = io;
   return 0;
 }
diff --git a/libmailutils/imapio/getline.c b/libmailutils/imapio/getline.c
index f586d86..e54e5d6 100644
--- a/libmailutils/imapio/getline.c
+++ b/libmailutils/imapio/getline.c
@@ -23,16 +23,86 @@
 #include <mailutils/cstr.h>
 #include <mailutils/cctype.h>
 #include <mailutils/errno.h>
+#include <mailutils/kwd.h>
 #include <mailutils/sys/imapio.h>
 
+#define STATUS_RESPONSE           1
+#define STATUS_RESPONSE_UNTAGGED  2
+
+static int
+is_status_response (const char *word)
+{
+  static struct mu_kwd resptab[] = {
+    /* RFC 3501, 7.1:
+
+       Status responses are OK, NO, BAD, PREAUTH and BYE.  OK, NO, and BAD
+       can be tagged or untagged.  PREAUTH and BYE are always untagged.
+    */
+    { "OK", STATUS_RESPONSE },
+    { "NO", STATUS_RESPONSE },
+    { "BAD", STATUS_RESPONSE },
+    { "PREAUTH", STATUS_RESPONSE_UNTAGGED },
+    { "BYE", STATUS_RESPONSE_UNTAGGED },
+    { NULL }
+  };
+  int result;
+  
+  if (mu_kwd_xlat_name (resptab, word, &result))
+    return 0;
+  return result;
+}
+
+static int
+get_response_code (struct _mu_imapio *io)
+{
+  size_t end = io->_imap_ws.ws_endp;
+  size_t wc = io->_imap_ws.ws_wordc;
+  int rc, i;
+  
+  do
+    {
+      if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL)))
+       {
+         if (rc == MU_WRDSE_NOINPUT)
+           break;
+         return MU_ERR_PARSE;
+       }
+
+      if (strcmp (io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc-1], "[") == 0)
+       {
+         do
+           {
+             /* Get word */
+             if ((rc = mu_wordsplit (NULL, &io->_imap_ws, 
MU_WRDSF_INCREMENTAL)))
+               {
+                 if (rc == MU_WRDSE_NOINPUT)
+                   break;
+                 return MU_ERR_PARSE;
+               }
+           }
+         while (strcmp (io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc-1], "]"));
+         if (rc)
+           break;
+         return 0;
+       }
+    }
+  while (0);
+
+  for (i = wc; i < io->_imap_ws.ws_wordc; i++)
+    free (io->_imap_ws.ws_wordv[i]);
+  io->_imap_ws.ws_wordv[wc] = NULL;
+  io->_imap_ws.ws_wordc = wc;
+  io->_imap_ws.ws_endp = end;
+  return 0;
+}
+
 int
 mu_imapio_getline (struct _mu_imapio *io)
 {
   int rc;
   char *last_arg;
+  int type;
   
-  io->_imap_ws_flags &= ~MU_WRDSF_APPEND;
-
   if (io->_imap_reply_ready)
     {
       mu_wordsplit_free_words (&io->_imap_ws);
@@ -50,11 +120,51 @@ mu_imapio_getline (struct _mu_imapio *io)
        break;
       io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base,
                                            MU_CTYPE_ENDLN);
+      if ((rc = mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level,
+                                 &io->_imap_ws,
+                                 io->_imap_ws_flags | MU_WRDSF_INCREMENTAL)))
+       {
+         if (rc == MU_WRDSE_NOINPUT)
+           break;
+         return MU_ERR_PARSE;
+       }
+      io->_imap_ws_flags |= MU_WRDSF_REUSE;
+
+      if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL)))
+       {
+         if (rc == MU_WRDSE_NOINPUT)
+           break;
+         return MU_ERR_PARSE;
+       }
+      
+      if ((type = is_status_response (io->_imap_ws.ws_wordv[1]))
+         && (type == STATUS_RESPONSE ||
+             strcmp (io->_imap_ws.ws_wordv[0], "*") == 0))
+       {
+         rc = get_response_code (io);
+         if (rc)
+           return MU_ERR_PARSE;
+         while (io->_imap_ws.ws_endp < io->_imap_ws.ws_len &&
+                mu_isblank (io->_imap_ws.ws_input[io->_imap_ws.ws_endp]))
+           io->_imap_ws.ws_endp++;
+         io->_imap_ws.ws_flags |= MU_WRDSF_NOSPLIT;
+         rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL);
+         io->_imap_ws.ws_flags &= ~MU_WRDSF_NOSPLIT;
+         if (rc)
+           {
+             if (rc == MU_WRDSE_NOINPUT)
+               break;
+             return MU_ERR_PARSE;
+           }
+         break;
+       }
 
-      if (mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level,
-                           &io->_imap_ws, io->_imap_ws_flags))
+      
+      rc = mu_wordsplit_len (io->_imap_buf_base + io->_imap_ws.ws_endp,
+                            io->_imap_buf_level - io->_imap_ws.ws_endp,
+                            &io->_imap_ws, io->_imap_ws_flags);
+      if (rc)
        return MU_ERR_PARSE;
-      io->_imap_ws_flags |= MU_WRDSF_REUSE|MU_WRDSF_APPEND;
 
       last_arg = io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc - 1];
       if (last_arg[0] == '{' && last_arg[strlen (last_arg)-1] == '}')
diff --git a/libmailutils/imapio/replstr.c b/libmailutils/imapio/replstr.c
index 56b3fa2..ed183f3 100644
--- a/libmailutils/imapio/replstr.c
+++ b/libmailutils/imapio/replstr.c
@@ -21,7 +21,8 @@
 #include <mailutils/argcv.h>
 #include <mailutils/sys/imapio.h>
 
-/* FIXME: It would be good to have a `, size_t *psize' argument, to allow
+/* FIXME: 1. Is it needed at all?
+   2. It would be good to have a `, size_t *psize' argument, to allow
    for passing an already allocated buffer.  This implies similar changes
    to mu_argcv_join. */
 int
diff --git a/libmailutils/list/Makefile.am b/libmailutils/list/Makefile.am
index 6d46fde..ee6913c 100644
--- a/libmailutils/list/Makefile.am
+++ b/libmailutils/list/Makefile.am
@@ -29,6 +29,7 @@ liblist_la_SOURCES = \
  get.c\
  getcomp.c\
  gmap.c\
+ head.c\
  insert.c\
  intersect.c\
  iterator.c\
@@ -41,7 +42,8 @@ liblist_la_SOURCES = \
  setcomp.c\
  setdestr.c\
  slice.c\
- slice2.c
+ slice2.c\
+ tail.c
 
 INCLUDES = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
 
diff --git a/libmailutils/list/count.c b/libmailutils/list/head.c
similarity index 82%
copy from libmailutils/list/count.c
copy to libmailutils/list/head.c
index 981dbcc..7c52b89 100644
--- a/libmailutils/list/count.c
+++ b/libmailutils/list/head.c
@@ -1,6 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2011 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
@@ -24,12 +23,14 @@
 #include <mailutils/errno.h>
 
 int
-mu_list_count (mu_list_t list, size_t *pcount)
+mu_list_head (mu_list_t list, void **pitem)
 {
   if (list == NULL)
     return EINVAL;
-  if (pcount == NULL)
+  if (pitem == NULL)
     return MU_ERR_OUT_PTR_NULL;
-  *pcount = list->count;
+  if (!list->head.next)
+    return MU_ERR_NOENT;
+  *pitem = list->head.next->item;
   return 0;
 }
diff --git a/libmailutils/list/count.c b/libmailutils/list/tail.c
similarity index 82%
copy from libmailutils/list/count.c
copy to libmailutils/list/tail.c
index 981dbcc..a8d1472 100644
--- a/libmailutils/list/count.c
+++ b/libmailutils/list/tail.c
@@ -1,6 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2011 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
@@ -24,12 +23,14 @@
 #include <mailutils/errno.h>
 
 int
-mu_list_count (mu_list_t list, size_t *pcount)
+mu_list_tail (mu_list_t list, void **pitem)
 {
   if (list == NULL)
     return EINVAL;
-  if (pcount == NULL)
+  if (pitem == NULL)
     return MU_ERR_OUT_PTR_NULL;
-  *pcount = list->count;
+  if (!list->head.prev)
+    return MU_ERR_NOENT;
+  *pitem = list->head.prev->item;
   return 0;
 }
diff --git a/libmailutils/string/wordsplit.c b/libmailutils/string/wordsplit.c
index a15b975..12af725 100644
--- a/libmailutils/string/wordsplit.c
+++ b/libmailutils/string/wordsplit.c
@@ -85,6 +85,25 @@ _wsplt_nomem (struct mu_wordsplit *wsp)
   return wsp->ws_errno;
 }
 
+static void
+mu_wordsplit_init0 (struct mu_wordsplit *wsp)
+{
+  if (wsp->ws_flags & MU_WRDSF_REUSE)
+    {
+      if (!(wsp->ws_flags & MU_WRDSF_APPEND))
+       mu_wordsplit_free_words (wsp);
+    }
+  else
+    {
+      wsp->ws_wordv = NULL;
+      wsp->ws_wordc = 0;
+      wsp->ws_wordn = 0;
+    }
+
+  wsp->ws_errno = 0;
+  wsp->ws_head = wsp->ws_tail = NULL;
+}  
+
 static int
 mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len,
                   int flags)
@@ -140,24 +159,13 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char 
*input, size_t len,
   if (!(wsp->ws_flags & MU_WRDSF_COMMENT))
     wsp->ws_comment = NULL;
 
-  if (wsp->ws_flags & MU_WRDSF_REUSE)
-    {
-      if (!(wsp->ws_flags & MU_WRDSF_APPEND))
-       mu_wordsplit_free_words (wsp);
-    }
-  else
-    {
-      wsp->ws_wordv = NULL;
-      wsp->ws_wordc = 0;
-      wsp->ws_wordn = 0;
-    }
-
   if (!(wsp->ws_flags & MU_WRDSF_CLOSURE))
     wsp->ws_closure = NULL;
-  
+
   wsp->ws_endp = 0;
-  wsp->ws_errno = 0;
-  wsp->ws_head = wsp->ws_tail = NULL;
+  
+  mu_wordsplit_init0 (wsp);
+
   return 0;
 }
 
@@ -815,7 +823,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t 
len,
          ws.ws_delim = wsp->ws_delim;
          if (mu_wordsplit (value, &ws,
                            MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
-                           MU_WRDSF_DELIM | MU_WRDSF_SQUEEZE_DELIMS))
+                           MU_WRDSF_DELIM | MU_WRDSF_WS))
            {
              mu_wordsplit_free (&ws);
              return 1;
@@ -1017,10 +1025,20 @@ skip_delim (struct mu_wordsplit *wsp)
   size_t start = wsp->ws_endp;
   if (wsp->ws_flags & MU_WRDSF_SQUEEZE_DELIMS)
     {
-      do
-       start++;
-      while (start < wsp->ws_len
-            && ISDELIM (wsp, wsp->ws_input[start]));
+      if ((wsp->ws_flags & MU_WRDSF_RETURN_DELIMS) &&
+         ISDELIM (wsp, wsp->ws_input[start]))
+       {
+         int delim = wsp->ws_input[start];
+         do
+           start++;
+         while (start < wsp->ws_len && delim == wsp->ws_input[start]);
+       }
+      else
+       {
+         do
+           start++;
+         while (start < wsp->ws_len && ISDELIM (wsp, wsp->ws_input[start]));
+       }
       start--;
     }
 
@@ -1030,9 +1048,9 @@ skip_delim (struct mu_wordsplit *wsp)
   return start;
 }
 
-#define _MU_WRDS_EOF  0
-#define _MU_WRDS_OK   1
-#define _MU_WRDS_ERR  2
+#define _MU_WRDS_EOF   0
+#define _MU_WRDS_OK    1
+#define _MU_WRDS_ERR   2
 
 static int
 scan_qstring (struct mu_wordsplit *wsp, size_t start, size_t * end)
@@ -1137,11 +1155,7 @@ scan_word (struct mu_wordsplit *wsp, size_t start)
     }
   else if (wsp->ws_flags & MU_WRDSF_RETURN_DELIMS)
     {
-      do
-       {
-         i++;
-       }
-      while (i < len && ISDELIM (wsp, command[i]));
+      i++;
     }
   else if (!(wsp->ws_flags & MU_WRDSF_SQUEEZE_DELIMS))
     flags |= _WSNF_EMPTYOK;
@@ -1151,7 +1165,8 @@ scan_word (struct mu_wordsplit *wsp, size_t start)
   if (mu_wordsplit_add_segm (wsp, start, i, flags))
     return _MU_WRDS_ERR;
   wsp->ws_endp = i;
-
+  if (wsp->ws_flags & MU_WRDSF_INCREMENTAL)
+    return _MU_WRDS_EOF;
   return _MU_WRDS_OK;
 }
 
@@ -1366,33 +1381,26 @@ mu_wordsplit_c_quote_copy (char *dst, const char *src, 
int quote_hex)
     }
 }
 
-int
-mu_wordsplit_len (const char *command, size_t len, struct mu_wordsplit *wsp,
-                 int flags)
+static int
+wordsplit_process_list (struct mu_wordsplit *wsp, size_t start)
 {
-  int rc;
-  size_t start = 0;
-
-  rc = mu_wordsplit_init (wsp, command, len, flags);
-  if (rc)
-    return rc;
-
-  if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
-    wsp->ws_debug ("Input:%.*s;", (int)len, command);
-
   if (wsp->ws_flags & MU_WRDSF_NOSPLIT)
     {
       /* Treat entire input as a quoted argument */
-      if (mu_wordsplit_add_segm (wsp, 0, len, _WSNF_QUOTE))
+      if (mu_wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE))
        return wsp->ws_errno;
     }
   else
     {
+      int rc;
+  
       while ((rc = scan_word (wsp, start)) == _MU_WRDS_OK)
        start = skip_delim (wsp);
       /* Make sure tail element is not joinable */
       if (wsp->ws_tail)
        wsp->ws_tail->flags &= ~_WSNF_JOIN;
+      if (rc == _MU_WRDS_ERR)
+       return wsp->ws_errno;
     }
 
   if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
@@ -1400,11 +1408,6 @@ mu_wordsplit_len (const char *command, size_t len, 
struct mu_wordsplit *wsp,
       wsp->ws_debug ("Initial list:");
       mu_wordsplit_dump_nodes (wsp);
     }
-  if (rc)
-    {
-      mu_wordsplit_free_nodes (wsp);
-      return wsp->ws_errno;
-    }
 
   if (wsp->ws_flags & MU_WRDSF_WS)
     {
@@ -1450,10 +1453,75 @@ mu_wordsplit_len (const char *command, size_t len, 
struct mu_wordsplit *wsp,
          wsp->ws_debug ("Coalesced list:");
          mu_wordsplit_dump_nodes (wsp);
        }
-
-      mu_wordsplit_finish (wsp);
     }
   while (0);
+  return wsp->ws_errno;
+}  
+
+int
+mu_wordsplit_len (const char *command, size_t length, struct mu_wordsplit *wsp,
+                 int flags)
+{
+  int rc;
+  size_t start;
+  const char *cmdptr;
+  size_t cmdlen;
+
+  if (!command)
+    {
+      if (!(flags & MU_WRDSF_INCREMENTAL))
+       return EINVAL;
+
+      start = skip_delim (wsp);
+      if (wsp->ws_endp == wsp->ws_len)
+       {
+         wsp->ws_errno = MU_WRDSE_NOINPUT;
+         if (wsp->ws_flags & MU_WRDSF_SHOWERR)
+           mu_wordsplit_perror (wsp);
+         return wsp->ws_errno;
+       }
+      
+      cmdptr = wsp->ws_input + wsp->ws_endp;
+      cmdlen = wsp->ws_len - wsp->ws_endp;
+      wsp->ws_flags |= MU_WRDSF_REUSE;
+      mu_wordsplit_init0 (wsp);
+    }
+  else
+    {
+      cmdptr = command;
+      cmdlen = length;
+      start = 0;
+      rc = mu_wordsplit_init (wsp, cmdptr, cmdlen, flags);
+      if (rc)
+       return rc;
+    }
+
+  if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
+    wsp->ws_debug ("Input:%.*s;", (int)cmdlen, cmdptr);
+
+  rc = wordsplit_process_list (wsp, start);
+  if (rc == 0 && (flags & MU_WRDSF_INCREMENTAL))
+    {
+      while (!wsp->ws_head && wsp->ws_endp < wsp->ws_len)
+       {
+         start = skip_delim (wsp);
+         if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
+           {
+             cmdptr = wsp->ws_input + wsp->ws_endp;
+             cmdlen = wsp->ws_len - wsp->ws_endp;
+             wsp->ws_debug ("Restart:%.*s;", (int)cmdlen, cmdptr);
+           }
+         rc = wordsplit_process_list (wsp, start);
+         if (rc)
+           break;
+       }
+    }
+  if (rc)
+    {
+      mu_wordsplit_free_nodes (wsp);
+      return rc;
+    }
+  mu_wordsplit_finish (wsp);
   mu_wordsplit_free_nodes (wsp);
   return wsp->ws_errno;
 }
@@ -1461,7 +1529,7 @@ mu_wordsplit_len (const char *command, size_t len, struct 
mu_wordsplit *wsp,
 int
 mu_wordsplit (const char *command, struct mu_wordsplit *ws, int flags)
 {
-  return mu_wordsplit_len (command, strlen (command), ws, flags);
+  return mu_wordsplit_len (command, command ? strlen (command) : 0, ws, flags);
 }
 
 void
@@ -1523,6 +1591,10 @@ mu_wordsplit_perror (struct mu_wordsplit *wsp)
       wsp->ws_error (_("undefined variable"));
       break;
 
+    case MU_WRDSE_NOINPUT:
+      wsp->ws_error (_("input exhausted"));
+      break;
+      
     default:
       wsp->ws_error (_("unknown error"));
     }
@@ -1532,10 +1604,11 @@ const char *_mu_wordsplit_errstr[] = {
   N_("no error"),
   N_("missing closing quote"),
   N_("memory exhausted"),
-  N_("variable expansion and command substitution " "are not yet supported"),
+  N_("command substitution is not yet supported"),
   N_("invalid mu_wordsplit usage"),
   N_("unbalanced curly brace"),
-  N_("undefined variable")
+  N_("undefined variable"),
+  N_("input exhausted")
 };
 int _mu_wordsplit_nerrs =
   sizeof (_mu_wordsplit_errstr) / sizeof (_mu_wordsplit_errstr[0]);
diff --git a/libmailutils/tests/list.at b/libmailutils/tests/list.at
index c2a39cc..408e78e 100644
--- a/libmailutils/tests/list.at
+++ b/libmailutils/tests/list.at
@@ -103,6 +103,18 @@ TESTLIST([get],[],
 [fire
 ])
 
+TESTLIST([head],[],
+[add en to tre fire fem
+head],
+[en
+])
+
+TESTLIST([tail],[],
+[add en to tre fire fem
+tail],
+[fem
+])
+
 
 # ------------------------------------------------------------
 # Iterators
diff --git a/libmailutils/tests/listop.c b/libmailutils/tests/listop.c
index a71de9e..68e59e4 100644
--- a/libmailutils/tests/listop.c
+++ b/libmailutils/tests/listop.c
@@ -685,6 +685,42 @@ slice (mu_list_t *plist, int argc, char **argv)
 }
 
 void
+head (size_t argc, mu_list_t list)
+{
+  int rc;
+  const char *text;
+    
+  if (argc != 1)
+    {
+      fprintf (stderr, "head ?\n");
+      return;
+    }
+  rc = mu_list_head (list, (void**) &text);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_list_head", NULL, rc);
+  else
+    printf ("%s\n", text);
+}
+
+void
+tail (size_t argc, mu_list_t list)
+{
+  int rc;
+  const char *text;
+    
+  if (argc != 1)
+    {
+      fprintf (stderr, "head ?\n");
+      return;
+    }
+  rc = mu_list_tail (list, (void**) &text);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_list_tail", NULL, rc);
+  else
+    printf ("%s\n", text);
+}
+
+void
 help ()
 {
   printf ("count\n");
@@ -708,6 +744,8 @@ help ()
   printf ("quit\n");
   printf ("iter num\n");
   printf ("help\n");
+  printf ("head\n");
+  printf ("tail\n");
   printf ("NUMBER\n");
 }
 
@@ -819,6 +857,10 @@ shell (mu_list_t list)
            find (itr[num], ws.ws_wordv[1]);
          else if (strcmp (ws.ws_wordv[0], "help") == 0)
            help ();
+         else if (strcmp (ws.ws_wordv[0], "head") == 0)
+           head (ws.ws_wordc, list);
+         else if (strcmp (ws.ws_wordv[0], "tail") == 0)
+           tail (ws.ws_wordc, list);
          else if (ws.ws_wordc == 1)
            {
              char *p;
diff --git a/libmailutils/tests/wordsplit.at b/libmailutils/tests/wordsplit.at
index ca43789..69c26f1 100644
--- a/libmailutils/tests/wordsplit.at
+++ b/libmailutils/tests/wordsplit.at
@@ -275,16 +275,17 @@ TESTWSP([custom, with returned delimiters],[],[delim : 
-ws trimnl return_delims]
 
 TESTWSP([custom, with returned & squeezed delimiters],[],[delim : -ws trimnl 
return_delims -squeeze_delims],
 [semicolon: separated::list: of :words],
-[NF: 9
+[NF: 10
 0: semicolon
 1: :
 2: " separated"
-3: ::
-4: list
-5: :
-6: " of "
-7: :
-8: words
+3: :
+4: :
+5: list
+6: :
+7: " of "
+8: :
+9: words
 ])
 
 TESTWSP([sed expressions],[],[sed],
@@ -373,4 +374,52 @@ TESTWSP([squote],[],[-default novar nocmd squote],
 3: it
 ])
 
+TESTWSP([incremental],[],[incremental],
+[incremental "input test" line
+
+
+],
+[NF: 1
+0: incremental
+NF: 1
+0: "input test"
+NF: 1
+0: line
+],
+[input exhausted
+])
+
+TESTWSP([incremental append],[],[incremental append],
+[incremental "input test" line
+
+
+],
+[NF: 1
+0: incremental
+NF: 2
+0: incremental
+1: "input test"
+NF: 3
+0: incremental
+1: "input test"
+2: line
+],
+[input exhausted
+])
+
+TESTWSP([incremental ws],[],[return_delims -squeeze_delims incremental ws],
+[a   list  test
+
+
+],
+[NF: 1
+0: a
+NF: 1
+0: list
+NF: 1
+0: test
+],
+[input exhausted
+])
+
 m4_popdef([TESTWSP])
diff --git a/libmailutils/tests/wsp.c b/libmailutils/tests/wsp.c
index 5af17be..1dc85df 100644
--- a/libmailutils/tests/wsp.c
+++ b/libmailutils/tests/wsp.c
@@ -49,6 +49,7 @@ struct mu_kwd bool_keytab[] = {
   { "cescapes", MU_WRDSF_CESCAPES },
   { "default", MU_WRDSF_DEFFLAGS },
   { "env_kv", MU_WRDSF_ENV_KV },
+  { "incremental", MU_WRDSF_INCREMENTAL },
   { NULL, 0 }
 };
 
@@ -164,7 +165,7 @@ make_env_kv ()
 int
 main (int argc, char **argv)
 {
-  char buf[1024];
+  char buf[1024], *ptr;
   int i, offarg = 0;
   int trimnl_option = 0;
   int plaintext_option = 0;
@@ -172,6 +173,7 @@ main (int argc, char **argv)
                  MU_WRDSF_ENOMEMABRT |
                  MU_WRDSF_ENV | MU_WRDSF_SHOWERR;
   struct mu_wordsplit ws;
+  int next_call = 0;
 
   for (i = 1; i < argc; i++)
     {
@@ -296,15 +298,39 @@ main (int argc, char **argv)
     ws.ws_env = (const char **) make_env_kv ();
   else
     ws.ws_env = (const char **) environ;
-       
-  while (fgets (buf, sizeof (buf), stdin))
+
+  if (wsflags & MU_WRDSF_INCREMENTAL)
+    trimnl_option = 1;
+  
+  next_call = 0;
+  while ((ptr = fgets (buf, sizeof (buf), stdin)))
     {
       int rc;
       size_t i;
       
       if (trimnl_option)
-       mu_rtrim_cset (buf, "\n");
-      rc = mu_wordsplit (buf, &ws, wsflags);
+       mu_rtrim_cset (ptr, "\n");
+      
+      if (wsflags & MU_WRDSF_INCREMENTAL)
+       {
+         if (next_call)
+           {
+             if (*ptr == 0)
+               ptr = NULL;
+             else
+               free ((void*)ws.ws_input);
+           }
+         else
+           next_call = 1;
+         if (ptr)
+           {
+             ptr = strdup (ptr);
+             if (!ptr)
+               abort ();
+           }
+       }
+       
+      rc = mu_wordsplit (ptr, &ws, wsflags);
       if (rc)
        {
          if (!(wsflags & MU_WRDSF_SHOWERR))
diff --git a/libmu_auth/tls.c b/libmu_auth/tls.c
index ef8df93..655730c 100644
--- a/libmu_auth/tls.c
+++ b/libmu_auth/tls.c
@@ -67,9 +67,6 @@ mu_tls_module_init (enum mu_gocs_op op, void *data)
 #include <gnutls/gnutls.h>
 #include <mailutils/sys/tls-stream.h>
 
-#define DH_BITS 768
-
-static gnutls_dh_params dh_params;
 static gnutls_certificate_server_credentials x509_cred;
 
 /* Return: zero means NOT READY, one means READY */
@@ -145,7 +142,6 @@ mu_init_tls_libs (int x509_setup)
 
   if (x509_setup && !x509_cred)
     {
-      mu_diag_output (MU_DIAG_INFO, _("initializing X509..."));
       gnutls_certificate_allocate_credentials (&x509_cred);
       if (mu_tls_module_config.ssl_cafile)
        gnutls_certificate_set_x509_trust_file (x509_cred,
@@ -156,11 +152,6 @@ mu_init_tls_libs (int x509_setup)
                                            mu_tls_module_config.ssl_cert, 
                                            mu_tls_module_config.ssl_key,
                                            GNUTLS_X509_FMT_PEM);
-      
-      gnutls_dh_params_init (&dh_params);
-      gnutls_dh_params_generate2 (dh_params, DH_BITS);
-      gnutls_certificate_set_dh_params (x509_cred, dh_params);
-      mu_diag_output (MU_DIAG_INFO, _("finished initializing X509"));
     }
   
 #ifdef DEBUG_TLS
@@ -191,7 +182,6 @@ initialize_tls_session (void)
   gnutls_set_default_priority (session);
   gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
   gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
-  gnutls_dh_set_prime_bits (session, DH_BITS);
 
   return session;
 }
diff --git a/libproto/imap/callback.c b/libproto/imap/callback.c
index 63df696..7fbc998 100644
--- a/libproto/imap/callback.c
+++ b/libproto/imap/callback.c
@@ -23,15 +23,15 @@
 #include <mailutils/sys/imap.h>
 
 void
-mu_imap_callback (mu_imap_t imap, int code, mu_list_t resp, ...)
+mu_imap_callback (mu_imap_t imap, int code, ...)
 {
   va_list ap;
   
-  if (code < 0 || code > _MU_IMAP_CB_MAX || !imap->callback[code].action)
+  if (code < 0 || code >= _MU_IMAP_CB_MAX || !imap->callback[code].action)
     return;
   
-  va_start (ap, resp);
-  imap->callback[code].action (imap->callback[code].data, code, resp, ap);
+  va_start (ap, code);
+  imap->callback[code].action (imap->callback[code].data, code, ap);
   va_end (ap);
 }
 
@@ -40,7 +40,7 @@ mu_imap_register_callback_function (mu_imap_t imap, int code,
                                    mu_imap_callback_t callback,
                                    void *data)
 {
-  if (code < 0 || code > _MU_IMAP_CB_MAX)
+  if (code < 0 || code >= _MU_IMAP_CB_MAX)
     {
       mu_error ("%s:%d: ignoring unsupported callback code %d",
                __FILE__, __LINE__, code);
diff --git a/libproto/imap/connect.c b/libproto/imap/connect.c
index a925e84..552530b 100644
--- a/libproto/imap/connect.c
+++ b/libproto/imap/connect.c
@@ -37,11 +37,17 @@ mu_imap_connect (mu_imap_t imap)
   char **wv;
   char *bufptr;
   size_t bufsize;
-  
+
   if (imap == NULL)
     return EINVAL;
   if (imap->io == NULL)
     return EINVAL;
+
+  _mu_imap_clrerrstr (imap);
+  status = _mu_imap_untagged_response_clear (imap);
+  if (status)
+    return status;
+  
   switch (imap->state)
     {
     default:
@@ -79,29 +85,26 @@ mu_imap_connect (mu_imap_t imap)
          imap->state = MU_IMAP_ERROR;
          return MU_ERR_BADREPLY;
        }
-      else if (strcmp (wv[1], "BYE") == 0)
-       {
-         status = EACCES;
-         mu_imapio_getbuf (imap->io, &bufptr, &bufsize);
-         _mu_imap_seterrstr (imap, bufptr + 2, bufsize - 2);
-       }
-      else if (strcmp (wv[1], "PREAUTH") == 0)
-       {
-         status = 0;
-         imap->state = MU_IMAP_CONNECTED;
-         imap->imap_state = MU_IMAP_STATE_AUTH;
-       }
-      else if (strcmp (wv[1], "OK") == 0)
-       {
-         status = 0;
-         imap->state = MU_IMAP_CONNECTED;
-         imap->imap_state = MU_IMAP_STATE_NONAUTH;
-       }
       else
        {
-         status = MU_ERR_BADREPLY;
-         imap->state = MU_IMAP_ERROR;
+         _mu_imap_untagged_response_add (imap);
+         mu_imap_foreach_response (imap, NULL, NULL);
+         switch (imap->state)
+           {
+           case MU_IMAP_CONNECTED:
+             status = 0;
+             break;
+
+           case MU_IMAP_CLOSING:
+             status = EACCES;
+             break;
+
+           default:
+             imap->state = MU_IMAP_ERROR;
+             status = MU_ERR_BADREPLY;
+           }
        }
+      break;
     }
   
   return status;
diff --git a/libproto/imap/err.c b/libproto/imap/err.c
index 29e275d..0145b7e 100644
--- a/libproto/imap/err.c
+++ b/libproto/imap/err.c
@@ -41,6 +41,12 @@ _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t 
len)
   return 0;
 }
 
+int
+_mu_imap_seterrstrz (mu_imap_t imap, const char *str)
+{
+  return _mu_imap_seterrstr (imap, str, strlen (str));
+}
+
 void
 _mu_imap_clrerrstr (mu_imap_t imap)
 {
diff --git a/libproto/imap/id.c b/libproto/imap/id.c
index bd5d447..527cd69 100644
--- a/libproto/imap/id.c
+++ b/libproto/imap/id.c
@@ -85,7 +85,6 @@ int
 mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc)
 {
   int status;
-  char *p;
   
   if (imap == NULL)
     return EINVAL;
@@ -147,11 +146,6 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t 
*passoc)
 
        case MU_IMAP_BAD:
          status = MU_ERR_BADREPLY;
-         if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-           {
-             _mu_imap_seterrstr (imap, p, strlen (p));
-             free (p);
-           }
          break;
        }
       imap->state = MU_IMAP_CONNECTED;
diff --git a/libproto/imap/login.c b/libproto/imap/login.c
index b1f840f..d4b05fd 100644
--- a/libproto/imap/login.c
+++ b/libproto/imap/login.c
@@ -28,7 +28,6 @@ int
 mu_imap_login (mu_imap_t imap, const char *user, const char *pass)
 {
   int status;
-  char *p;
   
   if (imap == NULL)
     return EINVAL;
@@ -69,11 +68,6 @@ mu_imap_login (mu_imap_t imap, const char *user, const char 
*pass)
 
        case MU_IMAP_BAD:
          status = MU_ERR_BADREPLY;
-         if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-           {
-             _mu_imap_seterrstr (imap, p, strlen (p));
-             free (p);
-           }
          break;
        }
       imap->state = MU_IMAP_CONNECTED;
diff --git a/libproto/imap/response.c b/libproto/imap/response.c
index 67087ad..0f959e2 100644
--- a/libproto/imap/response.c
+++ b/libproto/imap/response.c
@@ -27,6 +27,13 @@
 #include <mailutils/errno.h>
 #include <mailutils/sys/imap.h>
 
+static void
+response_to_errstr (mu_imap_t imap, size_t argc, char **argv)
+{
+  if (argc && strcmp (argv[argc-1], "]"))
+    _mu_imap_seterrstrz (imap, argv[argc-1]);
+}
+
 int
 _mu_imap_response (mu_imap_t imap)
 {
@@ -50,9 +57,15 @@ _mu_imap_response (mu_imap_t imap)
        {
          char **wv;
          size_t wc;
-         char *p;
          
          mu_imapio_get_words (imap->io, &wc, &wv);
+         if (wc == 0)
+           {
+             imap->state = MU_IMAP_ERROR;
+             status = MU_ERR_BADREPLY;/* FIXME: ECONNRESET ? */
+             break;
+           }
+           
          if (strcmp (wv[0], "*") == 0)
            {
              _mu_imap_untagged_response_add (imap);/* FIXME: error checking */
@@ -70,29 +83,17 @@ _mu_imap_response (mu_imap_t imap)
              else if (strcmp (wv[1], "OK") == 0)
                {
                  imap->resp_code = MU_IMAP_OK;
-                 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-                   {
-                     _mu_imap_seterrstr (imap, p, strlen (p));
-                     free (p);
-                   }
+                 response_to_errstr (imap, wc, wv);
                }
              else if (strcmp (wv[1], "NO") == 0)
                {
                  imap->resp_code = MU_IMAP_NO;
-                 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-                   {
-                     _mu_imap_seterrstr (imap, p, strlen (p));
-                     free (p);
-                   }
+                 response_to_errstr (imap, wc, wv);
                }
              else if (strcmp (wv[1], "BAD") == 0)
                {
                  imap->resp_code = MU_IMAP_BAD;
-                 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-                   {
-                     _mu_imap_seterrstr (imap, p, strlen (p));
-                     free (p);
-                   }
+                 response_to_errstr (imap, wc, wv);
                }
              else
                status = MU_ERR_BADREPLY;
diff --git a/libproto/imap/resproc.c b/libproto/imap/resproc.c
index af752b9..3097795 100644
--- a/libproto/imap/resproc.c
+++ b/libproto/imap/resproc.c
@@ -53,84 +53,157 @@ struct mu_kwd mu_imap_response_codes[] = {
   { NULL }
 };
 
-static void
-ok_response (mu_imap_t imap, mu_list_t resp, void *data)
+static int
+parse_response_code (mu_imap_t imap, mu_list_t resp)
 {
   struct imap_list_element *arg;
   int rcode = -1;
-  size_t n = 0;
-  
+
   arg = _mu_imap_list_at (resp, 1);
   if (!arg)
-    return;
-  if (arg->type == imap_eltype_string && arg->v.string[0] == '[')
+    return -1;
+  
+  if (_mu_imap_list_element_is_string (arg, "["))
     {
-      char *p;
+      arg = _mu_imap_list_at (resp, 2);
+      if (!arg || arg->type != imap_eltype_string)
+       return -1;
       
-      size_t len = strcspn (arg->v.string, "]");
+      if (mu_kwd_xlat_name (mu_imap_response_codes, arg->v.string, &rcode))
+       return -1;
       
-      if (mu_kwd_xlat_name_len (mu_imap_response_codes,
-                               arg->v.string + 1, len - 1, &rcode))
-       rcode = -1;
-      
-      switch (rcode)
-       {
-       case MU_IMAP_RESPONSE_PERMANENTFLAGS:
-         arg = _mu_imap_list_at (resp, 2);
-         if (!arg ||
-             _mu_imap_collect_flags (arg, &imap->mbox_stat.permanent_flags))
-           break;
-         imap->mbox_stat.flags |= MU_IMAP_STAT_PERMANENT_FLAGS;
-         mu_imap_callback (imap, MU_IMAP_CB_PERMANENT_FLAGS, resp,
-                           &imap->mbox_stat);
-         return;
+      arg = _mu_imap_list_at (resp, 4);
+      if (!arg || !_mu_imap_list_element_is_string (arg, "]"))
+       return -1;
+    }
+  return rcode;
+}
+  
+static void
+ok_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+  struct imap_list_element *arg;
+  int rcode;
+  size_t n = 0;
+  char *p;
+
+  rcode = parse_response_code (imap, resp);
+  switch (rcode)
+    {
+    case MU_IMAP_RESPONSE_PERMANENTFLAGS:
+      arg = _mu_imap_list_at (resp, 3);
+      if (!arg ||
+         _mu_imap_collect_flags (arg, &imap->mbox_stat.permanent_flags))
+       break;
+      imap->mbox_stat.flags |= MU_IMAP_STAT_PERMANENT_FLAGS;
+      mu_imap_callback (imap, MU_IMAP_CB_PERMANENT_FLAGS, &imap->mbox_stat);
+      return;
          
-       case MU_IMAP_RESPONSE_UIDNEXT:
-         arg = _mu_imap_list_at (resp, 2);
-         if (!arg || arg->type != imap_eltype_string)
-           break;
-         n = strtoul (arg->v.string, &p, 10);
-         if (*p == ']')
-           {
-             imap->mbox_stat.uidnext = n;
-             imap->mbox_stat.flags |= MU_IMAP_STAT_UIDNEXT;
-             mu_imap_callback (imap, MU_IMAP_CB_UIDNEXT, resp,
-                               &imap->mbox_stat);
-           }
-         return;
-                           
-       case MU_IMAP_RESPONSE_UIDVALIDITY:
-         arg = _mu_imap_list_at (resp, 2);
-         if (!arg || arg->type != imap_eltype_string)
-           break;
-         n = strtoul (arg->v.string, &p, 10);
-         if (*p == ']')
-           {
-             imap->mbox_stat.uidvalidity = n;
-             imap->mbox_stat.flags |= MU_IMAP_STAT_UIDVALIDITY;
-             mu_imap_callback (imap, MU_IMAP_CB_UIDVALIDITY, resp,
-                               &imap->mbox_stat);
-           }
-         return;
+    case MU_IMAP_RESPONSE_UIDNEXT:
+      arg = _mu_imap_list_at (resp, 3);
+      if (!arg || arg->type != imap_eltype_string)
+       break;
+      n = strtoul (arg->v.string, &p, 10);
+      if (*p == 0)
+       {
+         imap->mbox_stat.uidnext = n;
+         imap->mbox_stat.flags |= MU_IMAP_STAT_UIDNEXT;
+         mu_imap_callback (imap, MU_IMAP_CB_UIDNEXT, &imap->mbox_stat);
+       }
+      return;
                            
-       case MU_IMAP_RESPONSE_UNSEEN:
-         arg = _mu_imap_list_at (resp, 2);
-         if (!arg || arg->type != imap_eltype_string)
-           break;
-         n = strtoul (arg->v.string, &p, 10);
-         if (*p == ']')
-           {
-             imap->mbox_stat.first_unseen = n;
-             imap->mbox_stat.flags |= MU_IMAP_STAT_FIRST_UNSEEN;
-             mu_imap_callback (imap, MU_IMAP_CB_FIRST_UNSEEN, resp,
-                               &imap->mbox_stat);
-           }
-         return;
+    case MU_IMAP_RESPONSE_UIDVALIDITY:
+      arg = _mu_imap_list_at (resp, 3);
+      if (!arg || arg->type != imap_eltype_string)
+       break;
+      n = strtoul (arg->v.string, &p, 10);
+      if (*p == 0)
+       {
+         imap->mbox_stat.uidvalidity = n;
+         imap->mbox_stat.flags |= MU_IMAP_STAT_UIDVALIDITY;
+         mu_imap_callback (imap, MU_IMAP_CB_UIDVALIDITY, &imap->mbox_stat);
        }
+      return;
+      
+    case MU_IMAP_RESPONSE_UNSEEN:
+      arg = _mu_imap_list_at (resp, 3);
+      if (!arg || arg->type != imap_eltype_string)
+       break;
+      n = strtoul (arg->v.string, &p, 10);
+      if (*p == 0)
+       {
+         imap->mbox_stat.first_unseen = n;
+         imap->mbox_stat.flags |= MU_IMAP_STAT_FIRST_UNSEEN;
+         mu_imap_callback (imap, MU_IMAP_CB_FIRST_UNSEEN, &imap->mbox_stat);
+       }
+      return;
+    }
+
+  if (mu_list_tail (resp, (void*) &arg) || arg->type != imap_eltype_string)
+    arg = NULL;
+  mu_imap_callback (imap, MU_IMAP_CB_OK, rcode, arg ? arg->v.string : NULL);
+  if (imap->state == MU_IMAP_GREETINGS)
+    {
+      imap->state = MU_IMAP_CONNECTED;
+      imap->imap_state = MU_IMAP_STATE_NONAUTH;
+    }
+}
+
+static void
+default_response (mu_imap_t imap, int code, mu_list_t resp, void *data)
+{
+  struct imap_list_element *arg;
+
+  if (mu_list_tail (resp, (void*) &arg) || arg->type != imap_eltype_string)
+    arg = NULL;
+  mu_imap_callback (imap, code, parse_response_code (imap, resp),
+                   arg ? arg->v.string : NULL);
+}
+
+static void
+no_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+  default_response (imap, MU_IMAP_CB_NO, resp, data);
+  if (imap->state == MU_IMAP_GREETINGS)
+    imap->state = MU_IMAP_ERROR;
+}
+
+static void
+bad_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+  default_response (imap, MU_IMAP_CB_BAD, resp, data);
+  if (imap->state == MU_IMAP_GREETINGS)
+    imap->state = MU_IMAP_ERROR;
+}
+
+static void
+bye_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+  default_response (imap, MU_IMAP_CB_BYE, resp, data);
+  imap->state = MU_IMAP_CLOSING;
+}
+
+static void
+preauth_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+  if (imap->state == MU_IMAP_GREETINGS)
+    {
+      struct imap_list_element *arg;
+
+      if (mu_list_tail (resp, (void*) &arg) || arg->type != imap_eltype_string)
+       arg = NULL;
+      mu_imap_callback (imap, MU_IMAP_CB_PREAUTH,
+                       parse_response_code (imap, resp),
+                       arg ? arg->v.string : NULL);
+      imap->state = MU_IMAP_CONNECTED;
+      imap->imap_state = MU_IMAP_STATE_AUTH;
     }
-  mu_imap_callback (imap, MU_IMAP_CB_OK, resp, rcode);
+  else
+    mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
+             ("ignoring unexpected PREAUTH response"));
 }
 
+
 
 struct response_closure
 {
@@ -147,10 +220,10 @@ struct resptab
 
 static struct resptab resptab[] = {
   { "OK", ok_response },
-  { "NO", },
-  { "BAD", },
-  { "PREAUTH", },
-  { "BYE", },
+  { "NO", no_response },
+  { "BAD", bad_response },
+  { "PREAUTH", preauth_response },
+  { "BYE", bye_response },
   { NULL }
 };
 
@@ -211,7 +284,8 @@ _process_unsolicited_response (mu_imap_t imap, mu_list_t 
resp)
            return 1;
          imap->mbox_stat.message_count = n;
          imap->mbox_stat.flags |= MU_IMAP_STAT_MESSAGE_COUNT;
-         mu_imap_callback (imap, MU_IMAP_CB_MESSAGE_COUNT, resp, n);
+         mu_imap_callback (imap, MU_IMAP_CB_MESSAGE_COUNT, resp,
+                           &imap->mbox_stat);
          return 0;
        }
       else if (_mu_imap_list_element_is_string (arg, "RECENT"))
@@ -224,7 +298,8 @@ _process_unsolicited_response (mu_imap_t imap, mu_list_t 
resp)
            return 1;
          imap->mbox_stat.recent_count = n;
          imap->mbox_stat.flags |= MU_IMAP_STAT_RECENT_COUNT;
-         mu_imap_callback (imap, MU_IMAP_CB_RECENT_COUNT, resp, n);
+         mu_imap_callback (imap, MU_IMAP_CB_RECENT_COUNT, resp,
+                           &imap->mbox_stat);
          return 0;
        }
     }
@@ -243,7 +318,13 @@ _process_response (void *item, void *data)
                ("ignoring string response \"%s\"", elt->v.string));
     }
   else if (_process_unsolicited_response (clos->imap, elt->v.list))
-    clos->fun (clos->imap, elt->v.list, clos->data);
+    {
+      if (clos->fun)
+       clos->fun (clos->imap, elt->v.list, clos->data);
+      else
+       mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
+                 ("ignoring unexpected response"));
+    }
   return 0;
 }
 
diff --git a/libproto/imap/select.c b/libproto/imap/select.c
index 0679197..83a0926 100644
--- a/libproto/imap/select.c
+++ b/libproto/imap/select.c
@@ -67,7 +67,6 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int 
writable,
                struct mu_imap_stat *ps)
 {
   int status;
-  char *p;
   
   if (imap == NULL)
     return EINVAL;
@@ -138,11 +137,6 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int 
writable,
 
        case MU_IMAP_BAD:
          status = MU_ERR_BADREPLY;
-         if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-           {
-             _mu_imap_seterrstr (imap, p, strlen (p));
-             free (p);
-           }
          break;
        }
       imap->state = MU_IMAP_CONNECTED;
diff --git a/libproto/imap/status.c b/libproto/imap/status.c
index 1957bf9..3870572 100644
--- a/libproto/imap/status.c
+++ b/libproto/imap/status.c
@@ -119,7 +119,6 @@ int
 mu_imap_status (mu_imap_t imap, const char *mboxname, struct mu_imap_stat *ps)
 {
   int status;
-  char *p;
   int delim = 0;
   int i;
   
@@ -201,11 +200,6 @@ mu_imap_status (mu_imap_t imap, const char *mboxname, 
struct mu_imap_stat *ps)
 
        case MU_IMAP_BAD:
          status = MU_ERR_BADREPLY;
-         if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
-           {
-             _mu_imap_seterrstr (imap, p, strlen (p));
-             free (p);
-           }
          break;
        }
       imap->state = MU_IMAP_CONNECTED;
diff --git a/mu/imap.c b/mu/imap.c
index 103829e..6fc0a24 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -150,7 +150,18 @@ imap_prompt_env ()
 
   mutool_prompt_env[14] = NULL;
 }
-
+
+/* Callbacks */
+static void
+imap_popauth_callback (void *data, int code, va_list ap)
+{
+  int rcode = va_arg (ap, int);
+  const char *text = va_arg (ap, const char *);
+  if (text)
+    mu_diag_output (MU_DIAG_INFO, _("session authenticated: %s"), text);
+  else
+    mu_diag_output (MU_DIAG_INFO, _("session authenticated"));
+}
 
 static int
 com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
@@ -206,12 +217,6 @@ com_connect (int argc, char **argv)
       struct mu_sockaddr *sa;
       struct mu_sockaddr_hints hints;
 
-      if (QRY_VERBOSE ())
-       {
-         imap_set_verbose ();
-         imap_set_verbose_mask ();
-       }
-
       memset (&hints, 0, sizeof (hints));
       hints.flags = MU_AH_DETECT_FAMILY;
       hints.port = tls ? MU_IMAP_DEFAULT_SSL_PORT : MU_IMAP_DEFAULT_PORT;
@@ -243,6 +248,19 @@ com_connect (int argc, char **argv)
            }
 #endif
          mu_imap_set_carrier (imap, tcp);
+
+         if (QRY_VERBOSE ())
+           {
+             imap_set_verbose ();
+             imap_set_verbose_mask ();
+           }
+
+         /* Set callbacks */
+         mu_imap_register_callback_function (imap, MU_IMAP_CB_PREAUTH,
+                                             imap_popauth_callback,
+                                             NULL);
+
+         
          status = mu_imap_connect (imap);
          if (status)
            {
@@ -554,7 +572,6 @@ com_status (int argc, char **argv)
     }
   return 0;
 }
-
 
 struct mutool_command imap_comtab[] = {
   { "capability", 1, -1, com_capability,


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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