make the driver model, sync_chans() and sync_boxes() fully async.
async drivers to follow ...
This commit is contained in:
parent
bdcc285403
commit
168e5f3282
181
src/drv_imap.c
181
src/drv_imap.c
|
@ -1199,8 +1199,9 @@ do_cram_auth( imap_store_t *ctx, struct imap_cmd *cmdp, const char *prompt )
|
|||
}
|
||||
#endif
|
||||
|
||||
static store_t *
|
||||
imap_open_store( store_conf_t *conf )
|
||||
static void
|
||||
imap_open_store( store_conf_t *conf,
|
||||
void (*cb)( store_t *srv, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_conf_t *cfg = (imap_store_conf_t *)conf;
|
||||
imap_server_conf_t *srvc = cfg->server;
|
||||
|
@ -1367,12 +1368,12 @@ imap_open_store( store_conf_t *conf )
|
|||
}
|
||||
#if HAVE_LIBSSL
|
||||
if (CAP(CRAM)) {
|
||||
struct imap_cmd_cb cb;
|
||||
struct imap_cmd_cb cbd;
|
||||
|
||||
info( "Authenticating with CRAM-MD5\n" );
|
||||
memset( &cb, 0, sizeof(cb) );
|
||||
cb.cont = do_cram_auth;
|
||||
if (imap_exec( ctx, &cb, "AUTHENTICATE CRAM-MD5" ) != RESP_OK)
|
||||
memset( &cbd, 0, sizeof(cbd) );
|
||||
cbd.cont = do_cram_auth;
|
||||
if (imap_exec( ctx, &cbd, "AUTHENTICATE CRAM-MD5" ) != RESP_OK)
|
||||
goto bail;
|
||||
} else if (srvc->require_cram) {
|
||||
error( "IMAP error: CRAM-MD5 authentication is not supported by server\n" );
|
||||
|
@ -1402,8 +1403,10 @@ imap_open_store( store_conf_t *conf )
|
|||
else if (cfg->use_namespace && CAP(NAMESPACE)) {
|
||||
/* get NAMESPACE info */
|
||||
if (!ctx->got_namespace) {
|
||||
if (imap_exec( ctx, 0, "NAMESPACE" ) != RESP_OK)
|
||||
goto bail;
|
||||
if (imap_exec( ctx, 0, "NAMESPACE" ) != RESP_OK) {
|
||||
cb( 0, aux );
|
||||
return;
|
||||
}
|
||||
ctx->got_namespace = 1;
|
||||
}
|
||||
/* XXX for now assume personal namespace */
|
||||
|
@ -1413,11 +1416,13 @@ imap_open_store( store_conf_t *conf )
|
|||
ctx->prefix = ctx->ns_personal->child->child->val;
|
||||
}
|
||||
ctx->trashnc = 1;
|
||||
return &ctx->gen;
|
||||
cb( &ctx->gen, aux );
|
||||
return;
|
||||
|
||||
bail:
|
||||
imap_cancel_store( &ctx->gen );
|
||||
return 0;
|
||||
cb( 0, aux );
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1433,13 +1438,14 @@ imap_prepare_opts( store_t *gctx, int opts )
|
|||
gctx->opts = opts;
|
||||
}
|
||||
|
||||
static int
|
||||
imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
||||
static void
|
||||
imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
const char *prefix;
|
||||
int ret, i, j, bl;
|
||||
struct imap_cmd_cb cb;
|
||||
struct imap_cmd_cb cbd;
|
||||
char buf[1000];
|
||||
|
||||
|
||||
|
@ -1451,10 +1457,10 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|||
prefix = ctx->prefix;
|
||||
}
|
||||
|
||||
memset( &cb, 0, sizeof(cb) );
|
||||
cb.create = (gctx->opts & OPEN_CREATE) != 0;
|
||||
cb.trycreate = 1;
|
||||
if ((ret = imap_exec_b( ctx, &cb, "SELECT \"%s%s\"", prefix, gctx->name )) != DRV_OK)
|
||||
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)
|
||||
goto bail;
|
||||
|
||||
if (gctx->count) {
|
||||
|
@ -1489,19 +1495,20 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|||
bail:
|
||||
if (excs)
|
||||
free( excs );
|
||||
return ret;
|
||||
cb( ret, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data )
|
||||
static void
|
||||
imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
struct imap_cmd_cb cb;
|
||||
struct imap_cmd_cb cbd;
|
||||
|
||||
memset( &cb, 0, sizeof(cb) );
|
||||
cb.uid = msg->uid;
|
||||
cb.ctx = data;
|
||||
return imap_exec_m( (imap_store_t *)ctx, &cb, "UID FETCH %d (%sBODY.PEEK[])",
|
||||
msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " );
|
||||
memset( &cbd, 0, sizeof(cbd) );
|
||||
cbd.uid = msg->uid;
|
||||
cbd.ctx = data;
|
||||
cb( imap_exec_m( (imap_store_t *)ctx, &cbd, "UID FETCH %d (%sBODY.PEEK[])",
|
||||
msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " ), aux );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1531,8 +1538,9 @@ imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags)
|
|||
return issue_imap_cmd_w( ctx, 0, "UID STORE %d %cFLAGS.SILENT %s", uid, what, buf ) ? DRV_OK : DRV_STORE_BAD;
|
||||
}
|
||||
|
||||
static int
|
||||
imap_set_flags( store_t *gctx, message_t *msg, int uid, int add, int del )
|
||||
static void
|
||||
imap_set_flags( store_t *gctx, message_t *msg, int uid, int add, int del,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
int ret;
|
||||
|
@ -1546,35 +1554,38 @@ imap_set_flags( store_t *gctx, message_t *msg, int uid, int add, int del )
|
|||
}
|
||||
if ((!add || (ret = imap_flags_helper( ctx, uid, '+', add )) == DRV_OK) &&
|
||||
(!del || (ret = imap_flags_helper( ctx, uid, '-', del )) == DRV_OK))
|
||||
return DRV_OK;
|
||||
return ret;
|
||||
ret = DRV_OK;
|
||||
cb( ret, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_close( store_t *ctx )
|
||||
static void
|
||||
imap_close( store_t *ctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
return imap_exec_b( (imap_store_t *)ctx, 0, "CLOSE" );
|
||||
cb( imap_exec_b( (imap_store_t *)ctx, 0, "CLOSE" ), aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_trash_msg( store_t *gctx, message_t *msg )
|
||||
static void
|
||||
imap_trash_msg( store_t *gctx, message_t *msg,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd_cb cb;
|
||||
struct imap_cmd_cb cbd;
|
||||
|
||||
memset( &cb, 0, sizeof(cb) );
|
||||
cb.create = 1;
|
||||
return imap_exec_m( ctx, &cb, "UID COPY %d \"%s%s\"",
|
||||
msg->uid, ctx->prefix, gctx->conf->trash );
|
||||
memset( &cbd, 0, sizeof(cbd) );
|
||||
cbd.create = 1;
|
||||
cb( imap_exec_m( ctx, &cbd, "UID COPY %d \"%s%s\"",
|
||||
msg->uid, ctx->prefix, gctx->conf->trash ), aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
|
||||
static void
|
||||
imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd_cb cb;
|
||||
struct imap_cmd_cb cbd;
|
||||
const char *prefix, *box;
|
||||
int ret, d;
|
||||
int ret, d, uid;
|
||||
char flagstr[128];
|
||||
|
||||
d = 0;
|
||||
|
@ -1584,71 +1595,82 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
|
|||
}
|
||||
flagstr[d] = 0;
|
||||
|
||||
memset( &cb, 0, sizeof(cb) );
|
||||
cb.dlen = data->len;
|
||||
cb.data = data->data;
|
||||
if (!uid) {
|
||||
memset( &cbd, 0, sizeof(cbd) );
|
||||
cbd.dlen = data->len;
|
||||
cbd.data = data->data;
|
||||
cbd.ctx = &uid;
|
||||
uid = -2;
|
||||
|
||||
if (to_trash) {
|
||||
box = gctx->conf->trash;
|
||||
prefix = ctx->prefix;
|
||||
cb.create = 1;
|
||||
cbd.create = 1;
|
||||
if (ctx->trashnc)
|
||||
ctx->caps = ctx->rcaps & ~(1 << LITERALPLUS);
|
||||
} else {
|
||||
box = gctx->name;
|
||||
prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix;
|
||||
cb.create = (gctx->opts & OPEN_CREATE) != 0;
|
||||
cbd.create = (gctx->opts & OPEN_CREATE) != 0;
|
||||
/*if (ctx->currentnc)
|
||||
ctx->caps = ctx->rcaps & ~(1 << LITERALPLUS);*/
|
||||
*uid = -2;
|
||||
}
|
||||
cb.ctx = uid;
|
||||
ret = imap_exec_m( ctx, &cb, "APPEND \"%s%s\" %s", prefix, box, flagstr );
|
||||
ret = imap_exec_m( ctx, &cbd, "APPEND \"%s%s\" %s", prefix, box, flagstr );
|
||||
ctx->caps = ctx->rcaps;
|
||||
if (ret != DRV_OK)
|
||||
return ret;
|
||||
if (!uid)
|
||||
if (ret != DRV_OK) {
|
||||
cb( ret, -1, aux );
|
||||
return;
|
||||
}
|
||||
if (to_trash)
|
||||
ctx->trashnc = 0;
|
||||
else {
|
||||
/*ctx->currentnc = 0;*/
|
||||
gctx->count++;
|
||||
}
|
||||
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, uid, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_find_msg( store_t *gctx, const char *tuid, int *uid )
|
||||
static void
|
||||
imap_find_msg( store_t *gctx, const char *tuid,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd_cb cb;
|
||||
int ret;
|
||||
struct imap_cmd_cb cbd;
|
||||
int ret, uid;
|
||||
|
||||
memset( &cb, 0, sizeof(cb) );
|
||||
cb.ctx = uid;
|
||||
cb.uid = -1; /* we're looking for a UID */
|
||||
*uid = -1; /* in case we get no SEARCH response at all */
|
||||
if ((ret = imap_exec_m( ctx, &cb, "UID SEARCH HEADER X-TUID %." stringify(TUIDL) "s", tuid )) != DRV_OK)
|
||||
return ret;
|
||||
return *uid < 0 ? DRV_MSG_BAD : DRV_OK;
|
||||
memset( &cbd, 0, sizeof(cbd) );
|
||||
cbd.uid = -1; /* we're looking for a UID */
|
||||
cbd.ctx = &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)
|
||||
cb( ret, -1, aux );
|
||||
else
|
||||
cb( uid <= 0 ? DRV_MSG_BAD : DRV_OK, uid, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_list( store_t *gctx )
|
||||
static void
|
||||
imap_list( store_t *gctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
int ret;
|
||||
|
||||
if ((ret = imap_exec_b( ctx, 0, "LIST \"\" \"%s%%\"", ctx->prefix )) == DRV_OK)
|
||||
gctx->listed = 1;
|
||||
return ret;
|
||||
cb( ret, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
imap_check( store_t *gctx )
|
||||
static void
|
||||
imap_cancel( store_t *gctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
(void) gctx;
|
||||
/* flush queue here */
|
||||
return DRV_OK;
|
||||
(void)gctx;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static void
|
||||
imap_commit( store_t *gctx )
|
||||
{
|
||||
(void)gctx;
|
||||
}
|
||||
|
||||
imap_server_conf_t *servers, **serverapp = &servers;
|
||||
|
@ -1797,6 +1819,7 @@ struct driver imap_driver = {
|
|||
imap_find_msg,
|
||||
imap_set_flags,
|
||||
imap_trash_msg,
|
||||
imap_check,
|
||||
imap_close
|
||||
imap_close,
|
||||
imap_cancel,
|
||||
imap_commit,
|
||||
};
|
||||
|
|
|
@ -93,20 +93,22 @@ maildir_parse_flags( const char *base )
|
|||
return flags;
|
||||
}
|
||||
|
||||
static store_t *
|
||||
maildir_open_store( store_conf_t *conf )
|
||||
static void
|
||||
maildir_open_store( store_conf_t *conf,
|
||||
void (*cb)( store_t *ctx, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx;
|
||||
struct stat st;
|
||||
|
||||
if (stat( conf->path, &st ) || !S_ISDIR(st.st_mode)) {
|
||||
error( "Maildir error: cannot open store %s\n", conf->path );
|
||||
return 0;
|
||||
cb( 0, aux );
|
||||
return;
|
||||
}
|
||||
ctx = nfcalloc( sizeof(*ctx) );
|
||||
ctx->gen.conf = conf;
|
||||
ctx->uvfd = -1;
|
||||
return &ctx->gen;
|
||||
cb( &ctx->gen, aux );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -159,15 +161,17 @@ maildir_cleanup_drv( void )
|
|||
{
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_list( store_t *gctx )
|
||||
static void
|
||||
maildir_list( store_t *gctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
|
||||
if (!(dir = opendir( gctx->conf->path ))) {
|
||||
error( "%s: %s\n", gctx->conf->path, strerror(errno) );
|
||||
return DRV_STORE_BAD;
|
||||
cb( DRV_STORE_BAD, aux );
|
||||
return;
|
||||
}
|
||||
while ((de = readdir( dir ))) {
|
||||
struct stat st;
|
||||
|
@ -183,7 +187,7 @@ maildir_list( store_t *gctx )
|
|||
closedir (dir);
|
||||
gctx->listed = 1;
|
||||
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static const char *subdirs[] = { "cur", "new", "tmp" };
|
||||
|
@ -760,8 +764,9 @@ maildir_prepare_opts( store_t *gctx, int opts )
|
|||
gctx->opts = opts;
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
||||
static void
|
||||
maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
message_t **msgapp;
|
||||
|
@ -777,14 +782,17 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|||
ctx->excs = nfrealloc( excs, nexcs * sizeof(int) );
|
||||
ctx->nexcs = nexcs;
|
||||
|
||||
if (maildir_validate( gctx->path, "", ctx->gen.opts & OPEN_CREATE ) != DRV_OK)
|
||||
return DRV_BOX_BAD;
|
||||
if (maildir_validate( gctx->path, "", ctx->gen.opts & OPEN_CREATE ) != DRV_OK) {
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
|
||||
nfsnprintf( uvpath, sizeof(uvpath), "%s/.uidvalidity", gctx->path );
|
||||
#ifndef USE_DB
|
||||
if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) < 0) {
|
||||
perror( uvpath );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if ((ctx->uvfd = open( uvpath, O_RDWR, 0600 )) < 0) {
|
||||
|
@ -799,7 +807,8 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|||
goto fnok;
|
||||
}
|
||||
perror( uvpath );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
dbok:
|
||||
#if SEEK_SET != 0
|
||||
|
@ -811,7 +820,8 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|||
bork:
|
||||
close( ctx->uvfd );
|
||||
ctx->uvfd = -1;
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
if (db_create( &ctx->db, 0, 0 )) {
|
||||
fputs( "Maildir error: db_create() failed\n", stderr );
|
||||
|
@ -841,14 +851,16 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|||
fnok:
|
||||
#endif /* USE_DB */
|
||||
|
||||
if (maildir_scan( ctx, &msglist ) != DRV_OK)
|
||||
return DRV_BOX_BAD;
|
||||
if (maildir_scan( ctx, &msglist ) != DRV_OK) {
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
msgapp = &ctx->gen.msgs;
|
||||
for (i = 0; i < msglist.nents; i++)
|
||||
maildir_app_msg( ctx, &msgapp, msglist.ents + i );
|
||||
maildir_free_scan( &msglist );
|
||||
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -916,8 +928,9 @@ maildir_again( maildir_store_t *ctx, maildir_message_t *msg, const char *fn )
|
|||
return (msg->gen.status & M_DEAD) ? DRV_MSG_BAD : DRV_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data )
|
||||
static void
|
||||
maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
maildir_message_t *msg = (maildir_message_t *)gmsg;
|
||||
|
@ -929,8 +942,10 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data )
|
|||
nfsnprintf( buf, sizeof(buf), "%s/%s/%s", gctx->path, subdirs[gmsg->status & M_RECENT], msg->base );
|
||||
if ((fd = open( buf, O_RDONLY )) >= 0)
|
||||
break;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK)
|
||||
return ret;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
fstat( fd, &st );
|
||||
data->len = st.st_size;
|
||||
|
@ -938,12 +953,13 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data )
|
|||
if (read( fd, data->data, data->len ) != data->len) {
|
||||
perror( buf );
|
||||
close( fd );
|
||||
return DRV_MSG_BAD;
|
||||
cb( DRV_MSG_BAD, aux );
|
||||
return;
|
||||
}
|
||||
close( fd );
|
||||
if (!(gmsg->status & M_FLAGS))
|
||||
data->flags = maildir_parse_flags( msg->base );
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -961,30 +977,34 @@ maildir_make_flags( int flags, char *buf )
|
|||
return d;
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_store_msg( store_t *gctx, msg_data_t *data, int *uid )
|
||||
static void
|
||||
maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
const char *prefix, *box;
|
||||
int ret, fd, bl;
|
||||
int ret, fd, bl, uid;
|
||||
char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[NUM_FLAGS + 3], base[128];
|
||||
|
||||
bl = nfsnprintf( base, sizeof(base), "%ld.%d_%d.%s", time( 0 ), Pid, ++MaildirCount, Hostname );
|
||||
if (uid) {
|
||||
if (!to_trash) {
|
||||
#ifdef USE_DB
|
||||
if (ctx->db) {
|
||||
if ((ret = maildir_set_uid( ctx, base, uid )) != DRV_OK) {
|
||||
if ((ret = maildir_set_uid( ctx, base, &uid )) != DRV_OK) {
|
||||
free( data->data );
|
||||
return ret;
|
||||
cb( ret, 0, aux );
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif /* USE_DB */
|
||||
{
|
||||
if ((ret = maildir_uidval_lock( ctx )) != DRV_OK ||
|
||||
(ret = maildir_obtain_uid( ctx, uid )) != DRV_OK)
|
||||
return ret;
|
||||
(ret = maildir_obtain_uid( ctx, &uid )) != DRV_OK) {
|
||||
cb( ret, 0, aux );
|
||||
return;
|
||||
}
|
||||
maildir_uidval_unlock( ctx );
|
||||
nfsnprintf( base + bl, sizeof(base) - bl, ",U=%d", *uid );
|
||||
nfsnprintf( base + bl, sizeof(base) - bl, ",U=%d", uid );
|
||||
}
|
||||
prefix = gctx->path;
|
||||
box = "";
|
||||
|
@ -999,16 +1019,19 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int *uid )
|
|||
if (errno != ENOENT) {
|
||||
perror( buf );
|
||||
free( data->data );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
if ((ret = maildir_validate( gctx->conf->path, gctx->conf->trash, gctx->opts & OPEN_CREATE )) != DRV_OK) {
|
||||
free( data->data );
|
||||
return ret;
|
||||
cb( ret, 0, aux );
|
||||
return;
|
||||
}
|
||||
if ((fd = open( buf, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) {
|
||||
perror( buf );
|
||||
free( data->data );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
ret = write( fd, data->data, data->len );
|
||||
|
@ -1019,35 +1042,37 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int *uid )
|
|||
else
|
||||
error( "Maildir error: %s: partial write\n", buf );
|
||||
close( fd );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
close( fd );
|
||||
nfsnprintf( nbuf, sizeof(nbuf), "%s%s/%s/%s%s", prefix, box, subdirs[!(data->flags & F_SEEN)], base, fbuf );
|
||||
if (rename( buf, nbuf )) {
|
||||
perror( nbuf );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
if (uid)
|
||||
gctx->count++;
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, uid, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_find_msg( store_t *gctx, const char *tuid, int *uid )
|
||||
static void
|
||||
maildir_find_msg( store_t *gctx, const char *tuid,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
message_t *msg;
|
||||
|
||||
/* using a hash table might turn out to be more appropriate ... */
|
||||
for (msg = gctx->msgs; msg; msg = msg->next)
|
||||
if (!(msg->status & M_DEAD) && !memcmp( ((maildir_message_t *)msg)->tuid, tuid, TUIDL )) {
|
||||
*uid = msg->uid;
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, msg->uid, aux );
|
||||
return;
|
||||
}
|
||||
return DRV_MSG_BAD;
|
||||
cb( DRV_MSG_BAD, -1, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del )
|
||||
static void
|
||||
maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
maildir_message_t *msg = (maildir_message_t *)gmsg;
|
||||
|
@ -1089,8 +1114,10 @@ maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del )
|
|||
}
|
||||
if (!rename( buf, nbuf ))
|
||||
break;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK)
|
||||
return ret;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
free( msg->base );
|
||||
msg->base = nfmalloc( tl + 1 );
|
||||
|
@ -1099,7 +1126,7 @@ maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del )
|
|||
msg->gen.flags &= ~del;
|
||||
gmsg->status &= ~M_RECENT;
|
||||
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
#ifdef USE_DB
|
||||
|
@ -1119,8 +1146,9 @@ maildir_purge_msg( maildir_store_t *ctx, const char *name )
|
|||
}
|
||||
#endif /* USE_DB */
|
||||
|
||||
static int
|
||||
maildir_trash_msg( store_t *gctx, message_t *gmsg )
|
||||
static void
|
||||
maildir_trash_msg( store_t *gctx, message_t *gmsg,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
maildir_message_t *msg = (maildir_message_t *)gmsg;
|
||||
|
@ -1137,30 +1165,38 @@ maildir_trash_msg( store_t *gctx, message_t *gmsg )
|
|||
if (!rename( buf, nbuf ))
|
||||
break;
|
||||
if (!stat( buf, &st )) {
|
||||
if ((ret = maildir_validate( gctx->conf->path, gctx->conf->trash, 1 )) != DRV_OK)
|
||||
return ret;
|
||||
if ((ret = maildir_validate( gctx->conf->path, gctx->conf->trash, 1 )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
if (!rename( buf, nbuf ))
|
||||
break;
|
||||
if (errno != ENOENT) {
|
||||
perror( nbuf );
|
||||
return DRV_BOX_BAD;
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK)
|
||||
return ret;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
gmsg->status |= M_DEAD;
|
||||
gctx->count--;
|
||||
|
||||
#ifdef USE_DB
|
||||
if (ctx->db)
|
||||
return maildir_purge_msg( ctx, msg->base );
|
||||
if (ctx->db) {
|
||||
cb( maildir_purge_msg( ctx, msg->base ), aux );
|
||||
return;
|
||||
}
|
||||
#endif /* USE_DB */
|
||||
return DRV_OK;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_close( store_t *gctx )
|
||||
static void
|
||||
maildir_close( store_t *gctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
#ifdef USE_DB
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
|
@ -1184,23 +1220,36 @@ maildir_close( store_t *gctx )
|
|||
msg->status |= M_DEAD;
|
||||
gctx->count--;
|
||||
#ifdef USE_DB
|
||||
if (ctx->db && (ret = maildir_purge_msg( ctx, ((maildir_message_t *)msg)->base )) != DRV_OK)
|
||||
return ret;
|
||||
if (ctx->db && (ret = maildir_purge_msg( ctx, ((maildir_message_t *)msg)->base )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
#endif /* USE_DB */
|
||||
}
|
||||
}
|
||||
if (!retry)
|
||||
return DRV_OK;
|
||||
if ((ret = maildir_rescan( (maildir_store_t *)gctx )) != DRV_OK)
|
||||
return ret;
|
||||
if (!retry) {
|
||||
cb( DRV_OK, aux );
|
||||
return;
|
||||
}
|
||||
if ((ret = maildir_rescan( (maildir_store_t *)gctx )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
maildir_check( store_t *gctx )
|
||||
static void
|
||||
maildir_cancel( store_t *gctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
(void)gctx;
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static void
|
||||
maildir_commit( store_t *gctx )
|
||||
{
|
||||
(void) gctx;
|
||||
return DRV_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1248,6 +1297,7 @@ struct driver maildir_driver = {
|
|||
maildir_find_msg,
|
||||
maildir_set_flags,
|
||||
maildir_trash_msg,
|
||||
maildir_check,
|
||||
maildir_close
|
||||
maildir_close,
|
||||
maildir_cancel,
|
||||
maildir_commit,
|
||||
};
|
||||
|
|
53
src/isync.h
53
src/isync.h
|
@ -166,9 +166,13 @@ typedef struct {
|
|||
} msg_data_t;
|
||||
|
||||
#define DRV_OK 0
|
||||
#define DRV_MSG_BAD -1
|
||||
#define DRV_BOX_BAD -2
|
||||
#define DRV_STORE_BAD -3
|
||||
#define DRV_MSG_BAD 1
|
||||
#define DRV_BOX_BAD 2
|
||||
#define DRV_STORE_BAD 3
|
||||
#define DRV_SERVER_BAD 4
|
||||
#define DRV_CANCELED 5
|
||||
|
||||
/* All memory belongs to the driver's user. */
|
||||
|
||||
#define DRV_CRLF 1
|
||||
|
||||
|
@ -178,21 +182,32 @@ struct driver {
|
|||
int flags;
|
||||
int (*parse_store)( conffile_t *cfg, store_conf_t **storep, int *err );
|
||||
void (*cleanup)( void );
|
||||
store_t *(*open_store)( store_conf_t *conf );
|
||||
void (*open_store)( store_conf_t *conf,
|
||||
void (*cb)( store_t *ctx, void *aux ), void *aux );
|
||||
void (*disown_store)( store_t *ctx );
|
||||
store_t *(*own_store)( store_conf_t *conf );
|
||||
void (*cancel_store)( store_t *ctx );
|
||||
int (*list)( store_t *ctx );
|
||||
void (*list)( store_t *ctx,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*prepare_paths)( store_t *ctx );
|
||||
void (*prepare_opts)( store_t *ctx, int opts );
|
||||
int (*select)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs );
|
||||
int (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data );
|
||||
int (*store_msg)( store_t *ctx, msg_data_t *data, int *uid ); /* if uid is null, store to trash */
|
||||
int (*find_msg)( store_t *ctx, const char *tuid, int *uid );
|
||||
int (*set_flags)( store_t *ctx, message_t *msg, int uid, int add, int del ); /* msg can be null, therefore uid as a fallback */
|
||||
int (*trash_msg)( store_t *ctx, message_t *msg ); /* This may expunge the original message immediately, but it needn't to */
|
||||
int (*check)( store_t *ctx ); /* IMAP-style: flush */
|
||||
int (*close)( store_t *ctx ); /* IMAP-style: expunge inclusive */
|
||||
void (*select)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux );
|
||||
void (*find_msg)( store_t *ctx, const char *tuid,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux );
|
||||
void (*set_flags)( store_t *ctx, message_t *msg, int uid, int add, int del, /* msg can be null, therefore uid as a fallback */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*trash_msg)( store_t *ctx, message_t *msg, /* This may expunge the original message immediately, but it needn't to */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*close)( store_t *ctx, /* IMAP-style: expunge inclusive */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*cancel)( store_t *ctx, /* only not yet sent commands */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*commit)( store_t *ctx );
|
||||
};
|
||||
|
||||
|
||||
|
@ -217,7 +232,6 @@ void debug( const char *, ... );
|
|||
void debugn( const char *, ... );
|
||||
void info( const char *, ... );
|
||||
void infon( const char *, ... );
|
||||
void infoc( char );
|
||||
void warn( const char *, ... );
|
||||
void error( const char *, ... );
|
||||
|
||||
|
@ -248,12 +262,15 @@ unsigned char arc4_getbyte( void );
|
|||
|
||||
extern const char *str_ms[2], *str_hl[2];
|
||||
|
||||
#define SYNC_OK 0
|
||||
#define SYNC_OK 0 /* assumed to be 0 */
|
||||
#define SYNC_FAIL 1
|
||||
#define SYNC_BAD(ms) (2+(ms))
|
||||
#define SYNC_NOGOOD 4 /* internal */
|
||||
#define SYNC_BAD(ms) (2<<(ms))
|
||||
#define SYNC_NOGOOD 8 /* internal */
|
||||
#define SYNC_CANCELED 16 /* internal */
|
||||
|
||||
int sync_boxes( store_t *ctx[], const char *names[], channel_conf_t * );
|
||||
/* All passed pointers must stay alive until cb is called. */
|
||||
void sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
|
||||
/* config.c */
|
||||
|
||||
|
|
222
src/main.c
222
src/main.c
|
@ -24,6 +24,7 @@
|
|||
#include "isync.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -198,7 +199,16 @@ typedef struct {
|
|||
unsigned done:1, skip:1, cben:1;
|
||||
} main_vars_t;
|
||||
|
||||
static void sync_chans( main_vars_t *mvars );
|
||||
#define AUX &mvars->t[t]
|
||||
#define MVARS(aux) \
|
||||
int t = *(int *)aux; \
|
||||
main_vars_t *mvars = (main_vars_t *)(((char *)(&((int *)aux)[-t])) - offsetof(main_vars_t, t));
|
||||
|
||||
#define E_START 0
|
||||
#define E_OPEN 1
|
||||
#define E_SYNC 2
|
||||
|
||||
static void sync_chans( main_vars_t *mvars, int ent );
|
||||
|
||||
int
|
||||
main( int argc, char **argv )
|
||||
|
@ -460,19 +470,36 @@ main( int argc, char **argv )
|
|||
break;
|
||||
}
|
||||
mvars->argv = argv;
|
||||
sync_chans( mvars );
|
||||
mvars->cben = 1;
|
||||
sync_chans( mvars, E_START );
|
||||
return mvars->ret;
|
||||
}
|
||||
|
||||
#define ST_FRESH 0
|
||||
#define ST_OPEN 1
|
||||
#define ST_CLOSED 2
|
||||
|
||||
static void store_opened( store_t *ctx, void *aux );
|
||||
static void store_listed( int sts, void *aux );
|
||||
static void done_sync_dyn( int sts, void *aux );
|
||||
static void done_sync( int sts, void *aux );
|
||||
|
||||
static void
|
||||
sync_chans( main_vars_t *mvars )
|
||||
sync_chans( main_vars_t *mvars, int ent )
|
||||
{
|
||||
group_conf_t *group;
|
||||
channel_conf_t *chan;
|
||||
store_t *store;
|
||||
string_list_t *mbox, *sbox, **mboxp, **sboxp;
|
||||
char *channame;
|
||||
int t;
|
||||
|
||||
if (!mvars->cben)
|
||||
return;
|
||||
switch (ent) {
|
||||
case E_OPEN: goto opened;
|
||||
case E_SYNC: goto syncone;
|
||||
}
|
||||
for (;;) {
|
||||
mvars->boxlist = 0;
|
||||
if (!mvars->all) {
|
||||
|
@ -503,36 +530,32 @@ sync_chans( main_vars_t *mvars )
|
|||
merge_actions( mvars->chan, mvars->ops, XOP_HAVE_CREATE, OP_CREATE, 0 );
|
||||
merge_actions( mvars->chan, mvars->ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 );
|
||||
|
||||
mvars->state[M] = mvars->state[S] = ST_FRESH;
|
||||
info( "Channel %s\n", mvars->chan->name );
|
||||
mvars->boxes[M] = mvars->boxes[S] = mvars->cboxes = 0;
|
||||
mvars->skip = mvars->cben = 0;
|
||||
for (t = 0; t < 2; t++) {
|
||||
mvars->drv[t] = mvars->chan->stores[t]->driver;
|
||||
mvars->ctx[t] = mvars->drv[t]->own_store( mvars->chan->stores[t] );
|
||||
if ((store = mvars->drv[t]->own_store( mvars->chan->stores[t] )))
|
||||
store_opened( store, AUX );
|
||||
}
|
||||
for (t = 0; t < 2; t++)
|
||||
if (!mvars->ctx[t]) {
|
||||
for (t = 0; t < 2 && !mvars->skip; t++)
|
||||
if (mvars->state[t] == ST_FRESH) {
|
||||
info( "Opening %s %s...\n", str_ms[t], mvars->chan->stores[t]->name );
|
||||
if (!(mvars->ctx[t] = mvars->drv[t]->open_store( mvars->chan->stores[t] ))) {
|
||||
mvars->ret = 1;
|
||||
mvars->drv[t]->open_store( mvars->chan->stores[t], store_opened, AUX );
|
||||
}
|
||||
mvars->cben = 1;
|
||||
opened:
|
||||
if (mvars->skip)
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
if (mvars->state[M] != ST_OPEN || mvars->state[S] != ST_OPEN)
|
||||
return;
|
||||
|
||||
if (mvars->boxlist)
|
||||
mvars->boxp = mvars->boxlist;
|
||||
else if (mvars->chan->patterns) {
|
||||
for (t = 0; t < 2; t++) {
|
||||
if (!mvars->ctx[t]->listed) {
|
||||
if (mvars->drv[t]->list( mvars->ctx[t] ) != DRV_OK) {
|
||||
screwt:
|
||||
mvars->drv[t]->cancel_store( mvars->ctx[t] );
|
||||
mvars->ctx[t] = 0;
|
||||
mvars->ret = 1;
|
||||
goto next;
|
||||
} else if (mvars->ctx[t]->conf->map_inbox)
|
||||
add_string_list( &mvars->ctx[t]->boxes, mvars->ctx[t]->conf->map_inbox );
|
||||
}
|
||||
mvars->boxes[t] = filter_boxes( mvars->ctx[t]->boxes, mvars->chan->patterns );
|
||||
}
|
||||
mvars->boxes[M] = filter_boxes( mvars->ctx[M]->boxes, mvars->chan->patterns );
|
||||
mvars->boxes[S] = filter_boxes( mvars->ctx[S]->boxes, mvars->chan->patterns );
|
||||
for (mboxp = &mvars->boxes[M]; (mbox = *mboxp); ) {
|
||||
for (sboxp = &mvars->boxes[S]; (sbox = *sboxp); sboxp = &sbox->next)
|
||||
if (!strcmp( sbox->string, mbox->string )) {
|
||||
|
@ -550,60 +573,70 @@ sync_chans( main_vars_t *mvars )
|
|||
|
||||
if (mvars->list && mvars->multiple)
|
||||
printf( "%s:\n", mvars->chan->name );
|
||||
syncml:
|
||||
mvars->done = mvars->cben = 0;
|
||||
syncmlx:
|
||||
if (mvars->boxlist) {
|
||||
while ((mvars->names[S] = strsep( &mvars->boxp, ",\n" ))) {
|
||||
if (mvars->list)
|
||||
puts( mvars->names[S] );
|
||||
else {
|
||||
if ((mvars->names[S] = strsep( &mvars->boxp, ",\n" ))) {
|
||||
if (!mvars->list) {
|
||||
mvars->names[M] = mvars->names[S];
|
||||
switch (sync_boxes( mvars->ctx, mvars->names, mvars->chan )) {
|
||||
case SYNC_BAD(M): t = M; goto screwt;
|
||||
case SYNC_BAD(S): t = S; goto screwt;
|
||||
case SYNC_FAIL: mvars->ret = 1;
|
||||
}
|
||||
sync_boxes( mvars->ctx, mvars->names, mvars->chan, done_sync, mvars );
|
||||
goto syncw;
|
||||
}
|
||||
puts( mvars->names[S] );
|
||||
goto syncmlx;
|
||||
}
|
||||
} else if (mvars->chan->patterns) {
|
||||
for (mbox = mvars->cboxes; mbox; mbox = mbox->next)
|
||||
if (mvars->list)
|
||||
puts( mbox->string );
|
||||
else {
|
||||
if ((mbox = mvars->cboxes)) {
|
||||
mvars->cboxes = mbox->next;
|
||||
if (!mvars->list) {
|
||||
mvars->names[M] = mvars->names[S] = mbox->string;
|
||||
switch (sync_boxes( mvars->ctx, mvars->names, mvars->chan )) {
|
||||
case SYNC_BAD(M): t = M; goto screwt;
|
||||
case SYNC_BAD(S): t = S; goto screwt;
|
||||
case SYNC_FAIL: mvars->ret = 1;
|
||||
sync_boxes( mvars->ctx, mvars->names, mvars->chan, done_sync_dyn, mvars );
|
||||
goto syncw;
|
||||
}
|
||||
puts( mbox->string );
|
||||
free( mbox );
|
||||
goto syncmlx;
|
||||
}
|
||||
for (t = 0; t < 2; t++)
|
||||
if ((mbox = mvars->boxes[t])) {
|
||||
mvars->boxes[t] = mbox->next;
|
||||
if ((mvars->chan->ops[1-t] & OP_MASK_TYPE) && (mvars->chan->ops[1-t] & OP_CREATE)) {
|
||||
for (mbox = mvars->boxes[t]; mbox; mbox = mbox->next)
|
||||
if (mvars->list)
|
||||
puts( mbox->string );
|
||||
else {
|
||||
if (!mvars->list) {
|
||||
mvars->names[M] = mvars->names[S] = mbox->string;
|
||||
switch (sync_boxes( mvars->ctx, mvars->names, mvars->chan )) {
|
||||
case SYNC_BAD(M): t = M; goto screwt;
|
||||
case SYNC_BAD(S): t = S; goto screwt;
|
||||
case SYNC_FAIL: mvars->ret = 1;
|
||||
sync_boxes( mvars->ctx, mvars->names, mvars->chan, done_sync_dyn, mvars );
|
||||
goto syncw;
|
||||
}
|
||||
puts( mbox->string );
|
||||
}
|
||||
free( mbox );
|
||||
goto syncmlx;
|
||||
}
|
||||
} else {
|
||||
if (!mvars->list) {
|
||||
sync_boxes( mvars->ctx, mvars->chan->boxes, mvars->chan, done_sync, mvars );
|
||||
mvars->skip = 1;
|
||||
syncw:
|
||||
mvars->cben = 1;
|
||||
if (!mvars->done)
|
||||
return;
|
||||
syncone:
|
||||
if (!mvars->skip)
|
||||
goto syncml;
|
||||
} else
|
||||
if (mvars->list)
|
||||
printf( "%s <=> %s\n", mvars->chan->boxes[M], mvars->chan->boxes[S] );
|
||||
else
|
||||
switch (sync_boxes( mvars->ctx, mvars->chan->boxes, mvars->chan )) {
|
||||
case SYNC_BAD(M): t = M; goto screwt;
|
||||
case SYNC_BAD(S): t = S; goto screwt;
|
||||
case SYNC_FAIL: mvars->ret = 1;
|
||||
}
|
||||
|
||||
next:
|
||||
if (mvars->ctx[M])
|
||||
mvars->drv[M]->disown_store( mvars->ctx[M] );
|
||||
if (mvars->ctx[S])
|
||||
mvars->drv[S]->disown_store( mvars->ctx[S] );
|
||||
for (t = 0; t < 2; t++)
|
||||
if (mvars->state[t] == ST_OPEN) {
|
||||
mvars->drv[t]->disown_store( mvars->ctx[t] );
|
||||
mvars->state[t] = ST_CLOSED;
|
||||
}
|
||||
if (mvars->state[M] != ST_CLOSED || mvars->state[S] != ST_CLOSED) {
|
||||
mvars->skip = mvars->cben = 1;
|
||||
return;
|
||||
}
|
||||
free_string_list( mvars->cboxes );
|
||||
free_string_list( mvars->boxes[M] );
|
||||
free_string_list( mvars->boxes[S] );
|
||||
|
@ -621,3 +654,76 @@ sync_chans( main_vars_t *mvars )
|
|||
for (t = 0; t < N_DRIVERS; t++)
|
||||
drivers[t]->cleanup();
|
||||
}
|
||||
|
||||
static void
|
||||
store_opened( store_t *ctx, void *aux )
|
||||
{
|
||||
MVARS(aux)
|
||||
|
||||
if (!ctx) {
|
||||
mvars->state[t] = ST_CLOSED;
|
||||
mvars->ret = mvars->skip = 1;
|
||||
return;
|
||||
}
|
||||
mvars->ctx[t] = ctx;
|
||||
if (mvars->skip) {
|
||||
mvars->state[t] = ST_OPEN;
|
||||
sync_chans( mvars, E_OPEN );
|
||||
return;
|
||||
}
|
||||
if (!mvars->boxlist && mvars->chan->patterns && !ctx->listed)
|
||||
mvars->drv[t]->list( ctx, store_listed, AUX );
|
||||
else {
|
||||
mvars->state[t] = ST_OPEN;
|
||||
sync_chans( mvars, E_OPEN );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store_listed( int sts, void *aux )
|
||||
{
|
||||
MVARS(aux)
|
||||
|
||||
mvars->state[t] = ST_OPEN;
|
||||
switch (sts) {
|
||||
case DRV_OK:
|
||||
if (mvars->ctx[t]->conf->map_inbox)
|
||||
add_string_list( &mvars->ctx[t]->boxes, mvars->ctx[t]->conf->map_inbox );
|
||||
break;
|
||||
case DRV_STORE_BAD:
|
||||
mvars->drv[t]->cancel_store( mvars->ctx[t] );
|
||||
mvars->state[t] = ST_CLOSED;
|
||||
default:
|
||||
mvars->ret = mvars->skip = 1;
|
||||
break;
|
||||
}
|
||||
sync_chans( mvars, E_OPEN );
|
||||
}
|
||||
|
||||
static void
|
||||
done_sync_dyn( int sts, void *aux )
|
||||
{
|
||||
main_vars_t *mvars = (main_vars_t *)aux;
|
||||
|
||||
free( ((char *)mvars->names[S]) - offsetof(string_list_t, string) );
|
||||
done_sync( sts, aux );
|
||||
}
|
||||
|
||||
static void
|
||||
done_sync( int sts, void *aux )
|
||||
{
|
||||
main_vars_t *mvars = (main_vars_t *)aux;
|
||||
|
||||
mvars->done = 1;
|
||||
if (sts) {
|
||||
mvars->ret = 1;
|
||||
if (sts & (SYNC_BAD(M) | SYNC_BAD(S))) {
|
||||
mvars->skip = 1;
|
||||
if (sts & SYNC_BAD(M))
|
||||
mvars->state[M] = ST_CLOSED;
|
||||
if (sts & SYNC_BAD(S))
|
||||
mvars->state[S] = ST_CLOSED;
|
||||
}
|
||||
}
|
||||
sync_chans( mvars, E_SYNC );
|
||||
}
|
||||
|
|
1243
src/sync.c
1243
src/sync.c
File diff suppressed because it is too large
Load Diff
12
src/util.c
12
src/util.c
|
@ -43,6 +43,7 @@ debug( const char *msg, ... )
|
|||
vprintf( msg, va );
|
||||
va_end( va );
|
||||
fflush( stdout );
|
||||
need_nl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +71,7 @@ info( const char *msg, ... )
|
|||
vprintf( msg, va );
|
||||
va_end( va );
|
||||
fflush( stdout );
|
||||
need_nl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,16 +89,6 @@ infon( const char *msg, ... )
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
infoc( char c )
|
||||
{
|
||||
if (!(DFlags & QUIET)) {
|
||||
putchar( c );
|
||||
fflush( stdout );
|
||||
need_nl = Ontty;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
warn( const char *msg, ... )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user