isync/src/main_list.c
Oswald Buddenhagen ced20ad0d9 fix Tunnel leaving behind zombies
this generally went unnoticed, as the tunnel usually terminates right
before we exit anyway. however, if multiple Channels are synced, it may
become visible.

this is a "shotgun" implementation, where the main loop just reaps all
unclaimed children.
arguably, it would be cleaner if each socket actually tracked its own
process, but getting synchronous kills+waits right is tricky, so we
continue to pretend that there is no process as far as the socket layer
is concerned.

poll()/select() are not restartable, so they need EINTR handling now
that SIGCHLD is actually delivered.
2022-07-04 18:28:30 +02:00

188 lines
4 KiB
C

// SPDX-FileCopyrightText: 2022 Oswald Buddenhagen <ossi@users.sf.net>
// SPDX-License-Identifier: GPL-2.0-or-later WITH LicenseRef-isync-GPL-exception
//
// mbsync - mailbox synchronizer
//
#include "main_p.h"
typedef struct store_ent {
struct store_ent *next;
store_conf_t *conf;
} store_ent_t;
typedef struct {
core_vars_t *cvars;
store_conf_t *store;
driver_t *drv;
store_t *ctx;
store_ent_t *storeptr;
int cben, done;
} list_vars_t;
static store_ent_t *
add_store( store_ent_t ***storeapp, store_conf_t *store )
{
store_ent_t *se = nfzalloc( sizeof(*se) );
se->conf = store;
**storeapp = se;
*storeapp = &se->next;
return se;
}
static void do_list_stores( list_vars_t *lvars );
static void list_next_store( list_vars_t *lvars );
void
list_stores( core_vars_t *cvars, char **argv )
{
list_vars_t lvars[1];
store_ent_t *strs = NULL, **strapp = &strs;
store_conf_t *store;
memset( lvars, 0, sizeof(*lvars) );
lvars->cvars = cvars;
if (!stores) {
fputs( "No stores defined.\n", stderr );
cvars->ret = 1;
return;
}
if (!*argv) { // Implicit --all
for (store = stores; store; store = store->next)
add_store( &strapp, store );
} else {
for (; *argv; argv++) {
for (store = stores; store; store = store->next) {
if (!strcmp( store->name, *argv )) {
add_store( &strapp, store );
goto gotstr;
}
}
error( "No store named '%s' defined.\n", *argv );
cvars->ret = 1;
gotstr: ;
}
}
if (cvars->ret)
return;
lvars->storeptr = strs;
do_list_stores( lvars );
main_loop();
}
static void
list_store_bad( void *aux )
{
list_vars_t *lvars = (list_vars_t *)aux;
lvars->drv->cancel_store( lvars->ctx );
lvars->cvars->ret = 1;
list_next_store( lvars );
}
static void
advance_store( list_vars_t *lvars )
{
store_ent_t *nstr = lvars->storeptr->next;
free( lvars->storeptr );
lvars->storeptr = nstr;
}
static void list_store_connected( int sts, void *aux );
static void
do_list_stores( list_vars_t *lvars )
{
while (lvars->storeptr) {
lvars->store = lvars->storeptr->conf;
lvars->drv = lvars->store->driver;
int st = lvars->drv->get_fail_state( lvars->store );
if (st != FAIL_TEMP) {
info( "Skipping %sfailed store %s.\n",
(st == FAIL_WAIT) ? "temporarily " : "", lvars->store->name );
lvars->cvars->ret = 1;
goto next;
}
uint dcaps = lvars->drv->get_caps( NULL );
store_t *ctx = lvars->drv->alloc_store( lvars->store, "" );
if ((DFlags & DEBUG_DRV) || ((DFlags & FORCEASYNC(F)) && !(dcaps & DRV_ASYNC))) {
lvars->drv = &proxy_driver;
ctx = proxy_alloc_store( ctx, "", DFlags & FORCEASYNC(F) );
}
lvars->ctx = ctx;
lvars->drv->set_callbacks( ctx, NULL, list_store_bad, lvars );
info( "Opening store %s...\n", lvars->store->name );
lvars->cben = lvars->done = 0;
lvars->drv->connect_store( lvars->ctx, list_store_connected, lvars );
if (!lvars->done) {
lvars->cben = 1;
return;
}
next:
advance_store( lvars );
}
cleanup_mainloop();
}
static void
list_next_store( list_vars_t *lvars )
{
if (lvars->cben) {
advance_store( lvars );
do_list_stores( lvars );
}
}
static void
list_done_store( list_vars_t *lvars )
{
lvars->done = 1;
lvars->drv->free_store( lvars->ctx );
list_next_store( lvars );
}
static void list_store_listed( int sts, string_list_t *boxes, void *aux );
static void
list_store_connected( int sts, void *aux )
{
list_vars_t *lvars = (list_vars_t *)aux;
switch (sts) {
case DRV_CANCELED:
return;
case DRV_OK:
lvars->drv->list_store( lvars->ctx, LIST_INBOX | LIST_PATH_MAYBE, list_store_listed, lvars );
break;
default:
lvars->cvars->ret = 1;
list_done_store( lvars );
break;
}
}
static void
list_store_listed( int sts, string_list_t *boxes, void *aux )
{
list_vars_t *lvars = (list_vars_t *)aux;
string_list_t *box;
switch (sts) {
case DRV_CANCELED:
return;
case DRV_OK:
printf( "===== %s:\n", lvars->ctx->conf->name );
for (box = boxes; box; box = box->next)
puts( box->string );
break;
default:
lvars->cvars->ret = 1;
break;
}
list_done_store( lvars );
}