CVS commit by ossi: refactoring. main part is killing struct imap_cmd_cb as such. issue_imap_cmd is split into new_imap_cmd and submit_imap_cmd, so the command can be parametrized after it was instanciated.
M +109 -119 drv_imap.c 1.39 --- isync/src/drv_imap.c #1.38:1.39 @@ -127,19 +127,20 @@ typedef struct imap_store { } imap_store_t; -struct imap_cmd_cb { - int (*cont)( imap_store_t *ctx, struct imap_cmd *cmd, const char *prompt ); - void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response); - void *ctx; - char *data; - int dlen; - int uid; - unsigned create:1, trycreate:1; -}; - struct imap_cmd { struct imap_cmd *next; - struct imap_cmd_cb cb; char *cmd; int tag; + + struct { + int (*cont)( imap_store_t *ctx, struct imap_cmd *cmd, const char *prompt ); + void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response ); + void *aux; + char *data; + int data_len; + int uid; /* to identify fetch responses */ + unsigned + create:1, /* create the mailbox if we get an error ... */ + trycreate:1; /* ... but only if this is true or the server says so. */ + } param; }; @@ -476,26 +477,28 @@ buffer_gets( buffer_t * b, char **s ) static struct imap_cmd * -v_issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb, +new_imap_cmd( void ) +{ + struct imap_cmd *cmd = nfmalloc( sizeof(*cmd) ); + memset( &cmd->param, 0, sizeof(cmd->param) ); + return cmd; +} + +static struct imap_cmd * +v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, const char *fmt, va_list ap ) { - struct imap_cmd *cmd; int n, bufl; char buf[1024]; - cmd = nfmalloc( sizeof(struct imap_cmd) ); - nfvasprintf( &cmd->cmd, fmt, ap ); - cmd->tag = ++ctx->nexttag; - - if (cb) - cmd->cb = *cb; - else - memset( &cmd->cb, 0, sizeof(cmd->cb) ); - while (ctx->literal_pending) get_cmd_result( ctx, 0 ); - bufl = nfsnprintf( buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ? + if (!cmd) + cmd = new_imap_cmd(); + cmd->tag = ++ctx->nexttag; + nfvasprintf( &cmd->cmd, fmt, ap ); + bufl = nfsnprintf( buf, sizeof(buf), cmd->param.data ? CAP(LITERALPLUS) ? "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n", - cmd->tag, cmd->cmd, cmd->cb.dlen ); + cmd->tag, cmd->cmd, cmd->param.data_len ); if (DFlags & VERBOSE) { if (ctx->num_in_progress) @@ -507,15 +510,15 @@ v_issue_imap_cmd( imap_store_t *ctx, str } if (socket_write( &ctx->buf.sock, buf, bufl ) != bufl) { + if (cmd->param.data) + free( cmd->param.data ); free( cmd->cmd ); free( cmd ); - if (cb && cb->data) - free( cb->data ); return NULL; } - if (cmd->cb.data) { + if (cmd->param.data) { if (CAP(LITERALPLUS)) { - n = socket_write( &ctx->buf.sock, cmd->cb.data, cmd->cb.dlen ); - free( cmd->cb.data ); - if (n != cmd->cb.dlen || + n = socket_write( &ctx->buf.sock, cmd->param.data, cmd->param.data_len ); + free( cmd->param.data ); + if (n != cmd->param.data_len || (n = socket_write( &ctx->buf.sock, "\r\n", 2 )) != 2) { @@ -524,8 +527,8 @@ v_issue_imap_cmd( imap_store_t *ctx, str return NULL; } - cmd->cb.data = 0; + cmd->param.data = 0; } else ctx->literal_pending = 1; - } else if (cmd->cb.cont) + } else if (cmd->param.cont) ctx->literal_pending = 1; cmd->next = 0; @@ -537,17 +540,5 @@ v_issue_imap_cmd( imap_store_t *ctx, str static struct imap_cmd * -issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... ) -{ - struct imap_cmd *ret; - va_list ap; - - va_start( ap, fmt ); - ret = v_issue_imap_cmd( ctx, cb, fmt, ap ); - va_end( ap ); - return ret; -} - -static struct imap_cmd * -issue_imap_cmd_w( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... ) +submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, const char *fmt, ... ) { struct imap_cmd *ret; @@ -555,20 +546,16 @@ issue_imap_cmd_w( imap_store_t *ctx, str va_start( ap, fmt ); - ret = v_issue_imap_cmd( ctx, cb, fmt, ap ); + ret = v_submit_imap_cmd( ctx, cmd, fmt, ap ); va_end( ap ); - while (ctx->num_in_progress > max_in_progress || - socket_pending( &ctx->buf.sock )) - get_cmd_result( ctx, 0 ); return ret; } static int -imap_exec( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... ) +imap_exec( imap_store_t *ctx, struct imap_cmd *cmdp, const char *fmt, ... ) { va_list ap; - struct imap_cmd *cmdp; va_start( ap, fmt ); - cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap ); + cmdp = v_submit_imap_cmd( ctx, cmdp, fmt, ap ); va_end( ap ); if (!cmdp) @@ -579,11 +566,10 @@ imap_exec( imap_store_t *ctx, struct ima static int -imap_exec_b( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... ) +imap_exec_b( imap_store_t *ctx, struct imap_cmd *cmdp, const char *fmt, ... ) { va_list ap; - struct imap_cmd *cmdp; va_start( ap, fmt ); - cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap ); + cmdp = v_submit_imap_cmd( ctx, cmdp, fmt, ap ); va_end( ap ); if (!cmdp) @@ -598,11 +584,10 @@ imap_exec_b( imap_store_t *ctx, struct i static int -imap_exec_m( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... ) +imap_exec_m( imap_store_t *ctx, struct imap_cmd *cmdp, const char *fmt, ... ) { va_list ap; - struct imap_cmd *cmdp; va_start( ap, fmt ); - cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap ); + cmdp = v_submit_imap_cmd( ctx, cmdp, fmt, ap ); va_end( ap ); if (!cmdp) @@ -625,4 +610,12 @@ drain_imap_replies( imap_store_t *ctx ) */ +static void +process_imap_replies( imap_store_t *ctx ) +{ + while (ctx->num_in_progress > max_in_progress || + socket_pending( &ctx->buf.sock )) + get_cmd_result( ctx, 0 ); +} + static int is_atom( list_t *list ) @@ -839,5 +832,5 @@ parse_fetch( imap_store_t *ctx, char *cm if (body) { for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) - if (cmdp->cb.uid == uid) + if (cmdp->param.uid == uid) goto gotuid; error( "IMAP error: unexpected FETCH response (UID %d)\n", uid ); @@ -845,5 +838,5 @@ parse_fetch( imap_store_t *ctx, char *cm return -1; gotuid: - msgdata = (msg_data_t *)cmdp->cb.ctx; + msgdata = (msg_data_t *)cmdp->param.aux; msgdata->data = body; msgdata->len = size; @@ -881,5 +874,5 @@ parse_capability( imap_store_t *ctx, cha static int -parse_response_code( imap_store_t *ctx, struct imap_cmd_cb *cb, char *s ) +parse_response_code( imap_store_t *ctx, struct imap_cmd *cmd, char *s ) { char *arg, *earg, *p; @@ -914,8 +907,8 @@ parse_response_code( imap_store_t *ctx, for (; isspace( (unsigned char)*p ); p++); error( "*** IMAP ALERT *** %s\n", p ); - } else if (cb && cb->ctx && !strcmp( "APPENDUID", arg )) { + } else if (cmd && cmd->param.aux && !strcmp( "APPENDUID", arg )) { if (!(arg = next_arg( &s )) || (ctx->gen.uidvalidity = strtoll( arg, &earg, 10 ), *earg) || - !(arg = next_arg( &s )) || !(*(int *)cb->ctx = atoi( arg ))) + !(arg = next_arg( &s )) || !(*(int *)cmd->param.aux = atoi( arg ))) { error( "IMAP error: malformed APPENDUID status\n" ); @@ -948,6 +941,6 @@ parse_search( imap_store_t *ctx, char *c */ for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) - if (cmdp->cb.uid == -1) { - *(int *)cmdp->cb.ctx = uid; + if (cmdp->param.uid == -1) { + *(int *)cmdp->param.aux = uid; return; } @@ -1035,12 +1028,12 @@ get_cmd_result( imap_store_t *ctx, struc cmdp = (struct imap_cmd *)((char *)ctx->in_progress_append - offsetof(struct imap_cmd, next)); - if (cmdp->cb.data) { - n = socket_write( &ctx->buf.sock, cmdp->cb.data, cmdp->cb.dlen ); - free( cmdp->cb.data ); - cmdp->cb.data = 0; - if (n != (int)cmdp->cb.dlen) + if (cmdp->param.data) { + n = socket_write( &ctx->buf.sock, cmdp->param.data, cmdp->param.data_len ); + free( cmdp->param.data ); + cmdp->param.data = 0; + if (n != (int)cmdp->param.data_len) return RESP_BAD; - } else if (cmdp->cb.cont) { - if (cmdp->cb.cont( ctx, cmdp, cmd )) + } else if (cmdp->param.cont) { + if (cmdp->param.cont( ctx, cmdp, cmd )) return RESP_BAD; } else { @@ -1050,5 +1043,5 @@ get_cmd_result( imap_store_t *ctx, struc if (socket_write( &ctx->buf.sock, "\r\n", 2 ) != 2) return RESP_BAD; - if (!cmdp->cb.cont) + if (!cmdp->param.cont) ctx->literal_pending = 0; if (!tcmd) @@ -1065,5 +1058,5 @@ get_cmd_result( imap_store_t *ctx, struc ctx->in_progress_append = pcmdp; ctx->num_in_progress--; - if (cmdp->cb.cont || cmdp->cb.data) + if (cmdp->param.cont || cmdp->param.data) ctx->literal_pending = 0; arg = next_arg( &cmd ); @@ -1072,7 +1065,7 @@ get_cmd_result( imap_store_t *ctx, struc else { if (!strcmp( "NO", arg )) { - if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT, APPEND or UID COPY */ + if (cmdp->param.create && cmd && (cmdp->param.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT, APPEND or UID COPY */ p = strchr( cmdp->cmd, '"' ); - if (!issue_imap_cmd( ctx, 0, "CREATE %.*s", strchr( p + 1, '"' ) - p + 1, p )) { + if (!submit_imap_cmd( ctx, 0, "CREATE %.*s", strchr( p + 1, '"' ) - p + 1, p )) { resp = RESP_BAD; goto normal; @@ -1080,6 +1073,8 @@ get_cmd_result( imap_store_t *ctx, struc /* not waiting here violates the spec, but a server that does not grok this nonetheless violates it too. */ - cmdp->cb.create = 0; - if (!(ncmdp = issue_imap_cmd( ctx, &cmdp->cb, "%s", cmdp->cmd ))) { + ncmdp = nfmalloc( sizeof(*ncmdp) ); + memcpy( &ncmdp->param, &cmdp->param, sizeof(cmdp->param) ); + ncmdp->param.create = 0; + if (!submit_imap_cmd( ctx, ncmdp, "%s", cmdp->cmd )) { resp = RESP_BAD; goto normal; @@ -1100,11 +1095,11 @@ get_cmd_result( imap_store_t *ctx, struc arg, cmd ? cmd : "" ); } - if ((resp2 = parse_response_code( ctx, &cmdp->cb, cmd )) > resp) + if ((resp2 = parse_response_code( ctx, cmdp, cmd )) > resp) resp = resp2; normal: - if (cmdp->cb.done) - cmdp->cb.done( ctx, cmdp, resp ); - if (cmdp->cb.data) - free( cmdp->cb.data ); + if (cmdp->param.done) + cmdp->param.done( ctx, cmdp, resp ); + if (cmdp->param.data) + free( cmdp->param.data ); free( cmdp->cmd ); free( cmdp ); @@ -1274,5 +1269,5 @@ do_cram_auth( imap_store_t *ctx, struct if (n != l) return -1; - cmdp->cb.cont = 0; + cmdp->param.cont = 0; return 0; } @@ -1452,10 +1447,9 @@ imap_open_store( store_conf_t *conf, #if HAVE_LIBSSL if (CAP(CRAM)) { - struct imap_cmd_cb cbd; + struct imap_cmd *cmd = new_imap_cmd(); info( "Authenticating with CRAM-MD5\n" ); - memset( &cbd, 0, sizeof(cbd) ); - cbd.cont = do_cram_auth; - if (imap_exec( ctx, &cbd, "AUTHENTICATE CRAM-MD5" ) != RESP_OK) + cmd->param.cont = do_cram_auth; + if (imap_exec( ctx, cmd, "AUTHENTICATE CRAM-MD5" ) != RESP_OK) goto bail; } else if (srvc->require_cram) { @@ -1526,7 +1520,7 @@ imap_select( store_t *gctx, int minuid, { imap_store_t *ctx = (imap_store_t *)gctx; + struct imap_cmd *cmd = new_imap_cmd(); const char *prefix; int ret, i, j, bl; - struct imap_cmd_cb cbd; char buf[1000]; @@ -1540,8 +1534,7 @@ imap_select( store_t *gctx, int minuid, } - memset( &cbd, 0, sizeof(cbd) ); - cbd.create = (gctx->opts & OPEN_CREATE) != 0; - cbd.trycreate = 1; - if ((ret = imap_exec_b( ctx, &cbd, "SELECT \"%s%s\"", prefix, gctx->name )) != DRV_OK) + cmd->param.create = (gctx->opts & OPEN_CREATE) != 0; + cmd->param.trycreate = 1; + if ((ret = imap_exec_b( ctx, cmd, "SELECT \"%s%s\"", prefix, gctx->name )) != DRV_OK) goto bail; @@ -1585,10 +1578,8 @@ imap_fetch_msg( store_t *ctx, message_t int (*cb)( int sts, void *aux ), void *aux ) { - struct imap_cmd_cb cbd; - - memset( &cbd, 0, sizeof(cbd) ); - cbd.uid = msg->uid; - cbd.ctx = data; - return cb( imap_exec_m( (imap_store_t *)ctx, &cbd, "UID FETCH %d (%sBODY.PEEK[])", + struct imap_cmd *cmd = new_imap_cmd(); + cmd->param.uid = msg->uid; + cmd->param.aux = data; + return cb( imap_exec_m( (imap_store_t *)ctx, cmd, "UID FETCH %d (%sBODY.PEEK[])", msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " ), aux ); } @@ -1618,5 +1609,8 @@ imap_flags_helper( imap_store_t *ctx, in buf[imap_make_flags( flags, buf )] = 0; - return issue_imap_cmd_w( ctx, 0, "UID STORE %d %cFLAGS.SILENT %s", uid, what, buf ) ? DRV_OK : DRV_STORE_BAD; + if (!submit_imap_cmd( ctx, 0, "UID STORE %d %cFLAGS.SILENT %s", uid, what, buf )) + return DRV_STORE_BAD; + process_imap_replies( ctx ); + return DRV_OK; } @@ -1653,9 +1647,7 @@ imap_trash_msg( store_t *gctx, message_t { imap_store_t *ctx = (imap_store_t *)gctx; - struct imap_cmd_cb cbd; - - memset( &cbd, 0, sizeof(cbd) ); - cbd.create = 1; - return cb( imap_exec_m( ctx, &cbd, "UID COPY %d \"%s%s\"", + struct imap_cmd *cmd = new_imap_cmd(); + cmd->param.create = 1; + return cb( imap_exec_m( ctx, cmd, "UID COPY %d \"%s%s\"", msg->uid, ctx->prefix, gctx->conf->trash ), aux ); } @@ -1666,5 +1658,5 @@ imap_store_msg( store_t *gctx, msg_data_ { imap_store_t *ctx = (imap_store_t *)gctx; - struct imap_cmd_cb cbd; + struct imap_cmd *cmd = new_imap_cmd(); const char *prefix, *box; int ret, d, uid; @@ -1678,8 +1670,7 @@ imap_store_msg( store_t *gctx, msg_data_ flagstr[d] = 0; - memset( &cbd, 0, sizeof(cbd) ); - cbd.dlen = data->len; - cbd.data = data->data; - cbd.ctx = &uid; + cmd->param.data_len = data->len; + cmd->param.data = data->data; + cmd->param.aux = &uid; uid = -2; @@ -1687,5 +1678,5 @@ imap_store_msg( store_t *gctx, msg_data_ box = gctx->conf->trash; prefix = ctx->prefix; - cbd.create = 1; + cmd->param.create = 1; if (ctx->trashnc) ctx->caps = ctx->rcaps & ~(1 << LITERALPLUS); @@ -1693,9 +1684,9 @@ imap_store_msg( store_t *gctx, msg_data_ box = gctx->name; prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix; - cbd.create = (gctx->opts & OPEN_CREATE) != 0; + cmd->param.create = (gctx->opts & OPEN_CREATE) != 0; /*if (ctx->currentnc) ctx->caps = ctx->rcaps & ~(1 << LITERALPLUS);*/ } - ret = imap_exec_m( ctx, &cbd, "APPEND \"%s%s\" %s", prefix, box, flagstr ); + ret = imap_exec_m( ctx, cmd, "APPEND \"%s%s\" %s", prefix, box, flagstr ); ctx->caps = ctx->rcaps; if (ret != DRV_OK) @@ -1715,12 +1706,11 @@ imap_find_msg( store_t *gctx, const char { imap_store_t *ctx = (imap_store_t *)gctx; - struct imap_cmd_cb cbd; + struct imap_cmd *cmd = new_imap_cmd(); int ret, uid; - memset( &cbd, 0, sizeof(cbd) ); - cbd.uid = -1; /* we're looking for a UID */ - cbd.ctx = &uid; + cmd->param.uid = -1; /* we're looking for a UID */ + cmd->param.aux = &uid; uid = -1; /* in case we get no SEARCH response at all */ - if ((ret = imap_exec_m( ctx, &cbd, "UID SEARCH HEADER X-TUID %." stringify(TUIDL) "s", tuid )) != DRV_OK) + if ((ret = imap_exec_m( ctx, cmd, "UID SEARCH HEADER X-TUID %." stringify(TUIDL) "s", tuid )) != DRV_OK) return cb( ret, -1, aux ); else ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel