static int nfsnprintf( char *buf, int blen, const char *fmt, ... );
 
+static int nfvasprintf(char **strp, const char *fmt, va_list ap)
+{
+       int len;
+       char tmp[8192];
+
+       len = vsnprintf(tmp, sizeof(tmp), fmt, ap);
+       if (len < 0)
+               die("Fatal: Out of memory\n");
+       if (len >= sizeof(tmp))
+               die("imap command overflow !\n");
+       *strp = xmemdupz(tmp, len);
+       return len;
+}
 
 static void arc4_init( void );
 static unsigned char arc4_getbyte( void );
 static int
 socket_read( Socket_t *sock, char *buf, int len )
 {
-       int n = xread( sock->fd, buf, len );
+       ssize_t n = xread( sock->fd, buf, len );
        if (n <= 0) {
                socket_perror( "read", sock, n );
                close( sock->fd );
 static int
 socket_write( Socket_t *sock, const char *buf, int len )
 {
-       int n = write( sock->fd, buf, len );
+       int n = write_in_full( sock->fd, buf, len );
        if (n != len) {
                socket_perror( "write", sock, n );
                close( sock->fd );
        if (socket_write( &imap->buf.sock, buf, bufl ) != bufl) {
                free( cmd->cmd );
                free( cmd );
-               if (cb && cb->data)
+               if (cb)
                        free( cb->data );
                return NULL;
        }
                                        goto bail;
                        cur->len = s - p;
                        s++;
-                       cur->val = xmalloc( cur->len + 1 );
-                       memcpy( cur->val, p, cur->len );
-                       cur->val[cur->len] = 0;
+                       cur->val = xmemdupz(p, cur->len);
                } else {
                        /* atom */
                        p = s;
                                if (level && *s == ')')
                                        break;
                        cur->len = s - p;
-                       if (cur->len == 3 && !memcmp ("NIL", p, 3))
+                       if (cur->len == 3 && !memcmp ("NIL", p, 3)) {
                                cur->val = NIL;
-                       else {
-                               cur->val = xmalloc( cur->len + 1 );
-                               memcpy( cur->val, p, cur->len );
-                               cur->val[cur->len] = 0;
+                       } else {
+                               cur->val = xmemdupz(p, cur->len);
                        }
                }
 
                  normal:
                        if (cmdp->cb.done)
                                cmdp->cb.done( ctx, cmdp, resp );
-                       if (cmdp->cb.data)
-                               free( cmdp->cb.data );
+                       free( cmdp->cb.data );
                        free( cmdp->cmd );
                        free( cmdp );
                        if (!tcmd || tcmd == cmdp)
 static int
 read_message( FILE *f, msg_data_t *msg )
 {
-       int len, r;
+       struct strbuf buf;
 
-       memset( msg, 0, sizeof *msg );
-       len = CHUNKSIZE;
-       msg->data = xmalloc( len+1 );
-       msg->data[0] = 0;
-
-       while(!feof( f )) {
-               if (msg->len >= len) {
-                       void *p;
-                       len += CHUNKSIZE;
-                       p = xrealloc(msg->data, len+1);
-                       if (!p)
-                               break;
-                       msg->data = p;
-               }
-               r = fread( &msg->data[msg->len], 1, len - msg->len, f );
-               if (r <= 0)
+       memset(msg, 0, sizeof(*msg));
+       strbuf_init(&buf, 0);
+
+       do {
+               if (strbuf_fread(&buf, CHUNKSIZE, f) <= 0)
                        break;
-               msg->len += r;
-       }
-       msg->data[msg->len] = 0;
+       } while (!feof(f));
+
+       msg->len  = buf.len;
+       msg->data = strbuf_detach(&buf, NULL);
        return msg->len;
 }
 
        char *p = msg->data;
 
        while (1) {
-               if (!strncmp( "From ", p, 5 )) {
+               if (!prefixcmp(p, "From ")) {
                        count++;
                        p += 5;
                }
        data = &all_msgs->data[ *ofs ];
        msg->len = all_msgs->len - *ofs;
 
-       if (msg->len < 5 || strncmp( data, "From ", 5 ))
+       if (msg->len < 5 || prefixcmp(data, "From "))
                return 0;
 
        p = strchr( data, '\n' );
        if (p)
                msg->len = &p[1] - data;
 
-       msg->data = xmalloc( msg->len + 1 );
-       if (!msg->data)
-               return 0;
-
-       memcpy( msg->data, data, msg->len );
-       msg->data[ msg->len ] = 0;
-
+       msg->data = xmemdupz(data, msg->len);
        *ofs += msg->len;
-       return 1;
+       return 1;
 }
 
 static imap_server_conf_t server =
 static char *imap_folder;
 
 static int
-git_imap_config(const char *key, const char *val)
+git_imap_config(const char *key, const char *val, void *cb)
 {
        char imap_key[] = "imap.";
 
        if (strncmp( key, imap_key, sizeof imap_key - 1 ))
                return 0;
+
+       if (!val)
+               return config_error_nonbool(key);
+
        key += sizeof imap_key - 1;
 
        if (!strcmp( "folder", key )) {
                imap_folder = xstrdup( val );
        } else if (!strcmp( "host", key )) {
                {
-                       if (!strncmp( "imap:", val, 5 ))
+                       if (!prefixcmp(val, "imap:"))
                                val += 5;
                        if (!server.port)
                                server.port = 143;
                }
-               if (!strncmp( "//", val, 2 ))
+               if (!prefixcmp(val, "//"))
                        val += 2;
                server.host = xstrdup( val );
        }
        /* init the random number generator */
        arc4_init();
 
-       git_config( git_imap_config );
+       git_config(git_imap_config, NULL);
 
        if (!imap_folder) {
                fprintf( stderr, "no imap store specified\n" );
                return 1;
        }
+       if (!server.host) {
+               if (!server.tunnel) {
+                       fprintf( stderr, "no imap host specified\n" );
+                       return 1;
+               }
+               server.host = "tunnel";
+       }
 
        /* read the messages */
        if (!read_message( stdin, &all_msgs )) {