Browse Source

add --list-stores mode

this is useful for verifying the store configuration, and finding the
right mailbox names.

REFMAIL: YaZC3XUTWjyfjgn+@ugly
wip/maildir-path-under-inbox
Oswald Buddenhagen 3 years ago
parent
commit
5d5e07eb63
  1. 2
      NEWS
  2. 2
      src/Makefile.am
  3. 2
      src/config.c
  4. 2
      src/driver.c
  5. 2
      src/driver.h
  6. 9
      src/main.c
  7. 188
      src/main_list.c
  8. 1
      src/main_p.h
  9. 9
      src/mbsync.1

2
NEWS

@ -6,6 +6,8 @@ The old locations remain supported.
The reference point for relative local paths in the configuration file
is now the file's containing directory.
The unfiltered list of mailboxes in each Store can be printed now.
[1.4.0]
The 'isync' compatibility wrapper was removed.

2
src/Makefile.am

@ -8,7 +8,7 @@ mbsync_SOURCES = \
drv_imap.c \
drv_maildir.c \
sync.c sync_state.c \
main.c main_sync.c
main.c main_sync.c main_list.c
noinst_HEADERS = \
common.h config.h socket.h \
driver.h \

2
src/config.c

@ -20,8 +20,6 @@ char FieldDelimiter = ';';
char FieldDelimiter = ':';
#endif
static store_conf_t *stores;
char *
expand_strdup( const char *s, const conffile_t *cfile )
{

2
src/driver.c

@ -7,6 +7,8 @@
#include "driver.h"
store_conf_t *stores;
driver_t *drivers[N_DRIVERS] = { &maildir_driver, &imap_driver };
void

2
src/driver.h

@ -31,6 +31,8 @@ typedef struct store_conf {
STORE_CONF
} store_conf_t;
extern store_conf_t *stores;
/* For message->flags */
// Keep the MESSAGE_FLAGS in sync (grep that)!
/* The order is according to alphabetical maildir flag sort */

9
src/main.c

@ -33,6 +33,7 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
" " EXE " [flags] {{channel[:box,...]|group} ...|-a}\n"
" -a, --all operate on all defined channels\n"
" -l, --list list mailboxes instead of syncing them\n"
" -ls, --list-stores raw listing of stores' mailboxes\n"
" -n, --new propagate new messages\n"
" -d, --delete propagate message deletions\n"
" -f, --flags propagate message flag changes\n"
@ -173,6 +174,8 @@ main( int argc, char **argv )
mvars->all = 1;
} else if (!strcmp( opt, "list" )) {
mvars->list = 1;
} else if (!strcmp( opt, "list-stores" )) {
mvars->list_stores = 1;
} else if (!strcmp( opt, "help" )) {
usage( 0 );
} else if (!strcmp( opt, "version" )) {
@ -295,6 +298,9 @@ main( int argc, char **argv )
mvars->all = 1;
break;
case 'l':
if (*ochar == 's')
mvars->list_stores = 1, ochar++;
else
mvars->list = 1;
break;
case 'c':
@ -468,6 +474,9 @@ main( int argc, char **argv )
if (load_config( config ))
return 1;
if (mvars->list_stores)
list_stores( mvars, argv + oind );
else
sync_chans( mvars, argv + oind );
return mvars->ret;
}

188
src/main_list.c

@ -0,0 +1,188 @@
// 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) && !(dcaps & DRV_ASYNC))) {
lvars->drv = &proxy_driver;
ctx = proxy_alloc_store( ctx, "" );
}
lvars->ctx = ctx;
lvars->drv->set_bad_callback( ctx, 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_drivers();
}
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 );
}

1
src/main_p.h

@ -20,5 +20,6 @@ typedef struct {
} core_vars_t;
void sync_chans( core_vars_t *cvars, char **argv );
void list_stores( core_vars_t *cvars, char **argv );
#endif

9
src/mbsync.1

@ -11,6 +11,8 @@ mbsync - synchronize IMAP4 and Maildir mailboxes
.
.SH SYNOPSIS
\fBmbsync\fR [\fIoptions\fR ...] {{\fIchannel\fR[\fB:\fIbox\fR[{\fB,\fR|\fB\\n\fR}...]]|\fIgroup\fR} ...|\fB-a\fR}
.br
\fBmbsync\fR --list-stores [\fIoptions\fR ...] [\fIstore\fR} ...]
.
.SH DESCRIPTION
\fBmbsync\fR is a command line application which synchronizes mailboxes;
@ -43,6 +45,13 @@ command line are ignored.
Don't synchronize anything, but list all mailboxes in the selected Channels
and exit.
.TP
\fB-ls\fR, \fB--list-stores\fR
Don't synchronize anything, but list all mailboxes in the selected Stores
and exit.
If no Stores are specified, all configured ones are listed.
These are raw Store contents, not filtered by any Channel's \fBPatterns\fR.
This option may be used to verify each Store's configuration.
.TP
\fB-C\fR[\fBf\fR][\fBn\fR], \fB--create\fR[\fB-far\fR|\fB-near\fR]
Override any \fBCreate\fR options from the config file. See below.
.TP

Loading…
Cancel
Save