chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / innfeed / imap_connection.c
diff --git a/innfeed/imap_connection.c b/innfeed/imap_connection.c
deleted file mode 100644 (file)
index f575686..0000000
+++ /dev/null
@@ -1,4681 +0,0 @@
-/*  $Id: imap_connection.c 7103 2004-12-23 22:36:27Z rra $
-**
-**  Feed articles to an IMAP server via LMTP and IMAP.
-**
-**  Written by Tim Martin.
-**
-**  Instead of feeding articles via nntp to another host this feeds the
-**  messages via lmtp to a host and the control messages (cancel's etc..) it
-**  performs via IMAP.  This means it has 2 active connections at any given
-**  time and 2 queues.
-**
-**  When an article comes in it is immediatly placed in the lmtp queue. When
-**  an article is picked off the lmtp queue for processing first check if it's
-**  a control message.  If so, place it in the IMAP queue.  If not, attempt to
-**  deliver via LMTP.
-**
-**  This attempts to follow the exact same api as connection.c.
-**  
-**  TODO:
-**  
-**  feed to smtp 
-**  security layers?  <--punt on for now
-**  authname/password per connection object
-**  untagged IMAP messages
-*/
-
-#include "config.h"
-#include "clibrary.h"
-#include "portable/socket.h"
-#include <ctype.h>
-#include <errno.h>
-#include <netdb.h>
-#include <netdb.h>
-#include <time.h>
-#include <syslog.h>
-
-#include "inn/messages.h"
-#include "libinn.h"
-
-#include "buffer.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "host.h"
-#include "innfeed.h"
-#include "article.h"
-#include "configfile.h"
-
-#ifdef HAVE_SASL
-# include <sasl/sasl.h>
-#endif
-
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 1024
-#endif
-
-#define IMAP_PORT 143
-
-#ifdef SMTPMODE
-# define LMTP_PORT 25
-#else
-# define LMTP_PORT 2003
-#endif
-
-#define IMAP_TAGLENGTH 6
-
-#define QUEUE_MAX_SIZE 250
-
-#define DOSOMETHING_TIMEOUT 60
-
-
-
-/* external */
-extern char *deliver_username;
-extern char *deliver_authname;
-extern char *deliver_password;
-extern char *deliver_realm;
-extern char *deliver_rcpt_to;
-extern char *deliver_to_header;
-
-
-char hostname[MAXHOSTNAMELEN];
-char *mailfrom_name = NULL; /* default to no return path */
-
-#ifdef HAVE_SASL
-static int initialized_sasl = 0; /* weather sasl_client_init() has been called */
-#endif
-
-/* states the imap connection may be in */
-typedef enum {
-
-    IMAP_DISCONNECTED = 1,
-    IMAP_WAITING,
-    
-    IMAP_CONNECTED_NOTAUTH,
-
-    IMAP_READING_INTRO,
-
-    IMAP_WRITING_CAPABILITY,
-    IMAP_READING_CAPABILITY,
-
-    IMAP_WRITING_STARTAUTH,
-    IMAP_READING_STEPAUTH,
-    IMAP_WRITING_STEPAUTH,
-
-    IMAP_IDLE_AUTHED,
-    IMAP_WRITING_NOOP,
-    IMAP_READING_NOOP,
-
-    IMAP_WRITING_CREATE,
-    IMAP_READING_CREATE,
-
-    IMAP_WRITING_DELETE,
-    IMAP_READING_DELETE,
-
-    IMAP_WRITING_SELECT,
-    IMAP_READING_SELECT,
-
-    IMAP_WRITING_SEARCH,
-    IMAP_READING_SEARCH,
-
-    IMAP_WRITING_STORE,
-    IMAP_READING_STORE,
-    
-    IMAP_WRITING_CLOSE,
-    IMAP_READING_CLOSE,
-
-    IMAP_WRITING_QUIT,
-    IMAP_READING_QUIT
-   
-} imap_state_t;
-
-typedef enum {
-    LMTP_DISCONNECTED = 1,
-    LMTP_WAITING,
-
-    LMTP_CONNECTED_NOTAUTH,
-
-    LMTP_READING_INTRO,
-
-    LMTP_WRITING_LHLO,
-    LMTP_READING_LHLO,
-
-    LMTP_WRITING_STARTAUTH,
-    LMTP_READING_STEPAUTH,
-    LMTP_WRITING_STEPAUTH,
-
-    LMTP_AUTHED_IDLE,
-    LMTP_WRITING_NOOP,
-    LMTP_READING_NOOP,
-   
-    LMTP_READING_RSET,
-    LMTP_READING_MAILFROM,
-    LMTP_READING_RCPTTO,
-    LMTP_READING_DATA,
-    LMTP_READING_CONTENTS,
-
-    LMTP_WRITING_UPTODATA,
-    LMTP_WRITING_CONTENTS,
-
-    LMTP_WRITING_QUIT,
-    LMTP_READING_QUIT
-
-} lmtp_state_t;
-
-typedef struct imap_capabilities_s {
-
-    int imap4;         /* does server support imap4bis? */
-    int logindisabled; /* does the server allow the login command? */
-
-    char *saslmechs;   /* supported SASL mechanisms */
-
-} imap_capabilities_t;
-
-typedef struct lmtp_capabilities_s {
-
-    int Eightbitmime;
-    int EnhancedStatusCodes;
-    int pipelining;
-
-    char *saslmechs;
-
-} lmtp_capabilities_t;
-
-typedef enum {
-    STAT_CONT = 0,
-    STAT_NO = 1,
-    STAT_OK = 2,
-    STAT_FAIL = 3
-} imt_stat;
-
-/* Message types */
-typedef enum {
-    DELIVER,
-    CREATE_FOLDER,
-    CANCEL_MSG,
-    DELETE_FOLDER
-} control_type_t;
-
-typedef struct control_item_s {
-
-    Article article;
-    char *folder;
-    char *msgid;                 /* only for cancel's */
-    unsigned long  uid;          /* only for cancel's */
-
-} control_item_t;
-
-typedef struct article_queue_s {
-
-    control_type_t type;
-
-    time_t arrived;
-    time_t nextsend; /* time we should next try to send article */
-
-    int trys;
-
-    int counts_toward_size;
-
-    union {
-       Article article;
-       control_item_t *control;
-       void *generic;
-    } data;
-
-    struct article_queue_s *next;
-
-} article_queue_t;
-
-typedef struct Q_s {
-
-    article_queue_t *head;
-
-    article_queue_t *tail;
-
-    int size;
-
-} Q_t;
-
-typedef struct connection_s {
-
-    /* common stuff */
-    char *ServerName;
-
-    char *lmtp_respBuffer;         /* buffer all responses are read into */
-    Buffer lmtp_rBuffer;           /* buffer all responses are read into */
-
-    Host myHost ;                   /* the host who owns the connection */
-    
-    time_t timeCon ;                /* the time the connect happened 
-                                      (last auth succeeded) */
-
-    int issue_quit;                 /* Three states:
-                                    *   0 - don't do anything
-                                    *   1 - after issue quit enter wait state
-                                    *   2 - after issue quit reconnect
-                                    *   3 - after issue quit delete connection
-                                    *   4 - nuke cxn
-                                    */
-
-    /* Statistics */    
-    int lmtp_succeeded;
-    int lmtp_failed;
-
-    int cancel_succeeded;
-    int cancel_failed;
-    
-    int create_succeeded;
-    int create_failed;
-    
-    int remove_succeeded;
-    int remove_failed;
-
-    
-    /* LMTP stuff */
-    int lmtp_port;
-    lmtp_state_t lmtp_state;
-#ifdef HAVE_SASL
-    sasl_conn_t *saslconn_lmtp;
-#endif /* HAVE_SASL */
-    int sockfd_lmtp;
-
-    time_t lmtp_timeCon ;
-
-    EndPoint lmtp_endpoint;
-    unsigned int ident ;               /* an identifier for syslogging. */
-
-    lmtp_capabilities_t *lmtp_capabilities;
-
-    int lmtp_disconnects;
-    char *lmtp_tofree_str;
-
-    article_queue_t *current_article;
-    Buffer *current_bufs;
-    int     current_rcpts_issued;
-    int     current_rcpts_okayed;
-
-    /* Timer for the max amount of time to wait for a response from the
-       remote */
-    unsigned int lmtp_readTimeout ;
-    TimeoutId lmtp_readBlockedTimerId ;
-
-    /* Timer for the max amount of time to wait for a any amount of data
-       to be written to the remote */
-    unsigned int lmtp_writeTimeout ;
-    TimeoutId lmtp_writeBlockedTimerId ;
-
-    /* Timer for the number of seconds to sleep before attempting a
-       reconnect. */
-    unsigned int lmtp_sleepTimeout ;
-    TimeoutId lmtp_sleepTimerId ;
-
-    /* Timer for max amount between queueing some articles and trying to send them */
-    unsigned int dosomethingTimeout ;
-    TimeoutId dosomethingTimerId ;
-
-    Q_t lmtp_todeliver_q;
-
-
-
-    /* IMAP stuff */
-    int imap_port;
-#ifdef HAVE_SASL
-    sasl_conn_t *imap_saslconn;
-#endif /* HAVE_SASL */
-
-    char *imap_respBuffer;
-    Buffer imap_rBuffer;
-    EndPoint imap_endpoint;
-
-    imap_capabilities_t *imap_capabilities;
-    
-    int imap_sockfd;
-
-    time_t imap_timeCon ;
-
-    imap_state_t imap_state;
-    int imap_disconnects;
-    char *imap_tofree_str;
-
-    char imap_currentTag[IMAP_TAGLENGTH];
-    int  imap_tag_num;
-
-    /* Timer for the max amount of time to wait for a response from the
-       remote */
-    unsigned int imap_readTimeout ;
-    TimeoutId imap_readBlockedTimerId ;
-
-    /* Timer for the max amount of time to wait for a any amount of data
-       to be written to the remote */
-    unsigned int imap_writeTimeout ;
-    TimeoutId imap_writeBlockedTimerId ;
-
-    /* Timer for the number of seconds to sleep before attempting a
-       reconnect. */
-    unsigned int imap_sleepTimeout ;
-    TimeoutId imap_sleepTimerId ;
-
-    Q_t imap_controlMsg_q;
-
-    article_queue_t *current_control;
-
-    struct connection_s *next;
-
-} connection_t;
-
-static Connection gCxnList = NULL ;
-static unsigned int gCxnCount= 0 ;
-static unsigned int max_reconnect_period = MAX_RECON_PER ;
-static unsigned int init_reconnect_period = INIT_RECON_PER;
-
-typedef enum {
-    RET_OK = 0,
-    RET_FAIL = 1,
-    RET_QUEUE_EMPTY,
-    RET_EXCEEDS_SIZE,
-    RET_NO_FULLLINE,
-    RET_NO,
-    RET_ARTICLE_BAD
-} conn_ret;
-
-
-/********** Private Function Declarations *************/
-
-static void lmtp_readCB (EndPoint e, IoStatus i, Buffer *b, void *d);
-static void imap_readCB (EndPoint e, IoStatus i, Buffer *b, void *d);
-static void imap_writeCB (EndPoint e, IoStatus i, Buffer *b, void *d);
-static void lmtp_writeCB (EndPoint e, IoStatus i, Buffer *b, void *d);
-
-static conn_ret lmtp_Connect(connection_t *cxn);
-static conn_ret imap_Connect(connection_t *cxn);
-
-static void prepareReopenCbk (Connection cxn, int type);
-
-static void lmtp_readTimeoutCbk (TimeoutId id, void *data);
-static void imap_readTimeoutCbk (TimeoutId id, void *data);
-
-static void dosomethingTimeoutCbk (TimeoutId id, void *data);
-
-static conn_ret WriteToWire_imapstr(connection_t *cxn, char *str, int slen);
-static conn_ret WriteToWire_lmtpstr(connection_t *cxn, char *str, int slen);
-
-static conn_ret WriteToWire(connection_t *cxn, EndpRWCB callback, 
-                           EndPoint endp, Buffer *array);
-static void lmtp_sendmessage(connection_t *cxn, Article justadded);
-static void imap_ProcessQueue(connection_t *cxn);
-
-static conn_ret FindHeader(Buffer *bufs, const char *header, char **start, char **end);
-static conn_ret PopFromQueue(Q_t *q, article_queue_t **item);
-
-enum failure_type {
-    MSG_SUCCESS = 0,
-    MSG_FAIL_DELIVER = 1,
-    MSG_GIVE_BACK = 2,
-    MSG_MISSING = 3
-};
-
-static void QueueForgetAbout(connection_t *cxn, article_queue_t *item, 
-                            enum failure_type failed);
-
-static void delConnection (Connection cxn);
-static void DeleteIfDisconnected(Connection cxn);
-static void DeferAllArticles(connection_t *cxn, Q_t *q);
-
-static void lmtp_Disconnect(connection_t *cxn);
-static void imap_Disconnect(connection_t *cxn);
-static conn_ret imap_listenintro(connection_t *cxn);
-
-static void imap_writeTimeoutCbk (TimeoutId id, void *data);
-static void lmtp_writeTimeoutCbk (TimeoutId id, void *data);
-
-/******************** PRIVATE FUNCTIONS ***************************/
-
-static const char *imap_stateToString(int state)
-{
-    switch (state)
-       {
-       case IMAP_DISCONNECTED: return "disconnected";   
-       case IMAP_WAITING: return "waiting";
-       case IMAP_CONNECTED_NOTAUTH: return "connected (unauthenticated)";
-       case IMAP_READING_INTRO: return "reading intro";
-       case IMAP_WRITING_CAPABILITY: return "writing CAPABILITY";
-       case IMAP_READING_CAPABILITY: return "reading CAPABILITY";
-       case IMAP_WRITING_STARTAUTH: return "writing AUTHENTICATE";
-       case IMAP_READING_STEPAUTH: return "reading stepauth";
-       case IMAP_WRITING_STEPAUTH: return "writing stepauth";
-       case IMAP_IDLE_AUTHED: return "idle (authenticated)";
-       case IMAP_WRITING_NOOP: return "writing NOOP";
-       case IMAP_READING_NOOP: return "reading NOOP response";
-       case IMAP_WRITING_CREATE: return "writing CREATE";
-       case IMAP_READING_CREATE: return "reading CREATE response";
-       case IMAP_WRITING_DELETE: return "writing DELETE command";
-       case IMAP_READING_DELETE: return "reading DELETE response";            
-       case IMAP_WRITING_SELECT: return "writing SELECT";
-       case IMAP_READING_SELECT: return "reading SELECT response";
-       case IMAP_WRITING_SEARCH: return "writing SEARCH";
-       case IMAP_READING_SEARCH: return "reading SEARCH response";
-       case IMAP_WRITING_STORE: return "writing STORE";
-       case IMAP_READING_STORE: return "reading STORE response";           
-       case IMAP_WRITING_CLOSE: return "writing CLOSE";
-       case IMAP_READING_CLOSE: return "reading CLOSE response";
-       case IMAP_WRITING_QUIT: return "writing LOGOUT";
-       case IMAP_READING_QUIT: return "reading LOGOUT response";
-       default: return "Unknown state";
-       }
-}
-
-static const char *lmtp_stateToString(int state)
-{
-    switch(state)
-       {
-       case LMTP_DISCONNECTED: return "disconnected";
-       case LMTP_WAITING: return "waiting";
-       case LMTP_CONNECTED_NOTAUTH: return "connected (unauthenticated)";
-       case LMTP_READING_INTRO: return "reading intro";
-       case LMTP_WRITING_LHLO: return "writing LHLO";
-       case LMTP_READING_LHLO: return "reading LHLO response";
-       case LMTP_WRITING_STARTAUTH: return "writing AUTH";
-       case LMTP_READING_STEPAUTH: return "reading stepauth";
-       case LMTP_WRITING_STEPAUTH: return "writing stepauth";
-       case LMTP_AUTHED_IDLE: return "idle (authenticated)";
-       case LMTP_WRITING_NOOP: return "writing NOOP";
-       case LMTP_READING_NOOP: return "reading NOOP response";
-       case LMTP_READING_RSET: return "reading RSET response";
-       case LMTP_READING_MAILFROM: return "reading MAIL FROM response";
-       case LMTP_READING_RCPTTO: return "reading RCPT TO response";
-       case LMTP_READING_DATA: return "reading DATA response";
-       case LMTP_READING_CONTENTS: return "reading contents response";
-       case LMTP_WRITING_UPTODATA: 
-           return "writing RSET, MAIL FROM, RCPT TO, DATA commands";
-       case LMTP_WRITING_CONTENTS: return "writing contents of message";
-       case LMTP_WRITING_QUIT: return "writing QUIT";
-       case LMTP_READING_QUIT: return "reading QUIT";
-       default: return "unknown state";
-       }
-}
-
-/******************************* Queue functions ***********************************/
-
-/*
- * Add a message to a generic queue
- *
- *  q       - the queue adding to
- *  item    - the data to add to the queue
- *  type    - the type of item it is (i.e. cancel,lmtp,etc..)
- *  addsmsg - weather this should be counted toward the queue size
- *            this is for control msg's that create multiple queue items.
- *            For example a cancel message canceling a message in multiple
- *            newsgroups will create >1 queue item but we only want it to count
- *            once towards the queue
- *  must    - wheather we must take it even though it may put us over our max size
- */
-
-static conn_ret AddToQueue(Q_t *q, void *item, 
-                          control_type_t type, int addsmsg, bool must)
-{
-    article_queue_t *newentry;
-
-    if (must == false)
-    {
-       if (q->size >= QUEUE_MAX_SIZE)
-        {
-           return RET_EXCEEDS_SIZE;
-       }
-    } else {
-       if (q->size >= QUEUE_MAX_SIZE * 10)
-        {
-           d_printf(0, "Queue has grown way too much. Dropping article\n");
-           return RET_FAIL;
-       }
-    }
-
-    /* add to the end of our queue */
-    newentry = xmalloc(sizeof(article_queue_t));
-
-    newentry->type = type;
-
-    /* send as soon as possible */
-    newentry->nextsend = newentry->arrived = time(NULL);
-
-    newentry->trys = 0;
-
-    newentry->data.generic = item;
-    newentry->next = NULL;
-    newentry->counts_toward_size = addsmsg;
-
-    /* add to end of queue */
-    if (q->tail == NULL)
-    {
-       q->head = newentry;
-       q->tail = newentry;
-    } else {
-
-       q->tail->next = newentry;
-       q->tail = newentry;
-    }
-
-    q->size+=addsmsg;
-
-    return RET_OK;
-}
-
-/*
- * Pop an item from the queue
- *
- * q    - the queue to pop from
- * item - where the item shall be placed upon sucess
- *
- */
-
-static conn_ret PopFromQueue(Q_t *q, article_queue_t **item)
-{
-    /* if queue empty return error */
-    if ( q->head == NULL)
-    {
-       return RET_QUEUE_EMPTY;
-    }
-    
-    /* set what we return */
-    *item = q->head;
-
-    q->head = q->head->next;
-    if (q->head == NULL) q->tail = NULL;
-
-    q->size-=(*item)->counts_toward_size;
-    
-    return RET_OK;
-}
-
-/*
- * ReQueue an item. Will either put it back in the queue for another try
- * or forget about it
- *
- *  cxn     - our connection object (needed so forget about things)
- *  q       - the queue to requeue to 
- *  entry   - the item to put back
- */
-
-static void ReQueue(connection_t *cxn, Q_t *q, article_queue_t *entry)
-{
-    /* look at the time it's been here */
-    entry->nextsend = time(NULL) + (entry->trys *30); /* xxx better formula? */
-
-    entry->trys++;
-    
-    /* give up after 5 tries xxx configurable??? */
-    if (entry->trys >= 5)
-    {
-       QueueForgetAbout(cxn, entry, MSG_FAIL_DELIVER);
-       return;
-    }
-
-
-    /* ok let's add back to the end of the queue */
-    entry->next = NULL;
-
-    /* add to end of queue */
-    if (q->tail == NULL)
-    {
-       q->head = entry;
-       q->tail = entry;
-    } else {
-       q->tail->next = entry;
-       q->tail = entry;
-    }
-
-    q->size+=entry->counts_toward_size;
-}
-
-
-
-/*
- * Forget about an item. Tells host object if we succeeded/failed/etc with the message
- *
- * cxn    - connection object
- * item   - item
- * failed - type of failure (see below)
- *
- * failed:
- *   0 - succeeded delivering message
- *   1 - failed delivering message
- *   2 - Try to give back to host
- *   3 - Article missing (i.e. can't find on disk)
- */
-static void QueueForgetAbout(connection_t *cxn, article_queue_t *item, 
-                            enum failure_type failed)
-{
-    Article art = NULL;
-    
-    switch (item->type)
-       {
-       case DELIVER:
-           if (failed>0)
-               cxn->lmtp_failed++;
-           art = item->data.article;
-           break;
-
-       case CANCEL_MSG:
-           if (failed>0)
-               cxn->cancel_failed++;
-           free(item->data.control->msgid);
-           free(item->data.control->folder);
-
-           if (item->counts_toward_size == 1)
-               art = item->data.control->article;
-
-           free(item->data.control );
-           break;
-
-       case CREATE_FOLDER: 
-           if (failed>0)
-               cxn->create_failed++;
-           free(item->data.control->folder);
-
-           art = item->data.control->article;
-
-           free(item->data.control );
-           break;
-       case DELETE_FOLDER:
-           if (failed>0)
-               cxn->remove_failed++;
-           free(item->data.control->folder);
-
-           art = item->data.control->article;
-
-           free(item->data.control );
-           break;
-
-       default:
-           d_printf(0, "%s:%d QueueForgetAbout(): "
-                    "Unknown type to forget about\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           break;
-       }
-
-    if (art!=NULL) {
-       switch (failed) {
-       case MSG_SUCCESS:
-           hostArticleAccepted (cxn->myHost, cxn, art);
-           break;
-
-       case MSG_FAIL_DELIVER:
-           hostArticleRejected (cxn->myHost, cxn, art);
-           break;
-
-       case MSG_GIVE_BACK:
-           hostTakeBackArticle (cxn->myHost, cxn, art);
-           break;
-
-       case MSG_MISSING:
-           hostArticleIsMissing(cxn->myHost, cxn, art);
-           break;
-       default:
-           d_printf(0,"%s:%d QueueForgetAbout(): failure type unknown\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           break;
-       }
-    }
-
-    free(item);
-}
-
-/*
- * How much space is available in the queue
- */
-
-static int QueueSpace(Q_t *q)
-{
-    int ret = QUEUE_MAX_SIZE - q->size;
-    if (ret < 0) ret = 0;
-    return ret;
-}
-
-/*
- * How many items are in the queue
- */
-
-static int QueueItems(Q_t *q)
-{
-    return q->size;
-}
-
-
-/***************************** END Queue functions ***********************************/
-
-/***************************** Generic Parse Functions *******************************/
-
-/* returns the end of the header */
-
-static char *GetUntil(char *str)
-{
-    while (((*str) != '\0') && ( (*str) != '\r') && ( (*str) != '\n'))
-    {
-       str++;
-    }
-
-    return str;
-}
-
-static char *GotoNextLine(char *str)
-{
-    while (((*str) != '\0') && ( (*str) != '\r') && ( (*str) != '\n'))
-    {
-       str++;
-    }
-
-    if (*str == '\r') str++;
-    if (*str == '\n') str++;
-
-    return str;
-}
-
-/*
- * Finds the given header in the message
- *  Returns NULL if not found
- */
-static conn_ret FindHeader(Buffer *bufs, const char *header, char **start,
-       char **end)
-{
-    Buffer b;
-    int size;
-    char *str_base;
-    char *str;
-    int headerlen = strlen(header);
-    
-    if (bufs==NULL)
-    {
-       if (start)
-           *start=NULL; 
-       return RET_ARTICLE_BAD; 
-    }
-    
-    b = bufs[0];
-    size = bufferSize(b);
-    str_base = bufferBase(b);
-    str = str_base;
-    
-    while ((str - str_base) < size - headerlen)
-    {
-       if (*str == header[0])
-       {
-           if ((strncasecmp(header, str, headerlen)==0) && ( *(str + headerlen)==':'))
-           {
-
-               if (start)
-               {
-                   *start = str+headerlen+1;
-
-                   /* get rid of leading whitespace */
-                   while ( isspace((int) **start))                     
-                       (*start)++;
-               }
-               
-               if (end)
-                   *end = GetUntil(str+headerlen+1);
-               
-               return RET_OK;
-           }
-       } else if (*str == '\n') { 
-           /* end of headers */
-           return RET_NO;
-       }
-       str = GotoNextLine(str);
-    }
-
-    return RET_NO;
-}
-
-static conn_ret GetLine(char *buf, char *ret, int retmaxsize)
-{
-    char *str_base;
-    char *str;
-
-    int size = strlen(buf);
-    str_base = buf;
-    str = str_base;
-
-    while ( (*str) != '\0')
-    {
-       if ((*str) == '\n')
-        {
-           if (str-str_base > retmaxsize)
-           {
-               d_printf(0, "Max size exceeded! %s\n",str_base);
-               return RET_FAIL;
-           }
-
-           /* fill in the return string */
-           memcpy(ret, str_base, str-str_base);
-           ret[ str - str_base -1] = '\0';
-
-           memcpy( str_base, str_base + (str-str_base)+1, size - (str-str_base));
-           str_base[size - (str-str_base)]='\0';
-
-           return RET_OK;
-       }
-
-       str++;
-    }
-
-    /* couldn't find a full line */
-    return RET_NO_FULLLINE;
-}
-
-
-
-/************************** END Generic Parse Functions *******************************/
-
-/************************ Writing to Network functions *****************/
-
-static conn_ret WriteToWire(connection_t *cxn, EndpRWCB callback, 
-                           EndPoint endp, Buffer *array)
-{
-
-    if (array == NULL) return RET_FAIL;
-
-    prepareWrite (endp,
-                  array,
-                  NULL,
-                 callback,
-                  cxn);
-
-    return RET_OK;
-}
-
-static conn_ret WriteToWire_str(connection_t *cxn, EndpRWCB callback,
-                               EndPoint endp, char *str, int slen)
-{
-    conn_ret result;
-    Buffer buff;
-    Buffer *writeArr;
-
-    if (slen==-1) slen = strlen(str);
-
-    buff = newBufferByCharP(str, slen+1, slen);
-    ASSERT (buff != NULL);   
-
-    writeArr = makeBufferArray (buff, NULL) ;
-
-    result = WriteToWire(cxn, callback, endp, writeArr);
-
-    return result;
-}
-
-static conn_ret WriteToWire_imapstr(connection_t *cxn, char *str, int slen)
-{
-    /* prepare the timeouts */
-    clearTimer (cxn->imap_readBlockedTimerId) ;
-    
-    /* set up the write timer. */
-    clearTimer (cxn->imap_writeBlockedTimerId) ;
-
-    if (cxn->imap_writeTimeout > 0)
-       cxn->imap_writeBlockedTimerId = prepareSleep (imap_writeTimeoutCbk, cxn->imap_writeTimeout,
-                                                cxn);
-    cxn->imap_tofree_str = str;
-    return WriteToWire_str(cxn, imap_writeCB, cxn->imap_endpoint, str, slen);
-}
-
-static conn_ret WriteToWire_lmtpstr(connection_t *cxn, char *str, int slen)
-{
-    /* prepare the timeouts */
-    clearTimer (cxn->lmtp_readBlockedTimerId) ;
-    
-    /* set up the write timer. */
-    clearTimer (cxn->lmtp_writeBlockedTimerId) ;
-
-    if (cxn->lmtp_writeTimeout > 0)
-       cxn->lmtp_writeBlockedTimerId = prepareSleep (lmtp_writeTimeoutCbk, cxn->lmtp_writeTimeout,
-                                                cxn) ;
-
-
-
-    cxn->lmtp_tofree_str = str;
-    return WriteToWire_str(cxn, lmtp_writeCB, cxn->lmtp_endpoint, str, slen);
-}
-
-static conn_ret WriteArticle(connection_t *cxn, Buffer *array)
-{
-    int array_len = bufferArrayLen (array);
-    int lup=0;
-    int result;
-
-    for (lup=0;lup<array_len;lup++)
-    {
-       int current_size;
-       Buffer current_buf;
-       char *current_start;
-
-       current_buf = array[lup];
-               
-       current_size = bufferDataSize( current_buf );
-       
-       current_start = bufferBase( current_buf );
-
-    }
-
-    /* just call writetowire since it's easy */
-    result = WriteToWire(cxn, lmtp_writeCB, cxn->lmtp_endpoint, array);
-
-    if (result!=RET_OK)
-    {
-       return result;
-    }
-
-    cxn->lmtp_state = LMTP_WRITING_CONTENTS;
-
-    return RET_OK;
-}
-
-/************************ END Writing to Network functions *****************/
-
-
-
-/*
- * Adds a cancel item to the control queue
- * Cancel item to delete message with <msgid> in <folder>
- *
- * cxn       - connection object
- * folder    - pointer to start of folder string (this is a pointer into the actual message buffer)
- * folderlen - length of folder string 
- * msgid     - pointer to start of msgid string (this is a pointer into the actual message buffer)
- * msgidlen  - length of msgid string 
- * art       - the article for this control message (NULL if this cancel object lacks one)
- * must      - if must be accepted into queue
- */
-
-static conn_ret addCancelItem(connection_t *cxn, 
-                             char *folder, int folderlen,
-                             char *msgid, int msgidlen,
-                             Article art, int must)
-{
-    control_item_t *item;
-    conn_ret result;
-    int i;
-
-    ASSERT(folder); ASSERT(msgid); ASSERT(cxn);
-
-    /* sanity check folder, msgid */
-    for (i = 0; i < folderlen; i++) ASSERT(!isspace((int) folder[i]));
-    for (i = 0; i < msgidlen; i++) ASSERT(!isspace((int) msgid[i]));
-
-    /* create the object */
-    item = xcalloc (1, sizeof(control_item_t));
-
-    item->folder = xcalloc(folderlen+1, 1);
-    memcpy(item->folder, folder, folderlen);
-    item->folder[folderlen] = '\0';
-    
-    item->msgid = xcalloc (msgidlen+1, 1);
-    memcpy(item->msgid, msgid, msgidlen);
-    item->msgid[msgidlen] = '\0';
-
-    item->article = art;
-    
-    /* try to add to the queue (counts if art isn't null) */
-    result = AddToQueue(&(cxn->imap_controlMsg_q), item, CANCEL_MSG, (art != NULL), must);
-    if (result != RET_OK) {
-       d_printf(1,"%s:%d addCancelItem(): "
-                "I thought we had in space in [imap] queue "
-                "but apparently not\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-
-       /* cleanup */
-       free(item->folder);
-       free(item->msgid);
-       free(item);
-
-       return result;
-    }
-               
-    return RET_OK;
-}
-
-static conn_ret AddControlMsg(connection_t *cxn, 
-                             Article art, 
-                             Buffer *bufs, 
-                             char *control_header, 
-                             char *control_header_end, 
-                             bool must)
-{
-    char *rcpt_list = NULL, *rcpt_list_end;
-    control_item_t *item;
-    conn_ret res = RET_OK;
-    int t;
-
-    /* make sure contents ok; this also should load it into memory */
-    if (!artContentsOk (art)) {
-       d_printf(0, "%s:%d AddControlMsg(): "
-                "artContentsOk() said article was bad\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       hostArticleIsMissing (cxn->myHost, cxn, art);
-       return RET_FAIL;
-    }
-
-    res = RET_OK;
-    /* now let's look at the control to see what it is */
-    if (!strncasecmp(control_header,"newgroup",8)) {
-       control_header += 8;
-       t = CREATE_FOLDER;
-    } else if (!strncasecmp(control_header,"rmgroup",7)) {
-       /* jump past "rmgroup" */
-       control_header += 7;
-       t = DELETE_FOLDER;
-    } else if (!strncasecmp(control_header,"cancel",6)) {
-       t = CANCEL_MSG;
-       control_header += 6;
-    } else {
-       /* unrecognized type */
-       char tmp[100];
-       char *endstr;
-       size_t clen;
-
-       endstr = strchr(control_header,'\n');
-       clen = endstr - control_header;
-
-       if (clen > sizeof(tmp)-1) clen = sizeof(tmp)-1;
-
-       memcpy(tmp,control_header, clen);
-       tmp[clen]='\0';
-       
-       d_printf(0,"%s:%d Don't understand control header [%s]\n",
-                hostPeerName (cxn->myHost), cxn->ident,tmp);
-       return RET_FAIL;
-    }
-
-    switch (t) {
-    case CREATE_FOLDER:
-    case DELETE_FOLDER:
-    {
-       int folderlen;
-
-       /* go past all white space */
-       while ((*control_header == ' ') && 
-              (control_header != control_header_end)) {
-           control_header++;
-       }
-
-       /* trim trailing whitespace */
-       while (control_header_end[-1] == ' ') {
-           control_header_end--;
-       }
-
-       if (control_header >= control_header_end) {
-           d_printf(0,"%s:%d addControlMsg(): "
-                    "newgroup/rmgroup header has no group specified\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           return RET_FAIL;
-       }
-
-       folderlen = control_header_end - control_header;
-
-       item = xcalloc(1, sizeof(control_item_t));
-
-       item->folder = xcalloc(folderlen + 1, 1);
-       memcpy(item->folder, control_header, folderlen);
-       item->folder[folderlen] = '\0';
-
-       item->article = art;
-
-       if (AddToQueue(&(cxn->imap_controlMsg_q), item, t, 1, must) != RET_OK) {
-           d_printf(1,"%s:%d addCancelItem(): "
-                    "I thought we had in space in [imap] queue"
-                    " but apparently not\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           free(item->folder);
-           free(item);
-           return RET_FAIL;
-       }
-
-       break;
-    }
-
-    case CANCEL_MSG:
-    {
-       char *str, *laststart;
-
-       while (((*control_header) == ' ') && 
-              (control_header != control_header_end))
-       {
-           control_header++;
-       }
-
-       if (control_header == control_header_end)
-       {
-           d_printf(0, "%s:%d Control header contains cancel "
-                       "with no msgid specified\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           return RET_FAIL;
-       }
-
-       if (FindHeader(bufs, "Newsgroups", &rcpt_list, &rcpt_list_end)!=RET_OK)
-       {
-           d_printf(0,"%s:%d Cancel msg contains no newsgroups header\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           return RET_FAIL;
-       }
-
-       str = rcpt_list;
-       laststart = rcpt_list;
-
-       while (str != rcpt_list_end)
-       {
-           if (*str == ',') {
-               /* eliminate leading whitespace */
-               while (((*laststart) ==' ') || ((*laststart)=='\t'))
-               {
-                   laststart++;
-               }
-
-               res = addCancelItem(cxn, laststart, 
-                                   str - laststart, 
-                                   control_header, 
-                                   control_header_end - control_header,
-                                   NULL, must);
-               if (res!=RET_OK) return res;
-               
-               laststart = str+1;
-           }
-
-           str++;
-       }
-       
-       if (laststart<str)
-       {
-
-           res = addCancelItem(cxn, laststart, str - laststart, 
-                               control_header,
-                               control_header_end - control_header, 
-                               art, must);
-           if (res!=RET_OK) return res;
-       }
-       break;
-    }
-    default:
-       /* huh?!? */
-       d_printf(0, "%s:%d internal error in addControlMsg()\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-    }
-    return RET_FAIL;
-}
-
-/*
- * Show msg handling statistics
- */
-
-static void show_stats(connection_t *cxn)
-{   
-    d_printf(0, "%s:%d\n",hostPeerName (cxn->myHost), cxn->ident);
-    d_printf(0, "  imap queue = %d lmtp queue = %d\n",
-            QueueItems(&(cxn->imap_controlMsg_q)),
-            QueueItems(&(cxn->lmtp_todeliver_q)));
-    d_printf(0,"  imap state = %s\n", imap_stateToString(cxn->imap_state));
-    d_printf(0,"  lmtp state = %s\n", lmtp_stateToString(cxn->lmtp_state));
-    d_printf(0,"  delivered:  yes: %d no: %d\n",
-            cxn->lmtp_succeeded, 
-            cxn->lmtp_failed);
-    d_printf(0,"  cancel:     yes: %d no: %d\n",
-            cxn->cancel_succeeded, cxn->cancel_failed);
-    d_printf(0,"  create:     yes: %d no: %d\n",
-            cxn->create_succeeded, cxn->create_failed);
-    d_printf(0,"  remove:     yes: %d no: %d\n",
-            cxn->remove_succeeded, cxn->remove_failed);
-}
-
-/**************************** SASL helper functions ******************************/
-
-#ifdef HAVE_SASL
-/* callback to get userid or authid */
-static int getsimple(void *context __attribute__((unused)),
-                    int id,
-                    const char **result,
-                    unsigned *len)
-{
-  char *username;
-  char *authid;
-
-  if (! result)
-    return SASL_BADPARAM;
-
-
-  switch (id) {
-  case SASL_CB_GETREALM:
-      *result = deliver_realm;
-      if (len)
-         *len = deliver_realm ? strlen(deliver_realm) : 0;
-      break;
-
-  case SASL_CB_USER:
-      *result = deliver_username;
-      if (len)
-         *len = deliver_username ? strlen(deliver_username) : 0;
-    break;
-  case SASL_CB_AUTHNAME:
-    authid=deliver_authname;
-    *result = authid;
-    if (len)
-      *len = authid ? strlen(authid) : 0;
-      break;
-  case SASL_CB_LANGUAGE:
-    *result = NULL;
-    if (len)
-      *len = 0;
-    break;
-  default:
-    return SASL_BADPARAM;
-  }
-  return SASL_OK;
-}
-
-/* callback to get password */
-static int
-getsecret(sasl_conn_t *conn,
-         void *context __attribute__((unused)),
-         int id,
-         sasl_secret_t **psecret)
-{
-  size_t passlen;
-
-  if (! conn || ! psecret || id != SASL_CB_PASS)
-    return SASL_BADPARAM;
-
-  if (deliver_password==NULL)
-  {
-      d_printf(0,"SASL requested a password but I don't have one\n");
-      return SASL_FAIL;
-  }
-
-  passlen = strlen(deliver_password);
-  *psecret = xmalloc(sizeof(sasl_secret_t) + passlen + 1);
-  if (! *psecret)
-    return SASL_FAIL;
-
-  strlcpy((*psecret)->data, deliver_password, passlen + 1);
-  (*psecret)->len = passlen;
-
-  return SASL_OK;
-}
-
-
-/* callbacks we support */
-static sasl_callback_t saslcallbacks[] = {
-  {
-    SASL_CB_GETREALM, &getsimple, NULL
-  }, {
-    SASL_CB_USER, &getsimple, NULL
-  }, {
-    SASL_CB_AUTHNAME, &getsimple, NULL
-  }, {
-    SASL_CB_PASS, &getsecret, NULL    
-  }, {
-    SASL_CB_LIST_END, NULL, NULL
-  }
-};
-
-static sasl_security_properties_t *make_secprops(int min,int max)
-{
-  sasl_security_properties_t *ret=
-    xmalloc(sizeof(sasl_security_properties_t));
-
-  ret->maxbufsize=1024;
-  ret->min_ssf=min;
-  ret->max_ssf=max;
-
-  ret->security_flags=0;
-  ret->property_names=NULL;
-  ret->property_values=NULL;
-
-  return ret;
-}
-
-#ifndef NI_WITHSCOPEID
-#define NI_WITHSCOPEID 0
-#endif
-#ifndef NI_MAXHOST
-#define NI_MAXHOST     1025
-#endif
-#ifndef NI_MAXSERV
-#define NI_MAXSERV     32
-#endif
-
-static int iptostring(const struct sockaddr *addr, socklen_t addrlen,
-                    char *out, unsigned outlen) {
-    char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
-    
-    if(!addr || !out) return SASL_BADPARAM;
-
-    getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
-               NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV);
-
-    if(outlen < strlen(hbuf) + strlen(pbuf) + 2)
-       return SASL_BUFOVER;
-
-    snprintf(out, outlen, "%s;%s", hbuf, pbuf);
-
-    return SASL_OK;
-}
-
-static conn_ret SetSASLProperties(sasl_conn_t *conn, int sock, int minssf, int maxssf)
-{
-  int saslresult;
-  sasl_security_properties_t *secprops=NULL;
-  int addrsize=sizeof(struct sockaddr_in);
-  char localip[60], remoteip[60];
-  struct sockaddr_in saddr_l;
-  struct sockaddr_in saddr_r;
-
-  /* create a security structure and give it to sasl */
-  secprops = make_secprops(minssf, maxssf);
-  if (secprops != NULL)
-  {
-    sasl_setprop(conn, SASL_SEC_PROPS, secprops);
-    free(secprops);
-  }
-
-  if (getpeername(sock,(struct sockaddr *)&saddr_r,&addrsize)!=0)
-    return RET_FAIL;
-
-  if (iptostring((struct sockaddr *)&saddr_r, sizeof(struct sockaddr_in),
-               remoteip, sizeof(remoteip)))
-    return RET_FAIL;
-
-  if (sasl_setprop(conn, SASL_IPREMOTEPORT, remoteip)!=SASL_OK)
-    return RET_FAIL;
-  
-  addrsize=sizeof(struct sockaddr_in);
-  if (getsockname(sock,(struct sockaddr *) &saddr_l,&addrsize)!=0)
-    return RET_FAIL;
-
-  if (iptostring((struct sockaddr *)&saddr_l, sizeof(struct sockaddr_in),
-                localip, sizeof(localip)))
-    return RET_FAIL;
-    
-  if (sasl_setprop(conn, SASL_IPLOCALPORT, localip)!=SASL_OK)
-    return RET_FAIL;
-  
-  return RET_OK;
-}
-#endif /* HAVE_SASL */
-
-/************************** END SASL helper functions ******************************/
-
-/************************* Startup functions **********************************/
-
-static conn_ret Initialize(connection_t *cxn, int respTimeout)
-{
-#ifdef HAVE_SASL
-    conn_ret saslresult;
-#endif /* HAVE_SASL */
-
-    d_printf(1,"%s:%d initializing....\n",
-            hostPeerName (cxn->myHost), cxn->ident);
-
-#ifdef HAVE_SASL
-    /* only call sasl_client_init() once */
-    if (initialized_sasl == 0)
-    {
-       /* Initialize SASL */
-       saslresult=sasl_client_init(saslcallbacks);
-       
-       if (saslresult!=SASL_OK)
-       {
-           d_printf(0,
-                    "%s:%d Error initializing SASL (sasl_client_init) (%s)\n",
-                    hostPeerName (cxn->myHost), cxn->ident,
-                    sasl_errstring(saslresult, NULL, NULL));
-           return RET_FAIL;
-       } else {
-           initialized_sasl = 1;
-       }
-    }
-#endif /* HAVE_SASL */
-
-    cxn->lmtp_rBuffer = newBuffer(4096);
-    if (cxn->lmtp_rBuffer == NULL)
-    {
-       d_printf(0, "%s:%d Failure allocating buffer for lmtp_rBuffer\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-    bufferAddNullByte(cxn->lmtp_rBuffer);
-
-
-    cxn->imap_rBuffer = newBuffer(4096);
-    if (cxn->imap_rBuffer == NULL)
-    {
-       d_printf(0, "%s:%d Failure allocating buffer for imap_rBuffer \n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-    bufferAddNullByte(cxn->imap_rBuffer);
-
-    /* Initialize timeouts */
-    cxn->lmtp_writeTimeout = respTimeout;
-    cxn->lmtp_readTimeout = respTimeout;
-    cxn->imap_writeTimeout = respTimeout;
-    cxn->imap_readTimeout = respTimeout;
-    cxn->lmtp_sleepTimerId = 0 ;
-    cxn->lmtp_sleepTimeout = init_reconnect_period ;
-    cxn->imap_sleepTimerId = 0 ;
-    cxn->imap_sleepTimeout = init_reconnect_period ;
-
-    cxn->dosomethingTimeout = DOSOMETHING_TIMEOUT;
-
-    /* set up the write timer. */
-    clearTimer (cxn->dosomethingTimerId) ;
-
-    if (cxn->dosomethingTimeout > 0)
-       cxn->dosomethingTimerId = prepareSleep (dosomethingTimeoutCbk, 
-                                               cxn->dosomethingTimeout, cxn);
-
-
-
-    return RET_OK;
-}
-
-
-/* initialize the network */
-static conn_ret init_net(char *serverFQDN, 
-                        int port,
-                        int *sock)
-{
-  struct sockaddr_in addr;
-  struct hostent *hp;
-
-  if ((hp = gethostbyname(serverFQDN)) == NULL) {
-      d_printf(0, "gethostbyname(): %s\n", strerror(errno));
-    return RET_FAIL;
-  }
-
-  if (( (*sock) = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-      d_printf(0, "socket(): %s\n", strerror(errno));
-      return RET_FAIL; 
-  }
-
-  addr.sin_family = AF_INET;
-  memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
-  addr.sin_port = htons(port);
-
-  if (connect( (*sock), (struct sockaddr *) &addr, sizeof (addr)) < 0) {
-      d_printf(0,"connect(): %s\n",
-              strerror(errno));
-      return RET_FAIL;
-  }
-
-  return RET_OK;
-}
-
-
-
-static conn_ret SetupLMTPConnection(connection_t *cxn,
-                                   char *serverName,
-                                   int port)
-{
-#ifdef HAVE_SASL
-    int saslresult;
-#endif /* HAVE_SASL */
-    conn_ret result;
-
-    cxn->lmtp_port = port;
-
-    if (serverName==NULL)
-    {
-       d_printf(0, "%s:%d serverName is null\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;        
-    }
-
-#ifdef HAVE_SASL
-    /* Free the SASL connection if we already had one */
-    if (cxn->saslconn_lmtp!=NULL)
-    {
-       sasl_dispose(&cxn->saslconn_lmtp);
-    }
-
-    /* Start SASL */
-    saslresult=sasl_client_new("lmtp",
-                              serverName,
-                              NULL,
-                              NULL,
-                              NULL,
-                              0,
-                              &cxn->saslconn_lmtp);
-
-    if (saslresult != SASL_OK)
-    {
-
-       d_printf(0, "%s:%d:LMTP Error creating a new SASL connection (%s)\n",
-                hostPeerName (cxn->myHost), cxn->ident,
-                sasl_errstring(saslresult,NULL,NULL));
-       return RET_FAIL;
-    }
-#endif /* HAVE_SASL */
-
-    /* Connect the Socket */
-    result = init_net(serverName,
-                     LMTP_PORT, /*port,*/
-                     &(cxn->sockfd_lmtp));
-   
-    if (result != RET_OK)
-    {
-       d_printf(0, "%s:%d unable to connect to lmtp host\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-
-    if (cxn->lmtp_respBuffer) free(cxn->lmtp_respBuffer);
-    cxn->lmtp_respBuffer = xmalloc (4096);
-    cxn->lmtp_respBuffer[0]='\0';
-
-    /* Free if we had an existing one */
-    if (cxn->lmtp_endpoint != NULL)
-    {
-       delEndPoint(cxn->lmtp_endpoint);
-       cxn->lmtp_endpoint = NULL;
-    }
-
-    cxn->lmtp_endpoint = newEndPoint(cxn->sockfd_lmtp);
-    if (cxn->lmtp_endpoint == NULL)
-    {
-       d_printf(0, "%s:%d:LMTP failure creating endpoint\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-
-#ifdef HAVE_SASL
-    /* Set the SASL properties */
-    result = SetSASLProperties(cxn->saslconn_lmtp, cxn->sockfd_lmtp, 
-                              0, 0);
-    
-    if (result != RET_OK)
-    {
-       d_printf(0,"%s:%d:LMTP error setting SASL properties\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-#endif /* HAVE_SASL */
-
-
-    return RET_OK;
-}
-
-static conn_ret SetupIMAPConnection(connection_t *cxn,
-                                   char *serverName,
-                                   int port)
-{
-#ifdef HAVE_SASL
-    int saslresult;
-#endif /* HAVE_SASL */
-    conn_ret result;
-
-    cxn->imap_port = port;
-
-    if (serverName==NULL)
-    {
-       d_printf(0,"%s:%d:IMAP Servername is null",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;        
-    }
-
-#ifdef HAVE_SASL
-    /* Free the SASL connection if we already had one */
-    if (cxn->imap_saslconn!=NULL)
-    {
-       sasl_dispose(&cxn->imap_saslconn);
-    }
-
-    /* Start SASL */
-    saslresult=sasl_client_new("imap",
-                              serverName,
-                              NULL,
-                              NULL,
-                              NULL,
-                              0,
-                              &cxn->imap_saslconn);
-
-    if (saslresult != SASL_OK)
-    {
-       d_printf(0,"%s:%d:IMAP Error creating a new SASL connection (%s)",
-                hostPeerName (cxn->myHost), cxn->ident,
-                sasl_errstring(saslresult,NULL,NULL));
-       return RET_FAIL;
-    }
-#endif /* HAVE_SASL */
-
-    /* Connect the Socket */
-    result = init_net(serverName,
-                     port,
-                     &(cxn->imap_sockfd));
-   
-    if (result != RET_OK)
-    {
-       d_printf(0,"%s:%d:IMAP Unable to start network connection for IMAP",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-
-    if (cxn->imap_respBuffer) free(cxn->imap_respBuffer);
-    cxn->imap_respBuffer = xmalloc (4096);
-    cxn->imap_respBuffer[0]='\0';
-
-    /* Free if we had an existing one */
-    if (cxn->imap_endpoint != NULL)
-    {
-       delEndPoint(cxn->imap_endpoint);
-       cxn->imap_endpoint = NULL;
-    }
-
-    cxn->imap_endpoint = newEndPoint(cxn->imap_sockfd);
-    if (cxn->imap_endpoint == NULL)
-    {
-       d_printf(0,"%s:%d:IMAP Failure creating imap endpoint\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return RET_FAIL;
-    }
-
-#ifdef HAVE_SASL
-    /* Set the SASL properties */
-    result = SetSASLProperties(cxn->imap_saslconn, cxn->imap_sockfd, 
-                              0, 0);    
-    if (result != RET_OK)
-    {
-       d_printf(0,"%s:%d:IMAP Error setting sasl properties",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return result;
-    }
-#endif /* HAVE_SASL */
-
-
-    return RET_OK;
-}
-
-/************************* END Startup functions **********************************/
-
-/* Return the response code for this line
-   -1 if it doesn't seem to have one
-*/
-static int ask_code(char *str)
-{
-    int ret = 0;
-    
-    if (str==NULL) return -1;
-
-    if (strlen(str) < 3) return -1;
-
-    /* check to make sure 0-2 are digits */
-    if ((isdigit((int) str[0])==0) ||
-       (isdigit((int) str[1])==0) ||
-       (isdigit((int) str[2])==0))
-    {
-       d_printf(0,
-                "Parse error: response does not begin with a code [%s]\n",
-                str);
-       return -1;
-    }
-
-
-    ret = ((str[0]-'0')*100)+
-         ((str[1]-'0')*10)+
-         (str[2]-'0');
-    
-    return ret;
-}
-
-/* is this a continuation or not?
-   220-fdfsd is        (1)
-   220 fdsfs is not    (0)
- */
-
-static int ask_keepgoing(char *str)
-{
-    if (str==NULL) return 0;
-    if (strlen(str) < 4) return 0;
-
-    if (str[3]=='-') return 1;
-
-    return 0;
-}
-
-
-static conn_ret lmtp_listenintro(connection_t *cxn)
-{
-    Buffer *readBuffers;
-
-    /* set up to receive */
-    readBuffers = makeBufferArray (bufferTakeRef (cxn->lmtp_rBuffer), NULL) ;
-    prepareRead(cxn->lmtp_endpoint, readBuffers, lmtp_readCB, cxn, 5);    
-
-    cxn->lmtp_state = LMTP_READING_INTRO;
-
-    return RET_OK;
-}
-
-
-
-/************************** IMAP functions ***********************/
-
-static conn_ret imap_Connect(connection_t *cxn)
-{
-    conn_ret result;
-
-    ASSERT(cxn->imap_sleepTimerId == 0);
-
-    /* make the IMAP connection */
-    result = SetupIMAPConnection(cxn,
-                                cxn->ServerName,
-                                IMAP_PORT); 
-
-    /* Listen to the intro and start the authenticating process */
-    result = imap_listenintro(cxn);
-
-    return result;
-}
-
-/*
- * This is called when the data write timeout for the remote
- * goes off. We tear down the connection and notify our host.
- */
-static void imap_writeTimeoutCbk (TimeoutId id UNUSED, void *data)
-{
-  connection_t *cxn = (Connection) data ;
-  const char *peerName ;
-
-  peerName = hostPeerName (cxn->myHost) ;
-
-  syslog (LOG_WARNING, "timeout for %s", peerName);
-  d_printf(0, "%s: shutting down non-responsive IMAP connection (%s)\n",
-          hostPeerName (cxn->myHost), 
-          imap_stateToString(cxn->imap_state));
-
-  cxnLogStats (cxn,true) ;
-
-  imap_Disconnect(cxn);
-}
-
-/*
- * This is called when the timeout for the reponse from the remote
- * goes off. We tear down the connection and notify our host.
- */
-static void imap_readTimeoutCbk (TimeoutId id, void *data)
-{
-  Connection cxn = (Connection) data ;
-  const char *peerName ;
-
-  ASSERT (id == cxn->imap_readBlockedTimerId) ;
-
-  peerName = hostPeerName (cxn->myHost) ;
-
-  warn ("%s:%d cxnsleep non-responsive connection", peerName, cxn->ident) ;
-  d_printf(0, "%s:%d shutting down non-responsive IMAP connection (%s)\n",
-          hostPeerName (cxn->myHost), cxn->ident,
-          imap_stateToString(cxn->imap_state));
-
-  cxnLogStats (cxn,true);
-
-  if (cxn->imap_state == IMAP_DISCONNECTED)
-    {
-      imap_Disconnect(cxn);
-      lmtp_Disconnect(cxn);
-      delConnection (cxn) ;
-    }
-  else {
-      imap_Disconnect(cxn);
-  }      
-}
-
-/*
- * Called by the EndPoint class when the timer goes off
- */
-static void imap_reopenTimeoutCbk (TimeoutId id, void *data)
-{
-  Connection cxn = (Connection) data ;
-
-  ASSERT (id == cxn->imap_sleepTimerId) ;
-
-  cxn->imap_sleepTimerId = 0 ;
-
-  d_printf(1,"%s:%d:IMAP Reopen timer rang. Try to make new connection now\n",
-           hostPeerName (cxn->myHost), cxn->ident) ;
-  
-  if (cxn->imap_state != IMAP_DISCONNECTED)
-    {
-      warn ("%s:%d cxnsleep connection in bad state: %s",
-            hostPeerName (cxn->myHost), cxn->ident,
-            imap_stateToString (cxn->imap_state)) ;
-    }
-  else {
-      if (imap_Connect(cxn) != RET_OK)
-         prepareReopenCbk(cxn, 0);
-  }
-}
-
-static void imap_Disconnect(connection_t *cxn)
-{
-    clearTimer (cxn->imap_sleepTimerId) ;
-    cxn->imap_sleepTimerId = 0;
-    clearTimer (cxn->imap_readBlockedTimerId) ;
-    clearTimer (cxn->imap_writeBlockedTimerId) ;
-
-    DeferAllArticles(cxn, &(cxn->imap_controlMsg_q)) ;      /* give any articles back to Host */
-
-    cxn->imap_state = IMAP_DISCONNECTED;
-
-    cxn->imap_disconnects++;
-
-    cxn->imap_respBuffer[0]='\0';
-
-    if (cxn->issue_quit == 0)
-       prepareReopenCbk(cxn,0);
-
-    DeleteIfDisconnected(cxn);
-}
-
-/************************** END IMAP functions ***********************/
-
-/************************ LMTP functions **************************/
-
-/*
- * Create a network lmtp connection
- * and start listening for the intro string
- *
- */
-
-static conn_ret lmtp_Connect(connection_t *cxn)
-{
-    conn_ret result;
-
-    ASSERT(cxn->lmtp_sleepTimerId == 0);
-
-    /* make the LMTP connection */
-    result = SetupLMTPConnection(cxn,
-                                cxn->ServerName,
-                                LMTP_PORT);
-
-    if (result!=RET_OK) return result;
-
-    /* Listen to the intro */
-    result = lmtp_listenintro(cxn);
-
-    return result;
-}
-
-
-
-static void lmtp_Disconnect(connection_t *cxn)
-{
-    clearTimer (cxn->lmtp_sleepTimerId) ;
-    cxn->lmtp_sleepTimerId = 0;
-    clearTimer (cxn->lmtp_readBlockedTimerId) ;
-    clearTimer (cxn->lmtp_writeBlockedTimerId) ;
-
-    /* give any articles back to Host */
-    DeferAllArticles(cxn, &(cxn->lmtp_todeliver_q)) ;      
-
-    cxn->lmtp_state = LMTP_DISCONNECTED;
-
-    cxn->lmtp_disconnects++;
-
-    cxn->lmtp_respBuffer[0]='\0';
-
-    if (cxn->issue_quit == 0)
-       prepareReopenCbk(cxn,1);
-
-    DeleteIfDisconnected(cxn);
-}
-
-
-
-/*
- * Called by the EndPoint class when the timer goes off
- */
-static void lmtp_reopenTimeoutCbk (TimeoutId id, void *data)
-{
-  Connection cxn = (Connection) data ;
-
-  ASSERT (id == cxn->lmtp_sleepTimerId) ;
-
-  cxn->lmtp_sleepTimerId = 0 ;
-
-  d_printf(1,"%s:%d:LMTP Reopen timer rang. Try to make new connection now\n",
-           hostPeerName (cxn->myHost), cxn->ident) ;
-        
-  if (cxn->lmtp_state != LMTP_DISCONNECTED)
-    {
-      warn ("%s:%d cxnsleep connection in bad state: %s",
-            hostPeerName (cxn->myHost), cxn->ident,
-            lmtp_stateToString (cxn->lmtp_state)) ;
-    }
-  else {
-      if (lmtp_Connect(cxn) != RET_OK)
-         prepareReopenCbk(cxn, 1);
-  }
-}
-
-/*
- * Set up the callback used when the Connection is sleeping (i.e. will try
- * to reopen the connection).
- *
- * type (0 = imap, 1 = lmtp)
- */
-static void prepareReopenCbk (Connection cxn, int type)
-{
-    /* xxx check state */
-
-
-
-    if (type == 0) {
-
-       cxn->imap_sleepTimerId = prepareSleep (imap_reopenTimeoutCbk, 
-                                              cxn->imap_sleepTimeout, cxn) ;
-       d_printf (1,"%s:%d IMAP connection error\n"
-                 "  will try to reconnect in %d seconds\n",
-                 hostPeerName (cxn->myHost), cxn->ident, 
-                 cxn->imap_sleepTimeout) ;
-    } else {
-       cxn->lmtp_sleepTimerId = prepareSleep (lmtp_reopenTimeoutCbk, 
-                                              cxn->lmtp_sleepTimeout, cxn) ;
-       d_printf (1,"%s:%d:LMTP connection error\n"
-                 "will try to reconnect in %d seconds\n",
-                 hostPeerName (cxn->myHost), cxn->ident, 
-                 cxn->lmtp_sleepTimeout) ;
-    }
-
-    /* bump the sleep timer amount each time to wait longer and longer. Gets
-       reset in resetConnection() */
-    if (type == 0) {
-       cxn->imap_sleepTimeout *= 2 ;
-       if (cxn->imap_sleepTimeout > max_reconnect_period)
-           cxn->imap_sleepTimeout = max_reconnect_period ;
-    } else {
-       cxn->lmtp_sleepTimeout *= 2 ;
-       if (cxn->lmtp_sleepTimeout > max_reconnect_period)
-           cxn->lmtp_sleepTimeout = max_reconnect_period ;
-    }
-}
-
-/*
- * This is called when the timeout for the reponse from the remote
- * goes off. We tear down the connection and notify our host.
- */
-static void lmtp_readTimeoutCbk (TimeoutId id, void *data)
-{
-  Connection cxn = (Connection) data ;
-  const char *peerName ;
-
-  ASSERT (id == cxn->lmtp_readBlockedTimerId) ;
-
-  peerName = hostPeerName (cxn->myHost) ;
-
-  warn ("%s:%d cxnsleep non-responsive connection", peerName, cxn->ident) ;
-  d_printf(0,"%s:%d shutting down non-responsive LMTP connection (%s)\n",
-           hostPeerName (cxn->myHost), cxn->ident,
-          lmtp_stateToString(cxn->lmtp_state));
-
-  cxnLogStats (cxn,true) ;
-
-  if (cxn->lmtp_state == LMTP_DISCONNECTED) {
-      imap_Disconnect(cxn);
-      lmtp_Disconnect(cxn);
-      delConnection (cxn) ;
-  } else {
-      lmtp_Disconnect(cxn);
-  }      
-}
-
-
-
-/*
- * This is called when the data write timeout for the remote
- * goes off. We tear down the connection and notify our host.
- */
-static void lmtp_writeTimeoutCbk (TimeoutId id UNUSED, void *data)
-{
-    connection_t *cxn = (Connection) data ;
-    const char *peerName ;
-
-    peerName = hostPeerName (cxn->myHost) ;
-
-    syslog (LOG_WARNING, "timeout for %s", peerName);
-    d_printf(0, "%s:%d shutting down non-responsive LMTP connection (%s)\n",
-            hostPeerName (cxn->myHost), cxn->ident,
-            lmtp_stateToString(cxn->lmtp_state)) ;
-
-    cxnLogStats (cxn,true);
-
-    lmtp_Disconnect(cxn);
-}
-
-/************************ END LMTP functions **************************/
-
-/************************** LMTP write functions ********************/
-
-static conn_ret lmtp_noop(connection_t *cxn)
-{
-    int result;
-    char *p;
-
-    p = xstrdup("NOOP\r\n");
-    result = WriteToWire_lmtpstr(cxn, p, strlen(p));
-    if (result!=RET_OK) return result;
-
-    cxn->lmtp_state = LMTP_WRITING_NOOP;
-
-    return RET_OK;
-}
-
-static conn_ret lmtp_IssueQuit(connection_t *cxn)
-{
-    int result;
-    char *p;
-
-    p = xstrdup("QUIT\r\n");
-    result = WriteToWire_lmtpstr(cxn, p, strlen(p));
-    if (result!=RET_OK) return result;
-
-    cxn->lmtp_state = LMTP_WRITING_QUIT;
-
-    return RET_OK;
-}
-
-static conn_ret lmtp_getcapabilities(connection_t *cxn)
-{
-    int result;
-    char *p;
-
-    if (cxn->lmtp_capabilities != NULL)
-    {
-       if (cxn->lmtp_capabilities->saslmechs) {
-           free( cxn->lmtp_capabilities->saslmechs);
-       }
-       free( cxn->lmtp_capabilities );
-       cxn->lmtp_capabilities = NULL;
-    }
-
-    cxn->lmtp_capabilities = xcalloc (1, sizeof(lmtp_capabilities_t));
-    cxn->lmtp_capabilities->saslmechs = NULL;
-
-#ifdef SMTPMODE
-    p = concat("EHLO ", hostname, "\r\n", (char *) 0);
-#else
-    p = concat("LHLO ", hostname, "\r\n", (char *) 0);
-#endif /* SMTPMODE */
-
-    result = WriteToWire_lmtpstr(cxn, p, strlen(p));
-    if (result!=RET_OK) return result;
-
-    cxn->lmtp_state = LMTP_WRITING_LHLO;
-
-    return RET_OK;    
-}
-
-#ifdef HAVE_SASL
-static conn_ret lmtp_authenticate(connection_t *cxn)
-{
-    int saslresult;
-    
-    const char *mechusing;
-    const char *out;
-    unsigned int outlen;
-    char *inbase64;
-    int inbase64len;
-    int status;
-    int result;
-
-    char *p;
-
-    sasl_interact_t *client_interact=NULL;
-
-
-    saslresult=sasl_client_start(cxn->saslconn_lmtp, 
-                                cxn->lmtp_capabilities->saslmechs,
-                                &client_interact,
-                                &out, &outlen,
-                                &mechusing);
-
-
-
-    if ((saslresult != SASL_OK) && 
-       (saslresult != SASL_CONTINUE)) {
-
-       d_printf(0,"%s:%d:LMTP Error calling sasl_client_start (%s)\n",
-                hostPeerName (cxn->myHost), cxn->ident,
-                sasl_errstring(saslresult, NULL, NULL));
-       return RET_FAIL;
-    }
-
-    d_printf(1,"%s:%d:LMTP Decided to try to authenticate with SASL mechanism=%s\n",           
-            hostPeerName (cxn->myHost), cxn->ident,mechusing);
-
-    if (!out)
-    {
-       /* no initial client response */
-        p = concat("AUTH ", mechusing, "\r\n", (char *) 0);
-    } else if (!outlen) {
-       /* empty initial client response */
-        p = concat("AUTH ", mechusing, " =\r\n", (char *) 0);
-    } else {
-       /* initial client response - convert to base64 */
-       inbase64 = xmalloc(outlen*2+10);
-
-       saslresult = sasl_encode64(out, outlen,
-                                  inbase64, outlen*2+10,
-                                   (unsigned *) &inbase64len);
-       if (saslresult != SASL_OK) return RET_FAIL;
-        p = concat("AUTH ", mechusing, " ", inbase64, "\r\n", (char *) 0);
-        free(inbase64);
-    }
-
-    result = WriteToWire_lmtpstr(cxn, p, strlen(p));
-
-    cxn->lmtp_state = LMTP_WRITING_STARTAUTH;
-
-    return RET_OK;
-}
-
-static imt_stat lmtp_getauthline(char *str, char **line, int *linelen)
-{
-  char buf[4096];
-  int saslresult;
-  int response_code = -1;
-  
-  response_code = ask_code(str);
-
-  if (response_code == 334) {
-      
-      /* continue */
-
-  } else if (response_code == 235) {
-
-      /* woohoo! authentication complete */
-      return STAT_OK;
-
-  } else {
-      /* failure of some sort */
-      d_printf(0,"?:?:LMTP Authentication failure (%d) [%s]\n",
-              response_code,str);
-      return STAT_NO;
-  }
-
-  str += 4; /* jump past the "334 " */
-
-  *line = xmalloc(strlen(str)+30);
-  if ((*line)==NULL) {
-      return STAT_NO;
-  }
-
-  /* decode this line */      
-  saslresult = sasl_decode64(str, strlen(str), 
-                            *line, strlen(str)+1, (unsigned *) linelen);
-  if (saslresult != SASL_OK) {
-      d_printf(0,"?:?:LMTP base64 decoding error\n");
-      return STAT_NO;
-  }
-
-  return STAT_CONT;
-}
-#endif /* HAVE_SASL */
-
-static void lmtp_writeCB (EndPoint e UNUSED, IoStatus i UNUSED, Buffer *b,
-       void *d)
-{
-    connection_t *cxn = (connection_t *) d;
-    Buffer *readBuffers;
-
-    clearTimer (cxn->lmtp_writeBlockedTimerId) ;
-
-    /* Free the string that was written */
-    freeBufferArray (b);
-    if (cxn->lmtp_tofree_str!=NULL)
-    {
-       free(cxn->lmtp_tofree_str);
-       cxn->lmtp_tofree_str=NULL;
-    }
-
-    /* set up to receive */
-    readBuffers = makeBufferArray (bufferTakeRef (cxn->lmtp_rBuffer), NULL) ;
-    prepareRead(cxn->lmtp_endpoint, readBuffers, lmtp_readCB, cxn, 5);
-
-   /* set up the response timer. */
-    clearTimer (cxn->lmtp_readBlockedTimerId) ;
-
-    if (cxn->lmtp_readTimeout > 0)
-       cxn->lmtp_readBlockedTimerId = prepareSleep (lmtp_readTimeoutCbk, 
-                                                    cxn->lmtp_readTimeout, cxn) ;
-
-
-    switch (cxn->lmtp_state)
-       {
-           
-       case LMTP_WRITING_LHLO:
-           cxn->lmtp_state = LMTP_READING_LHLO;
-           break;
-
-       case LMTP_WRITING_STARTAUTH:
-       case LMTP_WRITING_STEPAUTH:
-
-           cxn->lmtp_state = LMTP_READING_STEPAUTH;
-
-           break;
-
-       case LMTP_WRITING_UPTODATA:
-           /* expect result to rset */
-           cxn->lmtp_state = LMTP_READING_RSET;
-           break;
-
-       case LMTP_WRITING_CONTENTS:
-           /* so we sent the whole DATA command
-              let's see what the server responded */
-
-           cxn->lmtp_state = LMTP_READING_CONTENTS;
-
-           break;
-
-       case LMTP_WRITING_NOOP:
-           cxn->lmtp_state = LMTP_READING_NOOP;
-           break;
-
-       case LMTP_WRITING_QUIT:
-           cxn->lmtp_state = LMTP_READING_QUIT;
-           break;
-
-       default:
-
-           d_printf(0,"%s:%d:LMTP Unknown state. Internal error\n",
-                    hostPeerName (cxn->myHost), cxn->ident) ;
-
-           break;
-       }
-}
-
-/************************** END LMTP write functions ********************/
-
-/************************** IMAP sending functions ************************/
-
-
-static void imap_writeCB (EndPoint e UNUSED, IoStatus i UNUSED, Buffer *b,
-       void *d)
-{
-    connection_t *cxn = (connection_t *) d;
-    Buffer *readBuffers;
-
-    clearTimer (cxn->imap_writeBlockedTimerId) ;
-
-    /* free the string we just wrote out */
-    freeBufferArray (b);
-    if (cxn->imap_tofree_str!=NULL)
-    {
-       free(cxn->imap_tofree_str);
-       cxn->imap_tofree_str=NULL;
-    }
-
-    /* set up to receive */
-    readBuffers = makeBufferArray (bufferTakeRef (cxn->imap_rBuffer), NULL) ;
-    prepareRead(cxn->imap_endpoint, readBuffers, imap_readCB, cxn, 5);
-
-    /* set up the response timer. */
-    clearTimer (cxn->imap_readBlockedTimerId) ;
-
-    if (cxn->imap_readTimeout > 0)
-       cxn->imap_readBlockedTimerId = prepareSleep(imap_readTimeoutCbk, 
-                                                   cxn->imap_readTimeout, 
-                                                   cxn);
-
-    switch (cxn->imap_state) {
-    case IMAP_WRITING_CAPABILITY:
-       cxn->imap_state = IMAP_READING_CAPABILITY;
-       break;
-
-    case IMAP_WRITING_STEPAUTH:
-    case IMAP_WRITING_STARTAUTH:
-       cxn->imap_state = IMAP_READING_STEPAUTH;
-       break;
-
-    case IMAP_WRITING_CREATE:
-       cxn->imap_state = IMAP_READING_CREATE;
-       break;
-
-    case IMAP_WRITING_DELETE:
-       cxn->imap_state = IMAP_READING_DELETE;
-       break;
-
-    case IMAP_WRITING_SELECT:
-       cxn->imap_state = IMAP_READING_SELECT;
-       break;
-
-    case IMAP_WRITING_SEARCH:
-       cxn->imap_state = IMAP_READING_SEARCH;
-       break;
-
-    case IMAP_WRITING_STORE:
-       cxn->imap_state = IMAP_READING_STORE;
-       break;
-
-    case IMAP_WRITING_CLOSE:
-       cxn->imap_state = IMAP_READING_CLOSE;
-       break;
-
-    case IMAP_WRITING_NOOP:
-       cxn->imap_state = IMAP_READING_NOOP;
-       break;
-
-    case IMAP_WRITING_QUIT:
-       cxn->imap_state = IMAP_READING_QUIT;
-       break;
-
-    default:
-       d_printf(0,"%s:%d:IMAP invalid connection state\n",
-                hostPeerName (cxn->myHost), cxn->ident) ;
-       imap_Disconnect(cxn);
-       break;
-    }
-}
-
-/*
- * Tag is already allocated
- */
-
-static void imap_GetTag(connection_t *cxn)
-{
-    sprintf(cxn->imap_currentTag,"%06d",cxn->imap_tag_num);
-    cxn->imap_tag_num++;
-    if (cxn->imap_tag_num >= 999999)
-    {
-       cxn->imap_tag_num = 0;
-    }
-}
-
-#ifdef HAVE_SASL
-static conn_ret imap_sendAuthStep(connection_t *cxn, char *str)
-{
-    conn_ret result;
-    int saslresult;
-    char in[4096];
-    unsigned int inlen;
-    const char *out;
-    unsigned int outlen;
-    char *inbase64;
-    unsigned int inbase64len;
-
-    /* base64 decode it */
-
-    saslresult = sasl_decode64(str, strlen(str), 
-                              in, strlen(str)+1, &inlen);
-    if (saslresult != SASL_OK) {
-       d_printf(0,"%s:%d:IMAP base64 decoding error\n",
-                hostPeerName (cxn->myHost), cxn->ident) ;
-       return RET_FAIL;
-    }
-
-    saslresult=sasl_client_step(cxn->imap_saslconn,
-                               in,
-                               inlen,
-                               NULL,
-                               &out,
-                               &outlen);
-
-    /* check if sasl succeeded */
-    if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) {
-
-       d_printf(0,"%s:%d:IMAP sasl_client_step failed with %s\n",
-                hostPeerName (cxn->myHost), cxn->ident,
-                sasl_errstring(saslresult,NULL,NULL));
-       cxn->imap_state = IMAP_CONNECTED_NOTAUTH;
-       return RET_FAIL;
-    }
-
-    inbase64 = xmalloc(outlen * 2 + 10);
-
-    /* convert to base64 */
-    saslresult = sasl_encode64(out, outlen,
-                              inbase64, outlen*2, (unsigned *) &inbase64len);
-
-    if (saslresult != SASL_OK) return RET_FAIL;
-
-    /* append endline */
-    strlcpy(inbase64 + inbase64len, "\r\n", outlen * 2 + 10 - inbase64len);
-    inbase64len+=2;
-    
-    /* send to server */
-    result = WriteToWire_imapstr(cxn,inbase64, inbase64len);
-    
-    cxn->imap_state = IMAP_WRITING_STEPAUTH;
-
-    return result;
-}
-#endif /* HAVE_SASL */
-
-static conn_ret imap_sendAuthenticate(connection_t *cxn)
-{
-    int result;
-
-    char *p;
-
-#ifdef HAVE_SASL
-    const char *mechusing;
-    char *inbase64;
-    int inbase64len;
-    int saslresult=SASL_NOMECH;
-
-    sasl_interact_t *client_interact=NULL;
-
-    if (cxn->imap_capabilities->saslmechs) {
-       saslresult=sasl_client_start(cxn->imap_saslconn, 
-                                    cxn->imap_capabilities->saslmechs,
-                                    &client_interact,
-                                    NULL, NULL,
-                                    &mechusing);
-    }
-
-
-
-    /* If no mechs try "login" */
-    if (saslresult == SASL_NOMECH)
-    {
-
-#else /* HAVE_SASL */
-
-     { /* always do login */
-
-#endif /* HAVE_SASL */
-       d_printf(1,"%s:%d:IMAP No mechanism found. Trying login method\n",
-                hostPeerName (cxn->myHost), cxn->ident) ;
-
-       if (cxn->imap_capabilities->logindisabled==1)
-       {
-           d_printf(0,"%s:%d:IMAP Login command w/o security layer not allowed on this server\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           return RET_FAIL;
-       }
-
-       if (deliver_authname==NULL)
-       {
-           d_printf(0,"%s:%d:IMAP Unable to log in because can't find a authname\n",
-                    hostPeerName (cxn->myHost), cxn->ident) ;
-           return RET_FAIL;
-       }
-
-       if (deliver_password==NULL)
-       {
-           d_printf(0,"%s:%d:IMAP Unable to log in because can't find a password\n",
-                    hostPeerName (cxn->myHost), cxn->ident) ;
-           return RET_FAIL;
-       }
-
-       imap_GetTag(cxn);
-
-        p = concat(cxn->imap_currentTag, " LOGIN ", deliver_authname, " \"",
-                   deliver_password, "\"\r\n", (char *) 0);
-       
-       result = WriteToWire_imapstr(cxn, p, strlen(p));
-       
-       cxn->imap_state = IMAP_WRITING_STARTAUTH;
-       
-       return RET_OK;       
-    }
-
-#ifdef HAVE_SASL
-    if ((saslresult != SASL_OK) && 
-       (saslresult != SASL_CONTINUE)) {
-
-       d_printf(0,"%s:%d:IMAP Error calling sasl_client_start (%s) mechusing = %s\n",
-                hostPeerName (cxn->myHost), cxn->ident,
-                sasl_errstring(saslresult, NULL, NULL), mechusing);
-       return RET_FAIL;
-    }
-
-    d_printf(1,"%s:%d:IMAP Trying to authenticate to imap with %s mechanism\n",
-            hostPeerName (cxn->myHost), cxn->ident,
-            mechusing);
-
-    imap_GetTag(cxn);
-
-    p = concat(cxn->imap_currentTag, " AUTHENTICATE ", mechusing, "\r\n",
-               (char *) 0);
-    result = WriteToWire_imapstr(cxn, p, strlen(p));
-
-    cxn->imap_state = IMAP_WRITING_STARTAUTH;
-
-    return RET_OK;
-#endif /* HAVE_SASL */
-}
-
-static conn_ret imap_CreateGroup(connection_t *cxn, char *bboard)
-{
-    conn_ret result;
-    char *tosend;
-
-    d_printf(1,"%s:%d:IMAP Ok creating group [%s]\n",
-            hostPeerName (cxn->myHost), cxn->ident,
-            bboard);
-
-    imap_GetTag(cxn);
-
-    tosend = concat(cxn->imap_currentTag, " CREATE ", bboard, "\r\n",
-                    (char *) 0);
-
-    result = WriteToWire_imapstr(cxn, tosend, -1);
-    if (result!=RET_OK) return result;
-    
-    cxn->imap_state = IMAP_WRITING_CREATE;
-    
-    return RET_OK;
-}
-
-static conn_ret imap_DeleteGroup(connection_t *cxn, char *bboard)
-{
-    conn_ret result;
-    char *tosend;
-
-    d_printf(1,"%s:%d:IMAP Ok removing bboard [%s]\n",
-                hostPeerName (cxn->myHost), cxn->ident, bboard);
-
-    imap_GetTag(cxn);
-
-    tosend = concat(cxn->imap_currentTag, " DELETE ", bboard, "\r\n",
-                    (char *) 0);
-    result = WriteToWire_imapstr(cxn, tosend, -1);
-    if (result!=RET_OK) return result;
-
-    cxn->imap_state = IMAP_WRITING_DELETE;
-    
-    return RET_OK;
-}
-
-static conn_ret imap_CancelMsg(connection_t *cxn, char *newsgroup)
-{
-    conn_ret result;
-    char *tosend;
-
-    ASSERT(newsgroup);
-
-    imap_GetTag(cxn);
-
-    /* select mbox */
-    tosend = concat(cxn->imap_currentTag, " SELECT ", newsgroup, "\r\n",
-                    (char *) 0);
-    result = WriteToWire_imapstr(cxn, tosend, -1);
-    if (result != RET_OK) return result;
-
-    cxn->imap_state = IMAP_WRITING_SELECT;
-
-    hostArticleOffered (cxn->myHost, cxn);
-
-    return RET_OK;
-}
-
-static conn_ret imap_sendSearch(connection_t *cxn, char *msgid)
-{
-    conn_ret result;
-    char *tosend;
-
-    ASSERT(msgid);
-
-    imap_GetTag(cxn);
-
-    /* preform search */
-    tosend = concat(cxn->imap_currentTag,
-                    " UID SEARCH header \"Message-ID\" \"", msgid, "\"\r\n",
-                    (char *) 0);
-    result = WriteToWire_imapstr(cxn, tosend, -1);
-    if (result != RET_OK) return result;
-
-    cxn->imap_state = IMAP_WRITING_SEARCH;
-
-    return RET_OK;
-}
-
-static conn_ret imap_sendKill(connection_t *cxn, unsigned uid)
-{
-    conn_ret result;
-    char *tosend;
-    size_t length;
-
-    imap_GetTag(cxn);
-
-    length = 7 + 50 + 20;
-    tosend = xmalloc(length);
-    snprintf(tosend,length,"%s UID STORE %d +FLAGS.SILENT (\\Deleted)\r\n",
-             cxn->imap_currentTag, uid);
-
-    result = WriteToWire_imapstr(cxn, tosend, -1);
-    if (result != RET_OK) return result;
-
-    cxn->imap_state = IMAP_WRITING_STORE;
-
-    return RET_OK;
-}
-
-static conn_ret imap_sendSimple(connection_t *cxn, const char *atom, int st)
-{
-    char *tosend;
-    conn_ret result;
-
-    imap_GetTag(cxn);
-    tosend = concat(cxn->imap_currentTag, " ", atom, "\r\n", (char *) 0);
-
-    result = WriteToWire_imapstr(cxn, tosend, -1);
-    if (result != RET_OK) return result;
-
-    cxn->imap_state = st;
-
-    return RET_OK;
-}
-
-static conn_ret imap_sendClose(connection_t *cxn)
-{
-    return imap_sendSimple(cxn, "CLOSE", IMAP_WRITING_CLOSE);
-}
-
-static conn_ret imap_sendQuit(connection_t *cxn)
-{
-    return imap_sendSimple(cxn, "LOGOUT", IMAP_WRITING_QUIT);
-}
-
-static conn_ret imap_noop(connection_t *cxn)
-{
-    return imap_sendSimple(cxn, "NOOP", IMAP_WRITING_NOOP);
-}
-       
-
-static conn_ret imap_sendCapability(connection_t *cxn)
-{
-    return imap_sendSimple(cxn, "CAPABILITY", IMAP_WRITING_CAPABILITY);
-}
-
-/************************** END IMAP sending functions ************************/
-
-/************************** IMAP reading functions ***************************/
-
-static conn_ret imap_listenintro(connection_t *cxn)
-{
-    Buffer *readBuffers;
-
-    /* set up to receive */
-    readBuffers = makeBufferArray (bufferTakeRef (cxn->imap_rBuffer), NULL) ;
-    prepareRead(cxn->imap_endpoint, readBuffers, imap_readCB, cxn, 5);    
-
-    cxn->imap_state = IMAP_READING_INTRO;
-
-    return RET_OK;
-}
-
-static conn_ret imap_ParseCapability(char *string, imap_capabilities_t **caps)
-{
-    char *str = string;
-    char *start = str;
-    size_t mechlen;
-
-    /* allocate the caps structure if it doesn't already exist */
-    if ( (*caps) == NULL)
-       (*caps) = xcalloc(1, sizeof(imap_capabilities_t));
-
-    while ( (*str) != '\0')
-    {
-
-       while (((*str) != '\0') && ((*str)!=' '))
-       {
-           str++;
-       }
-       
-       if ( (*str) != '\0')
-       {
-           *str = '\0';
-           str++;
-       }
-
-       if ( strcasecmp(start,"IMAP4")==0)
-       {
-           (*caps)->imap4 = 1;
-       } else if (strcasecmp(start,"LOGINDISABLED")==0) {
-           (*caps)->logindisabled = 1;
-       } else if ( strncmp(start, "AUTH=", 5)==0) {
-           
-           if ( (*caps)->saslmechs == NULL)
-           {
-                (*caps)->saslmechs = xstrdup (start + 5);
-           } else {
-                mechlen = strlen((*caps)->saslmechs) + 1;
-                mechlen += strlen(start + 5) + 1;
-               (*caps)->saslmechs = xrealloc((*caps)->saslmechs, mechlen);
-                strlcat((*caps)->saslmechs, " ", mechlen);
-                strlcat((*caps)->saslmechs, start + 5, mechlen);
-           }
-       }
-       
-       start = str;
-          
-    }
-
-    if ((*caps)->saslmechs) {
-       d_printf(1,"?:?:IMAP parsed capabilities: saslmechs = %s\n",
-                (*caps)->saslmechs);
-    }
-
-    return RET_OK;
-}
-
-
-static void imap_readCB (EndPoint e, IoStatus i, Buffer *b, void *d)
-{
-    connection_t *cxn = (connection_t *) d;
-    Buffer *readBuffers ;
-
-    int okno;
-    char *str;
-    char strbuf[4096];
-    char *linestart;
-    conn_ret ret;
-    char *p;
-
-    p = bufferBase(b[0]);
-
-    /* Add what we got to our internal read buffer */
-    bufferAddNullByte (b[0]) ;
-
-    if (i != IoDone) {
-       errno = endPointErrno(e);
-
-       syslog(LOG_ERR, "%s:%d IMAP i/o failed: %m",
-              hostPeerName (cxn->myHost), cxn->ident);
-       freeBufferArray (b);
-       imap_Disconnect(cxn);
-       return;
-    }
-
-    if (strchr (p, '\n') == NULL) {
-       /* partial read. expand buffer and retry */
-       
-       if (expandBuffer (b[0], BUFFER_EXPAND_AMOUNT)==false) {
-           d_printf(0,"%s:%d:IMAP expanding buffer returned false\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           
-           imap_Disconnect(cxn);
-           return;
-       }
-       readBuffers = makeBufferArray (bufferTakeRef (b[0]), NULL) ;
-       
-       if (!prepareRead (e, readBuffers, imap_readCB, cxn, 1)) {
-           imap_Disconnect(cxn);
-       }
-       
-       freeBufferArray (b);
-       return;
-    }
-
-    clearTimer (cxn->imap_readBlockedTimerId) ;
-
-    /* we got something. add to our buffer and free b */
-
-    strcat(cxn->imap_respBuffer, p);
-
-    bufferSetDataSize( b[0], 0);
-
-    freeBufferArray (b);
-
-
-
-    /* goto here to take another step */
- reset:
-
-    /* see if we have a full line */
-    ret = GetLine( cxn->imap_respBuffer , strbuf, sizeof(strbuf));
-    str = strbuf;
-    linestart = str;
-
-    /* if we don't have a full line */
-    if ( ret == RET_NO_FULLLINE)
-       {
-
-           readBuffers = makeBufferArray (bufferTakeRef (cxn->imap_rBuffer), NULL) ;
-
-           if ( !prepareRead (e, readBuffers, imap_readCB, cxn, 1) )
-               {
-                   imap_Disconnect(cxn);
-               }
-           return;
-
-       } else if (ret!=RET_OK)
-           {
-               return;
-           }
-
-    /* if untagged */
-    if ((str[0]=='*') && (str[1]==' '))
-    {
-       str+=2;
-       
-       /* now figure out what kind of untagged it is */
-       if (strncasecmp(str,"CAPABILITY ",11)==0)
-       {
-           str+=11;
-           
-           imap_ParseCapability(str,&(cxn->imap_capabilities));
-           
-       } else if (strncasecmp(str,"SEARCH",6)==0) {
-
-           str+=6;
-           
-           if ( (*str) == ' ')
-           {
-               str++;
-               
-               cxn->current_control->data.control->uid = atoi(str);
-               
-               d_printf(1,"%s:%d:IMAP i think the UID = %ld\n",
-                        hostPeerName (cxn->myHost), cxn->ident,
-                        cxn->current_control->data.control->uid);
-           } else {
-               /* it's probably a blank uid (i.e. message doesn't exist) */
-               cxn->current_control->data.control->uid = (unsigned long)-1;
-           }
-
-           
-       } else if (strncasecmp(str,"OK ",3)==0) {
-           
-           if (cxn->imap_state==IMAP_READING_INTRO)
-           {
-               imap_sendCapability(cxn); /* xxx errors */
-               return;
-               
-           } else {
-               
-           }
-           
-           
-       } else {
-           /* untagged command not understood */
-       }
-
-       /* always might be more to look at */
-       goto reset;
-
-    } else if ((str[0]=='+') && (str[1]==' ')) {
-
-       str+=2;
-
-       if (cxn->imap_state == IMAP_READING_STEPAUTH)
-       {
-#ifdef HAVE_SASL
-           if (imap_sendAuthStep(cxn, str)!=RET_OK)
-           {
-               imap_Disconnect(cxn);
-           }
-#else
-           d_printf(0,"%s:%d:IMAP got a '+ ...' without SASL. Something's wrong\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           imap_Disconnect(cxn);
-#endif /* HAVE_SASL */
-
-           return;
-       } else {
-           d_printf(0,"%s:%d:IMAP got a '+ ...' in state where not expected\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           imap_Disconnect(cxn);
-           return;
-       }
-       
-
-       
-    } else if (strncmp(str, cxn->imap_currentTag, IMAP_TAGLENGTH)==0) {        
-       /* matches our tag */
-       str += IMAP_TAGLENGTH;
-       
-       if (str[0]!=' ')
-       {
-           d_printf(0,"%s:%d:IMAP Parse error: tag with no space afterward\n",
-                    hostPeerName (cxn->myHost), cxn->ident);
-           imap_Disconnect(cxn);
-           return;         
-       }
-       str++;
-
-       /* should be OK/NO */
-       if (strncmp(str,"OK",2)==0)
-       {
-           okno = 1;
-       } else {
-           okno = 0;
-       }
-       
-       switch(cxn->imap_state)
-           {
-           case IMAP_READING_CAPABILITY:
-
-               if (okno==1) {
-                   if (imap_sendAuthenticate(cxn)!=RET_OK)
-                   {
-                       d_printf(0,"%s:%d:IMAP sendauthenticate failed\n",
-                                hostPeerName (cxn->myHost), cxn->ident);
-                       imap_Disconnect(cxn);
-                   }
-                   return;
-               } else {
-                   d_printf(0,"%s:%d:IMAP CAPABILITY gave a NO response\n",
-                            hostPeerName (cxn->myHost), cxn->ident);
-                   imap_Disconnect(cxn);
-               }
-               return;
-               
-               break;
-           case IMAP_READING_STEPAUTH:
-               
-               if (okno == 1) {
-
-                   cxn->imap_sleepTimeout = init_reconnect_period ;
-
-                   cxn->imap_timeCon = theTime () ;
-                   cxn->timeCon = theTime () ;
-                   
-                   d_printf(0,"%s:%d IMAP authentication succeeded\n",
-                            hostPeerName (cxn->myHost), cxn->ident);
-
-                   cxn->imap_disconnects=0;
-                   
-                   cxn->imap_state = IMAP_IDLE_AUTHED;
-
-                   /* try to send a message if we have one */
-                   
-                   imap_ProcessQueue(cxn);
-               } else {
-                   d_printf(0,"%s:%d:IMAP Authentication failed with [%s]\n",               
-                            hostPeerName (cxn->myHost), cxn->ident,str);
-                   imap_Disconnect(cxn);
-               }
-
-               return;
-
-               break;
-               
-           case IMAP_READING_CREATE:
-
-                   if (okno==1) {
-                       
-                       d_printf(1,"%s:%d:IMAP Create of bboard successful\n",
-                                hostPeerName (cxn->myHost), cxn->ident);
-                                
-                       cxn->create_succeeded++;
-
-                       /* we can delete article now */
-                       QueueForgetAbout(cxn, cxn->current_control, 
-                                        MSG_SUCCESS);
-                   } else {
-                       d_printf(1,"%s:%d:IMAP Create failed with [%s] for %s\n",
-                                hostPeerName (cxn->myHost), cxn->ident,str,
-                                cxn->current_control->data.control->folder);
-
-                       ReQueue(cxn, &(cxn->imap_controlMsg_q), cxn->current_control);
-                   }
-
-                   imap_ProcessQueue(cxn);
-                       
-                   break;
-                   
-           case IMAP_READING_DELETE:
-
-                   if (okno==1) {
-                       d_printf(1,"%s:%d:IMAP Delete successful\n",
-                                hostPeerName (cxn->myHost), cxn->ident);
-                       cxn->remove_succeeded++;
-
-                       /* we can delete article now */
-                       QueueForgetAbout(cxn, cxn->current_control, 
-                                        MSG_SUCCESS);
-                   } else {
-                       d_printf(1,"%s:%d:IMAP Delete mailbox failed with [%s] for %s\n",
-                                hostPeerName (cxn->myHost), cxn->ident,str,
-                                cxn->current_control->data.control->folder);
-
-                       ReQueue(cxn, &(cxn->imap_controlMsg_q), cxn->current_control);
-                       
-                   }
-
-                   imap_ProcessQueue(cxn);
-                   return;
-                       
-                   break;
-
-           case IMAP_READING_SELECT:
-
-                   if (okno==1) {
-
-                       imap_sendSearch(cxn, cxn->current_control->data.control->msgid);
-                       return;
-
-                   } else {
-                       d_printf(1,"%s:%d:IMAP Select failed with [%s] for %s\n",
-                                hostPeerName (cxn->myHost), cxn->ident,str,
-                                cxn->current_control->data.control->folder);
-
-                       ReQueue(cxn, &(cxn->imap_controlMsg_q), cxn->current_control);
-                       
-                       cxn->imap_state = IMAP_IDLE_AUTHED;
-
-                       imap_ProcessQueue(cxn);
-                       return;
-                   }
-
-                   break;
-
-           case IMAP_READING_SEARCH:
-               /* if no message let's forget about it */
-               if (cxn->current_control->data.control->uid
-                       == (unsigned long)-1) {
-                   d_printf(2, "%s:%d:IMAP Search didn't find the message\n",
-                            hostPeerName (cxn->myHost), cxn->ident);
-                   QueueForgetAbout(cxn, cxn->current_control, 
-                                    MSG_FAIL_DELIVER);
-                   if (imap_sendClose(cxn) != RET_OK)
-                       imap_Disconnect(cxn);
-                   return;
-               }
-
-               if (okno==1) {
-                   /* we got a uid. let's delete it */
-                   if (imap_sendKill(cxn, 
-                                      cxn->current_control->data.control->uid)
-                           != RET_OK)
-                       imap_Disconnect(cxn);
-                   return;
-               } else {
-                   d_printf(0, "%s:%d IMAP Received NO response to SEARCH\n",
-                            hostPeerName (cxn->myHost), cxn->ident);
-                   ReQueue(cxn, &(cxn->imap_controlMsg_q), 
-                           cxn->current_control);
-                   
-                   if (imap_sendClose(cxn) != RET_OK)
-                       imap_Disconnect(cxn);
-                   return;
-               }
-               break;
-
-           case IMAP_READING_STORE:
-
-                   if (okno==1) {
-
-                       d_printf(1,"%s:%d:IMAP Processed a Cancel fully\n",
-                                hostPeerName (cxn->myHost), cxn->ident);
-
-                       /* we can delete article now */
-                       QueueForgetAbout(cxn, cxn->current_control,
-                                        MSG_SUCCESS);
-
-                       cxn->cancel_succeeded++;
-
-                       if (imap_sendClose(cxn) != RET_OK)
-                           imap_Disconnect(cxn);
-                       return;
-
-                   } else {
-
-                       d_printf(1,"%s:%d:IMAP Store failed\n",
-                                hostPeerName (cxn->myHost), cxn->ident);
-                       ReQueue(cxn, &(cxn->imap_controlMsg_q), cxn->current_control);
-
-                       if (imap_sendClose(cxn) != RET_OK)
-                           imap_Disconnect(cxn);
-                       return;
-                   }
-
-                   break;
-
-           case IMAP_READING_NOOP:
-               cxn->imap_state = IMAP_IDLE_AUTHED;
-               return;
-               break;
-
-           case IMAP_READING_CLOSE:
-               if (!okno) {
-                   /* we can't do anything about it */
-                   d_printf(1,"%s:%d:IMAP Close failed\n",
-                            hostPeerName (cxn->myHost), cxn->ident);
-               }
-
-               cxn->imap_state = IMAP_IDLE_AUTHED;
-               
-               imap_ProcessQueue(cxn);             
-               return;
-               break;
-
-           case IMAP_READING_QUIT:
-               
-               /* we don't care if the server said OK or NO just
-                  that it said something */
-
-               d_printf(1,"%s:%d:IMAP Read quit response\n",
-                        hostPeerName (cxn->myHost), cxn->ident);
-               
-               cxn->imap_state = IMAP_DISCONNECTED;
-
-               DeleteIfDisconnected(cxn);
-               break;
-                   
-
-           default:
-               d_printf(0,"%s:%d:IMAP I don't understand state %d [%s]\n",
-                        hostPeerName (cxn->myHost), cxn->ident,
-                        cxn->imap_state,str);
-               imap_Disconnect(cxn);
-               break;
-           }
-           
-
-    } else {
-       d_printf(0,"%s:%d:IMAP tag (%s) doesn't match what we gave (%s). What's up with that??\n",
-                hostPeerName (cxn->myHost), cxn->ident, str, cxn->imap_currentTag);
-       imap_Disconnect(cxn);
-    }
-    
-}
-
-/************************** END IMAP reading functions ***************************/
-
-/*************************** LMTP reading functions ****************************/
-
-static void lmtp_readCB (EndPoint e, IoStatus i, Buffer *b, void *d)
-{
-    connection_t *cxn = (connection_t *) d;
-    char str[4096];
-    Buffer *readBuffers;
-    int result;
-    int response_code;
-    conn_ret ret;
-#ifdef HAVE_SASL
-    int inlen;
-    char *in;
-    int outlen;
-    const char *out;
-    char *inbase64;
-    int inbase64len;
-    imt_stat status;
-    int saslresult;
-    sasl_interact_t *client_interact=NULL;
-#endif /* HAVE_SASL */
-
-    char *p = bufferBase(b[0]);
-
-    bufferAddNullByte (b[0]) ;
-
-    if (i != IoDone) {
-       errno = endPointErrno(e);
-       syslog(LOG_ERR, "%s:%d LMTP i/o failed: %m",
-              hostPeerName (cxn->myHost), cxn->ident);
-
-       freeBufferArray (b);
-       lmtp_Disconnect(cxn);
-       return;
-    }
-
-    if (strchr (p, '\n') == NULL)
-    {
-       /* partial read. expand buffer and retry */
-
-       d_printf(0,"%s:%d:LMTP Partial. retry\n",
-                hostPeerName (cxn->myHost),cxn->ident);
-       expandBuffer (b[0], BUFFER_EXPAND_AMOUNT) ;
-       readBuffers = makeBufferArray (bufferTakeRef (b[0]), NULL) ;
-       
-       if ( !prepareRead (e, readBuffers, lmtp_readCB, cxn, 1) )
-       {
-           lmtp_Disconnect(cxn);
-        }
-
-       freeBufferArray (b);
-       return;
-    }
-
-    clearTimer (cxn->lmtp_readBlockedTimerId) ;
-
-    /* Add what we got to our internal read buffer */
-    strcat(cxn->lmtp_respBuffer, p);
-
-    bufferSetDataSize( b[0], 0);
-
-    freeBufferArray (b);
-
- reset:
-    /* see if we have a full line */
-    ret = GetLine( cxn->lmtp_respBuffer, str, sizeof(str));
-
-    /* get a line */
-    if (ret!=RET_OK)
-    {
-       if (ret!=RET_NO_FULLLINE)
-       {
-           /* was a more serious error */
-           d_printf(0,"%s:%d:LMTP Internal error getting line from server\n",
-                    hostPeerName (cxn->myHost),cxn->ident);
-           lmtp_Disconnect(cxn);
-           return;         
-       }
-
-       /* set up to receive some more */
-       readBuffers = makeBufferArray (bufferTakeRef (cxn->lmtp_rBuffer), NULL) ;
-       prepareRead(cxn->lmtp_endpoint, readBuffers, lmtp_readCB, cxn, 5);
-       return;
-    }
-
-    switch (cxn->lmtp_state)
-       {
-
-       case LMTP_READING_INTRO:
-           
-           if (ask_code(str)!=220)
-           {
-               d_printf(0,"%s:%d:LMTP Initial server msg does not start with 220 (began with %d)\n",
-                        hostPeerName (cxn->myHost),cxn->ident,
-                        ask_code(str));
-               lmtp_Disconnect(cxn);
-               return;
-           }
-
-           /* the initial intro could have many lines via
-               continuations. see if we need to read more */
-           if (ask_keepgoing(str)==1)
-           {
-               goto reset;
-           }
-
-           result = lmtp_getcapabilities(cxn);
-
-           if (result != RET_OK)
-           {
-               d_printf(0,"%s:%d:LMTP lmtp_getcapabilities() failure\n",
-                        hostPeerName (cxn->myHost),cxn->ident);
-               lmtp_Disconnect(cxn);
-               return;
-           }
-
-           break;
-
-       case LMTP_READING_LHLO:
-           /* recieve the response(s) */
-           response_code = ask_code(str);
-           
-           if (response_code != 250) /* was none */
-           {
-               d_printf(0,"%s:%d:LMTP Response code unexpected (%d)\n",
-                        hostPeerName (cxn->myHost),cxn->ident,
-                        response_code);
-               lmtp_Disconnect(cxn);
-               return;
-           }
-
-           /* look for one we know about; ignore all others */
-           if (strncmp(str+4,"8BITMIME",strlen("8BITMIME"))==0)
-           {
-               cxn->lmtp_capabilities->Eightbitmime = 1;
-           } else if (strncmp(str+4, "ENHANCEDSTATUSCODES",
-                              strlen("ENHANCEDSTATUSCODES"))==0) {
-               cxn->lmtp_capabilities->EnhancedStatusCodes = 1;
-           } else if (strncmp(str+4, "AUTH",4)==0) {
-               cxn->lmtp_capabilities->saslmechs = xstrdup(str + 4 + 5);
-           } else if (strncmp(str+4,"PIPELINING",strlen("PIPELINING"))==0) {
-               cxn->lmtp_capabilities->pipelining = 1;
-           } else {
-               /* don't care; ignore */
-           }
-           
-           /* see if this is the last line of the capability */
-           if (ask_keepgoing(str)==1)
-           {
-               goto reset;
-           } else {
-               /* we require a few capabilities */
-               if (!cxn->lmtp_capabilities->pipelining) {
-                   d_printf(0,"%s:%d:LMTP We require PIPELINING\n",
-                            hostPeerName (cxn->myHost),cxn->ident);
-                   
-                   lmtp_Disconnect(cxn);
-                   return;
-               }
-#ifdef HAVE_SASL
-               if (cxn->lmtp_capabilities->saslmechs) {
-                   /* start the authentication */
-                   result = lmtp_authenticate(cxn);
-                   
-                   if (result != RET_OK) {
-                       d_printf(0,"%s:%d:LMTP lmtp_authenticate() error\n",
-                            hostPeerName (cxn->myHost),cxn->ident);
-                       lmtp_Disconnect(cxn);
-                       return;
-                   }
-#else
-               if (0) {
-                   /* noop */
-#endif
-               } else {
-                   /* either we can't authenticate or the remote server
-                      doesn't support it */
-                   cxn->lmtp_state = LMTP_AUTHED_IDLE;
-                   d_printf(1,"%s:%d:LMTP Even though we can't authenticate"
-                            " we're going to try to feed anyway\n",
-                            hostPeerName (cxn->myHost),cxn->ident);
-                   /* We just assume we don't need to authenticate 
-                      (great assumption huh?) */
-                   hostRemoteStreams (cxn->myHost, cxn, true) ;
-
-                   cxn->lmtp_timeCon = theTime () ;
-                   cxn->timeCon = theTime () ;
-                   
-                   /* try to send a message if we have one */
-                   lmtp_sendmessage(cxn,NULL);
-                   return;
-               }
-           }
-           break;
-
-#ifdef HAVE_SASL
-       case LMTP_READING_STEPAUTH:
-           inlen = 0;
-           status = lmtp_getauthline(str, &in, &inlen);
-
-           switch (status)
-               {
-
-               case STAT_CONT:
-
-                   saslresult=sasl_client_step(cxn->saslconn_lmtp,
-                                               in,
-                                               inlen,
-                                               &client_interact,
-                                               &out,
-                                               &outlen);
-
-                   free(in);
-
-                   /* check if sasl succeeded */
-                   if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) {
-                       d_printf(0,"%s:%d:LMTP sasl_client_step(): %s\n",
-                                hostPeerName (cxn->myHost),cxn->ident,
-                                sasl_errstring(saslresult,NULL,NULL));
-
-                       lmtp_Disconnect(cxn);
-                       return;
-                   }
-
-                   /* convert to base64 */
-                   inbase64 = xmalloc(outlen*2+10);
-
-                   saslresult = sasl_encode64(out, outlen,
-                                              inbase64, outlen*2+10, 
-                                              (unsigned *) &inbase64len);
-                   
-                   if (saslresult != SASL_OK)
-                   {
-                       d_printf(0,"%s:%d:LMTP sasl_encode64(): %s\n",
-                                hostPeerName (cxn->myHost),cxn->ident,
-                                sasl_errstring(saslresult,NULL,NULL));
-
-                       lmtp_Disconnect(cxn);
-                       return;
-                   }
-
-                   /* add an endline */
-                   strlcpy(inbase64 + inbase64len, "\r\n", outlen * 2 + 10);
-
-                   /* send to server */
-                   result = WriteToWire_lmtpstr(cxn,inbase64, inbase64len+2);
-
-                   if (result != RET_OK)
-                   {
-                       d_printf(0,"%s:%d:LMTP WriteToWire() failure\n",
-                                hostPeerName (cxn->myHost),cxn->ident);
-                       lmtp_Disconnect(cxn);
-                       return;
-                   }
-
-                   cxn->lmtp_state = LMTP_WRITING_STEPAUTH;
-                   break;
-                   
-               case STAT_OK:
-                   cxn->lmtp_sleepTimeout = init_reconnect_period ;
-      
-                   d_printf(0,"%s:%d LMTP authentication succeeded\n",
-                            hostPeerName (cxn->myHost), cxn->ident);
-
-                   cxn->lmtp_disconnects=0;
-
-                   hostRemoteStreams (cxn->myHost, cxn, true) ;
-
-                   cxn->lmtp_timeCon = theTime () ;
-                   cxn->timeCon = theTime () ;
-
-                   cxn->lmtp_state = LMTP_AUTHED_IDLE;
-
-
-                   /* try to send a message if we have one */
-                   lmtp_sendmessage(cxn,NULL);
-                   return;
-
-                   break;
-
-               default:
-                   d_printf(0,"%s:%d:LMTP failed authentication\n",
-                            hostPeerName (cxn->myHost),cxn->ident);
-                   lmtp_Disconnect(cxn);
-                   return;
-               }
-           break;
-#endif /* HAVE_SASL */
-                   
-       case LMTP_READING_RSET:
-           if (ask_keepgoing(str)) {
-               goto reset;
-           }
-           if (ask_code(str) != 250) {
-               d_printf(0,"%s:%d:LMTP RSET failed with (%d)\n",
-                        hostPeerName (cxn->myHost),cxn->ident,
-                        ask_code(str));
-               lmtp_Disconnect(cxn);
-               return;
-           }
-
-           /* we pipelined so next we recieve the mail from response */
-           cxn->lmtp_state = LMTP_READING_MAILFROM;
-           goto reset;
-
-       case LMTP_READING_MAILFROM:
-           if (ask_keepgoing(str)) {
-               goto reset;
-           }
-           if (ask_code(str) != 250) {
-               d_printf(0,"%s:%d:LMTP MAILFROM failed with (%d)\n",
-                        hostPeerName (cxn->myHost),cxn->ident,
-                        ask_code(str));
-               lmtp_Disconnect(cxn);
-               return;
-           }
-
-           /* we pipelined so next we recieve the rcpt's */
-           cxn->lmtp_state = LMTP_READING_RCPTTO;
-           goto reset;
-           break;
-
-       case LMTP_READING_RCPTTO:
-           if (ask_keepgoing(str)) {
-               goto reset;
-           }
-           if (ask_code(str)!=250) {
-               d_printf(1,"%s:%d:LMTP RCPT TO failed with (%d) %s\n",
-                        hostPeerName (cxn->myHost),cxn->ident,
-                        ask_code(str), str);
-
-               /* if got a 5xx don't try to send anymore */
-               cxn->current_article->trys=100;
-
-               cxn->current_rcpts_issued--;
-           } else {
-               cxn->current_rcpts_okayed++;
-           }
-
-           /* if issued equals number okayed then we're done */
-           if ( cxn->current_rcpts_okayed == cxn->current_rcpts_issued) {
-               cxn->lmtp_state = LMTP_READING_DATA;
-           } else {
-               /* stay in same state */
-           }
-           goto reset;
-           break;
-
-       case LMTP_READING_DATA:
-           if (ask_keepgoing(str)) {
-               goto reset;
-           }
-           if (cxn->current_rcpts_issued == 0) {
-               if (cxn->current_article->trys < 100) {
-                   d_printf(1, "%s:%d:LMTP None of the rcpts "
-                            "were accepted for this message. Re-queueing\n",
-                            hostPeerName (cxn->myHost),cxn->ident);
-               }
-
-               ReQueue(cxn, &(cxn->lmtp_todeliver_q), cxn->current_article);
-
-               cxn->lmtp_state = LMTP_AUTHED_IDLE;
-               lmtp_sendmessage(cxn,NULL);
-           } else {
-               if (WriteArticle(cxn, cxn->current_bufs) != RET_OK)
-               {
-                   d_printf(0, "%s:%d:LMTP Error writing article\n",
-                            hostPeerName (cxn->myHost),cxn->ident);
-                   lmtp_Disconnect(cxn);
-                   return;
-               }
-               
-               cxn->lmtp_state = LMTP_WRITING_CONTENTS;
-           }
-
-           break;
-
-       case LMTP_READING_CONTENTS:
-           if (ask_keepgoing(str)) {
-               goto reset;
-           }
-
-           /* need 1 response from server for every rcpt */
-           cxn->current_rcpts_issued--;
-           
-           if (ask_code(str) != 250) {
-               d_printf(1, "%s:%d:LMTP DATA failed with %d (%s)\n",
-                        hostPeerName (cxn->myHost),cxn->ident,
-                        ask_code(str), str);
-               cxn->current_rcpts_okayed--;
-           }
-
-           if (cxn->current_rcpts_issued>0) {
-               goto reset;
-           }
-
-           /*
-            * current_rcpts_okayed is number that succeeded
-            *
-            */
-           if (cxn->current_rcpts_okayed == 0) {
-               cxn->lmtp_state = LMTP_AUTHED_IDLE;
-           } else {
-               cxn->lmtp_state = LMTP_AUTHED_IDLE;
-               cxn->lmtp_succeeded++;      
-               d_printf(1, "%s:%d:LMTP Woohoo! message accepted\n",
-                        hostPeerName (cxn->myHost),cxn->ident);
-           }
-
-           /* we can delete article now */
-           QueueForgetAbout(cxn, cxn->current_article, MSG_SUCCESS);
-
-           /* try to send another if we have one and we're still idle
-            * forgetting the msg might have made us unidle
-            */
-           if (cxn->lmtp_state == LMTP_AUTHED_IDLE) {
-               lmtp_sendmessage(cxn,NULL);
-           }
-           
-           break;
-
-       case LMTP_READING_NOOP:
-           if (ask_keepgoing(str)) {
-               goto reset;
-           }
-           cxn->lmtp_state = LMTP_AUTHED_IDLE;
-           break;
-
-       case LMTP_READING_QUIT:
-           d_printf(1,"%s:%d:LMTP read quit\n",
-                    hostPeerName (cxn->myHost),cxn->ident);
-
-           cxn->lmtp_state = LMTP_DISCONNECTED;            
-
-           DeleteIfDisconnected(cxn);
-           break;
-
-       default:
-
-           d_printf(0,"%s:%d:LMTP Bad state in lmtp_readCB %d\n",
-                    hostPeerName (cxn->myHost),cxn->ident,
-                    cxn->lmtp_state);
-           lmtp_Disconnect(cxn);
-           return;
-       }
-
-
-}
-
-/*
- * Add a rcpt to:<foo> to the string
- *
- */
-
-static void addrcpt(char *newrcpt, int newrcptlen, char **out, int *outalloc)
-{
-    int size = strlen(*out);
-    int fsize = size;
-    int newsize = size + 9+strlen(deliver_rcpt_to)+newrcptlen+3;
-    char c;
-
-    /* see if we need to grow the string */
-    if (newsize > *outalloc) {
-       (*outalloc) = newsize;
-       (*out) = xrealloc(*out, *outalloc);
-    }
-
-    strlcpy((*out) + size,"RCPT TO:<", newsize - size);
-    size += 9;
-
-    c = newrcpt[newrcptlen];
-    newrcpt[newrcptlen] = '\0';
-    size += snprintf((*out) + size, newsize - size, deliver_rcpt_to, newrcpt);
-    newrcpt[newrcptlen] = c;
-
-    strlcpy((*out) + size, ">\r\n", newsize - size);
-
-    /* has embedded '\n' */
-    d_printf(2, "Attempting to send to: %s", (*out) + fsize);
-}
-
-/*
- * Takes the newsgroups header value and makes it into a list of RCPT TO:'s we can send over the wire
- *
- *  in     - newsgroups header start
- *  in_end - end of newsgroups header
- *  num    - number of rcpt's we created
- */
-
-static char *ConvertRcptList(char *in, char *in_end, int *num)
-{
-    int retalloc = 400;
-    char *ret = xmalloc(retalloc);
-    char *str = in;
-    char *laststart = in;
-
-    (*num) = 0;
-
-    /* start it off empty */     
-    strlcpy(ret, "", retalloc);
-    
-    while ( str !=  in_end)
-    {
-       if ((*str) == ',')
-       {
-           /* eliminate leading whitespace */
-           while (((*laststart) ==' ') || ((*laststart)=='\t'))
-           {
-               laststart++;
-           }
-
-#ifndef SMTPMODE
-           addrcpt(laststart, str - laststart, &ret, &retalloc);
-           (*num)++;
-#endif /* SMTPMODE */
-           laststart = str+1;
-       }
-
-       str++;
-    }
-
-    if (laststart<str)
-    {
-       addrcpt(laststart, str - laststart, &ret, &retalloc);
-       (*num)++;
-    }
-
-    return ret;
-}
-
-static void addto(char *newrcpt, int newrcptlen, const char *sep,
-                 char **out, int *outalloc)
-{
-    int size = strlen(*out);
-    int newsize = size + strlen(sep)+1+strlen(deliver_to_header)+newrcptlen+1;
-    char c;
-
-    /* see if we need to grow the string */
-    if (newsize > *outalloc) {
-       (*outalloc) = newsize;
-       (*out) = xrealloc(*out, *outalloc);
-    }
-
-    size += snprintf((*out) + size, newsize - size, "%s<", sep);
-
-    c = newrcpt[newrcptlen];
-    newrcpt[newrcptlen] = '\0';
-    size += snprintf((*out) + size, newsize - size, deliver_to_header,newrcpt);
-    newrcpt[newrcptlen] = c;
-
-    strlcpy((*out) + size, ">", newsize - size);
-}
-
-/*
- * Takes the newsgroups header value and makes it into a To: header
- *
- *  in     - newsgroups header start
- *  in_end - end of newsgroups header
- */
-
-static char *BuildToHeader(char *in, char *in_end)
-{
-    int retalloc = 400;
-    char *ret = xmalloc(retalloc);
-    char *str = in;
-    char *laststart = in;
-    const char *sep = "";
-
-    /* start it off with the header name */     
-    strlcpy(ret,"To: ", retalloc);
-    
-    while ( str !=  in_end)
-    {
-       if ((*str) == ',')
-       {
-           /* eliminate leading whitespace */
-           while (((*laststart) ==' ') || ((*laststart)=='\t'))
-           {
-               laststart++;
-           }
-
-           addto(laststart, str - laststart, sep, &ret, &retalloc);
-           laststart = str+1;
-
-           /* separate multiple addresses with a comma */
-           sep = ", ";
-       }
-
-       str++;
-    }
-
-    if (laststart<str)
-    {
-       addto(laststart, str - laststart, sep, &ret, &retalloc);
-    }
-
-    /* terminate the header */
-    strlcat(ret, "\n\r", retalloc);
-    return ret;
-}
-
-/*************************** END LMTP reading functions ****************************/
-
-
-
-/*
- * Process the control message queue. If we run out ask the host for more.
- *
- *  cxn       - connection object
- */
-
-static void imap_ProcessQueue(connection_t *cxn)
-{
-    article_queue_t *item;
-    int result;
-
- retry:
-
-    /* pull an article off the queue */
-    result = PopFromQueue(&(cxn->imap_controlMsg_q), &item);
-
-    if (result==RET_QUEUE_EMPTY)
-    {
-       if (cxn->issue_quit)
-       {
-           imap_sendQuit(cxn);
-           return;
-       }
-
-       cxn->imap_state = IMAP_IDLE_AUTHED;
-
-       /* now we wait for articles from our Host, or we have some
-          articles already. On infrequently used connections, the
-          network link is torn down and rebuilt as needed. So we may
-          be rebuilding the connection here in which case we have an
-          article to send. */
-
-       /* make sure imap has _lots_ of space too */
-       if ((QueueItems(&(cxn->lmtp_todeliver_q)) == 0) && 
-           (QueueItems(&(cxn->imap_controlMsg_q)) == 0))
-       {
-           if (hostGimmeArticle (cxn->myHost,cxn)==true)
-               goto retry;
-       }
-
-       return;
-    }
-
-    cxn->current_control = item;
-
-    switch (item->type)
-       {
-       case CREATE_FOLDER:
-           imap_CreateGroup(cxn, item->data.control->folder);
-           break;
-
-       case CANCEL_MSG:
-           imap_CancelMsg(cxn, item->data.control->folder);
-           break;
-
-       case DELETE_FOLDER:
-           imap_DeleteGroup(cxn, item->data.control->folder); 
-           break;
-       default:
-           break;
-       }
-
-    return;
-}
-
-
-
-/*
- *
- * Pulls a message off the queue and trys to start sending it. If the
- * message is a control message put it in the control queue and grab
- * another message. If the message doesn't exist on disk or something
- * is wrong with it tell the host and try again. If we run out of
- * messages to get tell the host we want more
- *
- * cxn       - connection object
- * justadded - the article that was just added to the queue
- */
-
-static void lmtp_sendmessage(connection_t *cxn, Article justadded)
-{
-    bool res;
-    conn_ret result;
-    char *p;
-    Buffer *bufs;
-    char *control_header = NULL;
-    char *control_header_end = NULL;
-
-    article_queue_t *item;
-    char *rcpt_list, *rcpt_list_end;
-
-    /* retry point */
- retry:
-
-    /* pull an article off the queue */
-    result = PopFromQueue(&(cxn->lmtp_todeliver_q), &item);
-
-    if (result==RET_QUEUE_EMPTY)
-    {
-       if (cxn->issue_quit) {
-           lmtp_IssueQuit(cxn);
-           return;
-       }
-       /* now we wait for articles from our Host, or we have some
-          articles already. On infrequently used connections, the
-          network link is torn down and rebuilt as needed. So we may
-          be rebuilding the connection here in which case we have an
-          article to send. */
-
-       /* make sure imap has space too */
-       d_printf(1,"%s:%d stalled waiting for articles\n",
-                hostPeerName (cxn->myHost),cxn->ident);
-       if ((QueueItems(&(cxn->lmtp_todeliver_q)) == 0) && 
-           (QueueItems(&(cxn->imap_controlMsg_q)) == 0)) {
-           if (hostGimmeArticle (cxn->myHost,cxn)==true)
-               goto retry;
-       }
-
-       return;
-    }
-
-    /* make sure contents ok; this also should load it into memory */
-    res = artContentsOk (item->data.article);
-    if (res==false)
-    {
-       if (justadded == item->data.article) {
-           ReQueue(cxn, &(cxn->lmtp_todeliver_q), item);
-           return;
-       } else {
-           /* tell to reject taking this message */
-           QueueForgetAbout(cxn,item, MSG_MISSING);
-       }
-
-       goto retry;
-    }
-
-    /* Check if it's a control message */
-    bufs = artGetNntpBuffers (item->data.article);
-    if (bufs == NULL)
-    {
-       /* tell to reject taking this message */
-       QueueForgetAbout(cxn,item, MSG_MISSING);
-       goto retry;
-    }
-
-    result = FindHeader(bufs, "Control", &control_header, &control_header_end);
-    if (result == RET_OK) {
-       result = AddControlMsg(cxn, item->data.article, bufs, 
-                              control_header,control_header_end, 1);
-       if (result != RET_OK) {
-           d_printf(1,"%s:%d Error adding to [imap] control queue\n",
-                    hostPeerName (cxn->myHost),cxn->ident) ;
-           ReQueue(cxn, &(cxn->lmtp_todeliver_q), item);
-           return;
-       }
-
-       switch(cxn->imap_state) {
-       case IMAP_IDLE_AUTHED:
-           /* we're idle. let's process the queue */
-           imap_ProcessQueue(cxn);
-           break;
-       case IMAP_DISCONNECTED:
-       case IMAP_WAITING:
-           /* Let's connect. Once we're connected we can 
-              worry about the message */
-           if (cxn->imap_sleepTimerId == 0) {
-               if (imap_Connect(cxn) != RET_OK) prepareReopenCbk(cxn,0);
-           }
-           break;
-       default:
-           /* we're doing something right now */
-           break;
-       }
-       
-       /* all we did was add a control message. 
-          we still want to get an lmtp message */
-       goto retry;
-    }
-
-    if (cxn->current_bufs != NULL) {
-       /*      freeBufferArray(cxn->current_bufs); */
-       cxn->current_bufs = NULL;
-    }
-    cxn->current_bufs = bufs;
-    cxn->current_article = item;
-    
-    /* we make use of pipelining here
-       send:
-         rset
-         mail from
-        rcpt to
-        data
-    */
-
-    /* find out who it's going to */
-    result = FindHeader(cxn->current_bufs, "Newsgroups", 
-                       &rcpt_list, &rcpt_list_end);
-
-    if ((result != RET_OK) || (rcpt_list == NULL)) {
-       d_printf(1,"%s:%d Didn't find Newsgroups header\n",
-                hostPeerName (cxn->myHost),cxn->ident) ;
-       QueueForgetAbout(cxn, cxn->current_article, MSG_FAIL_DELIVER);
-       goto retry;     
-    }
-
-    /* free's original rcpt_list */
-    rcpt_list = ConvertRcptList(rcpt_list, rcpt_list_end, 
-                               &cxn->current_rcpts_issued);
-    cxn->current_rcpts_okayed = 0;
-    
-    if(mailfrom_name == NULL)
-       mailfrom_name = xstrdup("");
-    p = concat("RSET\r\n"
-               "MAIL FROM:<", mailfrom_name, ">\r\n",
-               rcpt_list,
-               "DATA\r\n", (char *) 0);
-
-    cxn->lmtp_state = LMTP_WRITING_UPTODATA;
-    result = WriteToWire_lmtpstr(cxn, p, strlen(p));
-
-    if (result != RET_OK) {
-       d_printf(0,"%s:%d failed trying to write\n",
-                hostPeerName (cxn->myHost),cxn->ident) ;
-       lmtp_Disconnect(cxn);
-       return;
-    }
-
-    /* prepend To: header to article */
-    if (deliver_to_header) {
-       char *to_list, *to_list_end;
-       int i, len;
-
-       result = FindHeader(cxn->current_bufs, "Followup-To", 
-                           &to_list, &to_list_end);
-
-       if ((result != RET_OK) || (to_list == NULL)) {
-           result = FindHeader(cxn->current_bufs, "Newsgroups", 
-                               &to_list, &to_list_end);
-       }
-
-       /* free's original to_list */
-       to_list = BuildToHeader(to_list, to_list_end);
-
-       len = bufferArrayLen(cxn->current_bufs);
-       cxn->current_bufs = xrealloc(cxn->current_bufs,
-                                     sizeof(Buffer) * (len+2));
-       cxn->current_bufs[len+1] = NULL;
-
-       for (i = len; i > 0; i--) {
-           cxn->current_bufs[i] = cxn->current_bufs[i-1];
-       }
-
-       cxn->current_bufs[0] = newBufferByCharP(to_list, strlen(to_list+1),
-                                               strlen(to_list));
-    }
-
-    hostArticleOffered (cxn->myHost, cxn);
-}
-
-/*
- * Called by the EndPoint class when the timer goes off
- */
-static void dosomethingTimeoutCbk (TimeoutId id, void *data)
-{
-  Connection cxn = (Connection) data ;
-
-  ASSERT (id == cxn->dosomethingTimerId) ;
-
-  show_stats(cxn);
-
-  /* we're disconnected but there are things to send */
-  if ((cxn->lmtp_state == LMTP_DISCONNECTED) && 
-      (cxn->lmtp_sleepTimerId == 0) &&
-      QueueItems(&(cxn->lmtp_todeliver_q)) > 0)
-  {
-      if (lmtp_Connect(cxn) != RET_OK)
-         prepareReopenCbk(cxn, 1);
-  }
-
-  if ((cxn->imap_state == IMAP_DISCONNECTED) &&
-      (cxn->imap_sleepTimerId == 0) &&
-      (QueueItems(&(cxn->imap_controlMsg_q)) > 0))
-  {
-      if (imap_Connect(cxn) != RET_OK)
-         prepareReopenCbk(cxn, 0);
-  }
-
-
-  /* if we're idle and there are items to send let's send them */
-  if ((cxn->lmtp_state == LMTP_AUTHED_IDLE) && 
-      QueueItems(&(cxn->lmtp_todeliver_q)) > 0) {
-      lmtp_sendmessage(cxn,NULL);
-  } else if (cxn->lmtp_state == LMTP_AUTHED_IDLE) {
-      lmtp_noop(cxn);
-  }
-
-  if ((cxn->imap_state == IMAP_IDLE_AUTHED) &&
-      (QueueItems(&(cxn->imap_controlMsg_q)) > 0)) {
-      imap_ProcessQueue(cxn);
-  } else if (cxn->imap_state == IMAP_IDLE_AUTHED) {
-      imap_noop(cxn);
-  }
-
-  /* set up the timer. */
-  clearTimer (cxn->dosomethingTimerId) ;
-
-  cxn->dosomethingTimerId = prepareSleep (dosomethingTimeoutCbk, 
-                                         cxn->dosomethingTimeout, cxn);  
-}
-
-/* Give all articles in the queue back to the host. We're probably
- * going to exit soon.
- * */
-
-static void DeferAllArticles(connection_t *cxn, Q_t *q)
-{
-    article_queue_t *cur;
-    conn_ret ret;
-    
-    while (1)
-    {
-       ret = PopFromQueue(q, &cur);
-       if (ret == RET_QUEUE_EMPTY) return;
-
-       if (ret == RET_OK)
-        {
-           QueueForgetAbout(cxn, cur, MSG_GIVE_BACK);
-       } else {
-           d_printf(0,"%s:%d Error emptying queue (deffering all articles)\n",
-                    hostPeerName (cxn->myHost),cxn->ident);
-           return;
-       }
-    }
-}
-
-/*
- * Does the actual deletion of a connection and all its private data.
- */
-static void delConnection (Connection cxn)
-{
-  bool shutDown;
-  Connection c, q;
-
-  if (cxn == NULL)
-    return ;
-
-  d_printf (1,"Deleting connection: %s:%d\n",
-           hostPeerName (cxn->myHost),cxn->ident) ;
-
-  for (c = gCxnList, q = NULL ; c != NULL ; q = c, c = c->next)
-    if (c == cxn)
-      {
-        if (gCxnList == c)
-          gCxnList = gCxnList->next ;
-        else
-          q->next = c->next ;
-        break ;
-      }
-  
-  ASSERT (c != NULL) ;
-  if (cxn->lmtp_endpoint != NULL)
-    delEndPoint (cxn->lmtp_endpoint) ;
-  if (cxn->imap_endpoint != NULL)
-    delEndPoint (cxn->imap_endpoint) ;
-
-  delBuffer (cxn->imap_rBuffer) ;
-  delBuffer (cxn->lmtp_rBuffer) ;
-
-  /* tell the Host we're outta here. */
-  shutDown = hostCxnGone (cxn->myHost, cxn) ;
-
-  cxn->ident = 0 ;
-  cxn->timeCon = 0 ;
-
-  free (cxn->ServerName) ;
-
-  clearTimer (cxn->imap_readBlockedTimerId) ;
-  clearTimer (cxn->imap_writeBlockedTimerId) ;
-  clearTimer (cxn->lmtp_readBlockedTimerId) ;
-  clearTimer (cxn->lmtp_writeBlockedTimerId) ;
-
-  clearTimer (cxn->imap_sleepTimerId);
-  cxn->imap_sleepTimerId = 0;  
-  clearTimer (cxn->lmtp_sleepTimerId);  
-  cxn->lmtp_sleepTimerId = 0;
-
-  clearTimer (cxn->dosomethingTimerId);
-
-  free (cxn->imap_respBuffer);
-  free (cxn->lmtp_respBuffer);
-
-  free (cxn) ;
-
-  if (shutDown)
-    {
-      /* exit program if that was the last connexion for the last host */
-      /* XXX what about if there are ever multiple listeners?
-        XXX    this will be executed if all hosts on only one of the 
-        XXX    listeners have gone */
-      time_t now = theTime () ;
-      char dateString [30] ;
-
-      strlcpy (dateString,ctime (&now),sizeof (dateString)) ;
-      dateString [24] = '\0' ;
-
-      notice ("ME finishing at %s", dateString) ;
-
-      exit (0) ;
-    }
-}
-
-
-/******************** PUBLIC FUNCTIONS ****************************/
-
-
-
-  /*
-   * Create a new Connection.
-   * 
-   * HOST is the host object we're owned by.
-   * IDENT is an identifier to be added to syslog entries so we can tell
-   *    what's happening on different connections to the same peer.
-   * IPNAME is the name (or ip address) of the remote)
-   * MAXTOUT is the maximum amount of time to wait for a response before
-   *    considering the remote host dead.
-   * PORTNUM is the portnum to contact on the remote end.
-   * RESPTIMEOUT is the amount of time to wait for a response from a remote
-   *    before considering the connection dead.
-   * CLOSEPERIOD is the number of seconds after connecting that the
-   *     connections should be closed down and reinitialized (due to problems
-   *     with old NNTP servers that hold history files open. Value of 0 means
-   *     no close down.
-   */
-
-Connection newConnection (Host host,
-                          unsigned int ident,
-                          const char *ipname,
-                          unsigned int artTout UNUSED,
-                          unsigned int portNum UNUSED,
-                          unsigned int respTimeout,
-                          unsigned int closePeriod UNUSED,
-                          double lowPassLow UNUSED,
-                          double lowPassHigh UNUSED,
-                         double lowPassFilter UNUSED)
-{
-    Connection cxn;
-    /* check arguments */
-
-    /* allocate connection structure */
-    cxn = xcalloc (1, sizeof(connection_t)) ;
-
-    cxn->ident = ident ;
-    cxn->ServerName = xstrdup (ipname) ;
-    cxn->myHost = host ;
-
-    /* setup mailfrom user */
-    if (gethostname(hostname, MAXHOSTNAMELEN)!=0)
-    {
-       d_printf(0,"%s gethostname failed\n",ipname);
-       return NULL;
-    }
-
-
-    mailfrom_name = concat("news@", hostname, (char *) 0);
-
-    cxn->next = gCxnList ;
-    gCxnList = cxn ;
-    gCxnCount++ ;
-
-    /* init stuff */
-    Initialize(cxn, respTimeout);
-
-    return cxn;
-}
-
-
-/* Causes the Connection to build the network connection. */
-bool cxnConnect (Connection cxn)
-{
-    /* make the lmtp connection */
-    if (lmtp_Connect(cxn) != RET_OK) return false;
-
-    if (imap_Connect(cxn) != RET_OK) return false;
-
-    return true;
-}
-
-
-static void QuitIfIdle(Connection cxn)
-{
-    if ((cxn->lmtp_state == LMTP_AUTHED_IDLE) && 
-       (QueueItems(&(cxn->lmtp_todeliver_q))<=0)) {
-       lmtp_IssueQuit(cxn);
-    }
-    if ((cxn->imap_state == IMAP_IDLE_AUTHED) && 
-       (QueueItems(&(cxn->imap_controlMsg_q))<=0)) {
-       imap_sendQuit(cxn);
-    }
-}
-
-static void DeleteIfDisconnected(Connection cxn)
-{
-    /* we want to shut everything down. if both connections disconnected now we can */
-    if ((cxn->issue_quit >= 1) &&
-       (cxn->lmtp_state == LMTP_DISCONNECTED) &&
-       (cxn->imap_state == IMAP_DISCONNECTED))
-    {
-
-       switch (cxn->issue_quit)
-       {
-       case 1:
-           if (cxn->lmtp_state == LMTP_DISCONNECTED)
-           {
-               cxn->lmtp_state = LMTP_WAITING;
-               cxn->imap_state = IMAP_WAITING;
-               cxn->issue_quit = 0;
-               hostCxnWaiting (cxn->myHost,cxn) ;  /* tell our Host we're waiting */
-           }
-           break;
-       case 2:
-           if (cxn->lmtp_state == LMTP_DISCONNECTED)
-           {
-               cxn->issue_quit = 0;
-               
-               if (imap_Connect(cxn)!=RET_OK) prepareReopenCbk(cxn,0);
-               if (lmtp_Connect(cxn)!=RET_OK) prepareReopenCbk(cxn,1);
-           }
-           break;
-       case 3:
-           if (cxn->lmtp_state == LMTP_DISCONNECTED)
-           {
-               hostCxnDead (cxn->myHost,cxn) ;
-               delConnection(cxn);
-           }
-           break;
-           
-       }       
-    }
-}
-
-  /* puts the connection into the wait state (i.e. waits for an article
-     before initiating a connect). Can only be called right after
-     newConnection returns, or while the Connection is in the (internal)
-     Sleeping state. */
-void cxnWait (Connection cxn)
-{
-    cxn->issue_quit = 1;
-
-    QuitIfIdle(cxn);
-}
-
-  /* The Connection will disconnect as if cxnDisconnect were called and then
-     it automatically reconnects to the remote. */
-void cxnFlush (Connection cxn)
-{
-    cxn->issue_quit = 2;
-
-    QuitIfIdle(cxn);
-}
-
-
-
-  /* The Connection sends remaining articles, then issues a QUIT and then
-     deletes itself */
-void cxnClose (Connection cxn)
-{
-    d_printf(0,"%s:%d Closing cxn\n",hostPeerName (cxn->myHost), cxn->ident);
-    cxn->issue_quit = 3;
-
-    QuitIfIdle(cxn);
-
-    DeleteIfDisconnected(cxn);
-}
-
-  /* The Connection drops all queueed articles, then issues a QUIT and then
-     deletes itself */
-void cxnTerminate (Connection cxn)
-{
-    d_printf(0,"%s:%d Terminate\n",hostPeerName (cxn->myHost), cxn->ident);
-
-    cxn->issue_quit = 3;    
-
-    /* give any articles back to host in both queues */
-    DeferAllArticles(cxn, &(cxn->lmtp_todeliver_q));
-    DeferAllArticles(cxn, &(cxn->imap_controlMsg_q));
-
-    QuitIfIdle(cxn);
-}
-
-  /* Blow away the connection gracelessly and immedately clean up */
-void cxnNuke (Connection cxn)
-{
-    d_printf(0,"%s:%d Nuking connection\n",cxn->ServerName, cxn->ident);
-
-    cxn->issue_quit = 4;
-
-    /* give any articles back to host in both queues */
-    DeferAllArticles(cxn, &(cxn->lmtp_todeliver_q));
-    DeferAllArticles(cxn, &(cxn->imap_controlMsg_q));
-
-    imap_Disconnect(cxn);
-    lmtp_Disconnect(cxn);
-
-    hostCxnDead (cxn->myHost,cxn);    
-    delConnection(cxn);
-}
-
-/*
- * must
- *   true  - must queue article. Don't try sending
- *   false - queue of article may fail. Try sending
- *
- * Always adds to lmtp queue even if control message
- *
- */
-
-static bool ProcessArticle(Connection cxn, Article art, bool must)
-{
-    conn_ret result;
-
-    /* Don't accept any articles when we're closing down the connection */
-    if (cxn->issue_quit > 1) {
-       return false;
-    }
-
-    /* if it's a regular message let's add it to the queue */
-    result = AddToQueue(&(cxn->lmtp_todeliver_q), art, DELIVER,1,must);
-
-    if (result == RET_EXCEEDS_SIZE) {
-       return false;
-    }
-
-    if (result != RET_OK)
-    {
-       d_printf(0,"%s:%d Error adding to delivery queue\n",
-                hostPeerName (cxn->myHost), cxn->ident);
-       return must;
-    }
-
-    if (must == true) return true;
-
-    switch (cxn->lmtp_state)
-       {
-       case LMTP_WAITING:
-       case LMTP_DISCONNECTED:     
-           if (cxn->lmtp_sleepTimerId == 0)
-               if (lmtp_Connect(cxn) != RET_OK) prepareReopenCbk(cxn,1);
-           break;
-           
-       case LMTP_AUTHED_IDLE:
-           lmtp_sendmessage(cxn,art);
-           break;
-       default:
-           /* currently doing something */
-           break;
-       }
-    
-    return true;
-}
-
-  /* Tells the Connection to take the article and handle its
-     transmission. If it can't (due to queue size or whatever), then the
-     function returns false. The connection assumes ownership of the
-     article if it accepts it (returns true). */
-bool cxnTakeArticle (Connection cxn, Article art)
-{
-    /* if we're closing down always refuse */
-    if (cxn->issue_quit == 1) return false;
-
-    return ProcessArticle (cxn,art,false);
-}
-
-  /* Tell the Connection to take the article (if it can) for later
-     processing. Assumes ownership of it if it takes it. */
-bool cxnQueueArticle (Connection cxn, Article art)
-{
-    return ProcessArticle (cxn,art,true);
-}
-
-/* generate a syslog message for the connections activity. Called by Host. */
-void cxnLogStats (Connection cxn, bool final)
-{
-  const char *peerName ;
-  time_t now = theTime() ;
-  int total, good, bad;
-
-  ASSERT (cxn != NULL) ;
-
-  peerName = hostPeerName (cxn->myHost) ;
-
-  total = cxn->lmtp_succeeded + cxn->lmtp_failed;
-  total += cxn->cancel_succeeded + cxn->cancel_failed;
-  total += cxn->create_succeeded + cxn->create_failed;
-  total += cxn->remove_succeeded + cxn->remove_failed;
-
-  good = cxn->lmtp_succeeded;
-  good += cxn->cancel_succeeded;
-  good += cxn->create_succeeded;
-  good += cxn->remove_succeeded;
-
-  bad = cxn->lmtp_failed;
-  bad += cxn->cancel_failed;
-  bad += cxn->create_failed;
-  bad += cxn->remove_failed;
-  notice ("%s:%d %s seconds %ld accepted %d refused %d rejected %d",
-          peerName, cxn->ident, (final ? "final" : "checkpoint"),
-          (long) (now - cxn->timeCon), total, 0, bad);
-  show_stats(cxn);
-
-  if (final) {
-      cxn->lmtp_succeeded   = 0;
-      cxn->lmtp_failed     = 0;
-      cxn->cancel_succeeded = 0;
-      cxn->cancel_failed   = 0;
-      cxn->create_succeeded = 0;
-      cxn->create_failed   = 0;
-      cxn->remove_succeeded = 0;
-      cxn->remove_failed   = 0;
-
-      if (cxn->timeCon > 0)
-        cxn->timeCon = theTime() ;
-    }
-
-}
-
-  /* return the number of articles the connection can be given. This lets
-     the host shovel in as many as possible. May be zero. */
-size_t cxnQueueSpace (Connection cxn)
-{
-    int lmtpsize;
-    int imapsize;
-
-    lmtpsize = QueueSpace(&(cxn->lmtp_todeliver_q));
-    imapsize = QueueSpace(&(cxn->imap_controlMsg_q));
-
-    if (lmtpsize >=1) lmtpsize--;
-    if (imapsize >=1) imapsize--;
-
-    d_printf(1,"%s:%d Q Space lmtp size = %d state = %d\n",
-            hostPeerName (cxn->myHost), cxn->ident,
-            lmtpsize,cxn->lmtp_state);
-    d_printf(1,"%s:%d Q Space imap size = %d state = %d\n",
-            hostPeerName (cxn->myHost), cxn->ident,
-            imapsize,cxn->imap_state); 
-
-    /* return the smaller of our 2 queues */
-    if (lmtpsize < imapsize)
-       return lmtpsize;
-    else
-       return imapsize;
-}
-
-  /* adjust the mode no-CHECK filter values */
-void cxnSetCheckThresholds (Connection cxn,
-                           double lowFilter UNUSED,
-                           double highFilter UNUSED,
-                           double lowPassFilter UNUSED)
-{
-    d_printf(1,"%s:%d Threshold change. This means nothing to me\n",
-            hostPeerName (cxn->myHost), cxn->ident);
-}
-
-/* print some debugging info. */
-void gPrintCxnInfo (FILE *fp, unsigned int indentAmt)
-{
-  char indent [INDENT_BUFFER_SIZE] ;
-  unsigned int i ;
-  Connection cxn ;
-
-  for (i = 0 ; i < MIN(INDENT_BUFFER_SIZE - 1,indentAmt) ; i++)
-    indent [i] = ' ' ;
-  indent [i] = '\0' ;
-
-  fprintf (fp,"%sGlobal Connection list : (count %d) {\n",
-           indent,gCxnCount) ;
-  for (cxn = gCxnList ; cxn != NULL ; cxn = cxn->next)
-    printCxnInfo (cxn,fp,indentAmt + INDENT_INCR) ;
-  fprintf (fp,"%s}\n",indent) ;
-}
-
-void printCxnInfo (Connection cxn, FILE *fp, unsigned int indentAmt)
-{
-  char indent [INDENT_BUFFER_SIZE] ;
-  unsigned int i ;
-  article_queue_t *artH ;
-
-  for (i = 0 ; i < MIN(INDENT_BUFFER_SIZE - 1,indentAmt) ; i++)
-    indent [i] = ' ' ;
-  indent [i] = '\0' ;
-
-  fprintf (fp,"%sConnection : %p {\n",indent, (void *) cxn) ;
-  fprintf (fp,"%s    host : %p\n",indent, (void *) cxn->myHost) ;
-  fprintf (fp,"%s    endpoint (imap): %p\n",indent, (void *) cxn->imap_endpoint) ;
-  fprintf (fp,"%s    endpoint (lmtp): %p\n",indent, (void *) cxn->lmtp_endpoint) ;
-  fprintf (fp,"%s    state (imap) : %s\n",indent, imap_stateToString (cxn->imap_state)) ;
-  fprintf (fp,"%s    state (lmtp) : %s\n",indent, lmtp_stateToString (cxn->lmtp_state)) ;
-  fprintf (fp,"%s    ident : %d\n",indent,cxn->ident) ;
-  fprintf (fp,"%s    ip-name (imap): %s\n", indent, cxn->ServerName) ;
-  fprintf (fp,"%s    ip-name (lmtp): %s\n", indent, cxn->ServerName) ;
-  fprintf (fp,"%s    port-number (imap) : %d\n",indent,cxn->imap_port) ;
-  fprintf (fp,"%s    port-number (lmtp) : %d\n",indent,cxn->lmtp_port) ;
-
-  fprintf (fp,"%s    Issuing Quit : %d\n",indent, cxn->issue_quit) ;
-
-  fprintf (fp,"%s    time-connected (imap) : %ld\n",indent,(long) cxn->imap_timeCon) ;
-  fprintf (fp,"%s    time-connected (lmtp) : %ld\n",indent,(long) cxn->lmtp_timeCon) ;
-  fprintf (fp,"%s    articles from INN : %d\n",indent,
-          cxn->lmtp_succeeded+
-          cxn->lmtp_failed+
-          cxn->cancel_succeeded+
-          cxn->cancel_failed+
-          cxn->create_succeeded+
-          cxn->create_failed+
-          cxn->remove_succeeded+
-          cxn->remove_failed+
-          QueueSpace(&(cxn->lmtp_todeliver_q))+
-          QueueSpace(&(cxn->imap_controlMsg_q))
-          );
-  fprintf(fp,"%s    LMTP STATS: yes: %d no: %d\n",indent, 
-         cxn->lmtp_succeeded, cxn->lmtp_failed);
-  fprintf(fp,"%s    control:    yes: %d no: %d\n",indent, 
-         cxn->cancel_succeeded, cxn->cancel_failed);
-  fprintf(fp,"%s    create:     yes: %d no: %d\n",indent, 
-         cxn->create_succeeded, cxn->create_failed);
-  fprintf(fp,"%s    remove:     yes: %d no: %d\n",indent, 
-         cxn->remove_succeeded, cxn->remove_failed);
-
-  fprintf (fp,"%s    response-timeout : %d\n",indent,cxn->imap_readTimeout) ;
-  fprintf (fp,"%s    response-callback : %d\n",indent,cxn->imap_readBlockedTimerId) ;
-
-  fprintf (fp,"%s    write-timeout : %d\n",indent,cxn->imap_writeTimeout) ;
-  fprintf (fp,"%s    write-callback : %d\n",indent,cxn->imap_writeBlockedTimerId) ;
-
-  fprintf (fp,"%s    reopen wait : %d\n",indent,cxn->imap_sleepTimeout) ;
-  fprintf (fp,"%s    reopen id : %d\n",indent,cxn->imap_sleepTimerId) ;
-
-  fprintf (fp,"%s    IMAP queue {\n",indent) ;
-  for (artH = cxn->imap_controlMsg_q.head; artH != NULL ; artH = artH->next)
-    printArticleInfo (artH->data.article,fp,indentAmt + INDENT_INCR) ;
-  fprintf (fp,"%s    }\n",indent) ;
-
-  fprintf (fp,"%s    LMTP queue {\n",indent) ;
-  for (artH = cxn->lmtp_todeliver_q.head ; artH != NULL ; artH = artH->next)
-    printArticleInfo (artH->data.control->article,fp,indentAmt + INDENT_INCR) ;
-  fprintf (fp,"%s    }\n",indent) ;
-
-  fprintf (fp,"%s}\n",indent) ;
-}
-
-/* config file load callback */
-int cxnConfigLoadCbk (void *data UNUSED)
-{
-  long iv ;
-  int rval = 1 ;
-  FILE *fp = (FILE *) data ;
-
-  if (getInteger (topScope,"max-reconnect-time",&iv,NO_INHERIT))
-    {
-      if (iv < 1)
-        {
-          rval = 0 ;
-          logOrPrint (LOG_ERR,fp,
-                      "ME config: value of %s (%ld) in %s cannot be less"
-                      " than 1. Using %ld", "max-reconnect-time",
-                      iv,"global scope",(long) MAX_RECON_PER);
-          iv = MAX_RECON_PER ;
-        }
-    }
-  else
-    iv = MAX_RECON_PER ;
-  max_reconnect_period = (unsigned int) iv ;
-
-  if (getInteger (topScope,"initial-reconnect-time",&iv,NO_INHERIT))
-    {
-      if (iv < 1)
-        {
-          rval = 0 ;
-          logOrPrint (LOG_ERR,fp,
-                      "ME config: value of %s (%ld) in %s cannot be less"
-                      " than 1. Using %ld", "initial-reconnect-time",
-                      iv,"global scope",(long)INIT_RECON_PER);
-          iv = INIT_RECON_PER ;
-        }
-    }
-  else
-    iv = INIT_RECON_PER ;
-  init_reconnect_period = (unsigned int) iv ;
-
-  return rval ;
-}
-
-/* check connection state is in cxnWaitingS, cxnConnectingS or cxnIdleS */
-bool cxnCheckstate (Connection cxn)
-{
-    d_printf(5, "%s:%d Being asked to check state\n",
-            hostPeerName (cxn->myHost), cxn->ident);
-
-    /* return false if either connection is doing something */
-    if (cxn->imap_state > IMAP_IDLE_AUTHED) return false;
-    if (cxn->lmtp_state > LMTP_AUTHED_IDLE) return false;
-
-    return true;
-}