isync

mailbox synchronization program
git clone https://git.code.sf.net/p/isync/isync
Log | Files | Refs | README | LICENSE

commit 0e1f8f9a3f8aa1d84894ed0addac398cd709bb81
parent 8aa22a62e790c4ced512e0f74c407725162a3b0d
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date:   Mon, 23 Mar 2015 08:42:51 +0100

revamp console output options

- the old meaning of -V[V] was moved to -D{n|N}, as these are really
  debugging options.
- don't print the info messages by default; this can be re-enabled with
  the -V switch, and is implied by most debug options (it was really
  kind of stupid that verbose/debug operation disabled these).
- the sync algo/state debugging can be separately enabled with -Ds now.

Diffstat:
MNEWS | 3+++
Msrc/common.h | 26++++++++++++++++----------
Msrc/drv_imap.c | 12++++++------
Msrc/drv_maildir.c | 18++++++++++++++----
Msrc/main.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/mbsync.1 | 27+++++++++++++++++++++------
Msrc/sync.c | 26+++++++++++++++++++++++---
Msrc/util.c | 45+++++++++++++++++++++++++++++++--------------
8 files changed, 167 insertions(+), 63 deletions(-)

diff --git a/NEWS b/NEWS @@ -5,6 +5,9 @@ The 'isync' compatibility wrapper is now deprecated. An IMAP Path/NAMESPACE rooted in INBOX won't be handled specially any more. This means that some Patterns may need adjustment. +The default output is a lot less verbose now. +The meanings of the -V and -D options changed significantly. + The SSL/TLS configuration has been re-designed. SSL is now explicitly enabled or disabled - "use SSL if available" is gone. Notice: Tunnels are assumed to be secure and thus default to no SSL. diff --git a/src/common.h b/src/common.h @@ -59,14 +59,18 @@ typedef unsigned int uint; /* main.c */ -#define DEBUG 1 -#define VERBOSE 2 -#define XVERBOSE 4 -#define QUIET 8 -#define VERYQUIET 16 -#define KEEPJOURNAL 32 -#define ZERODELAY 64 -#define CRASHDEBUG 128 +#define DEBUG_CRASH 0x01 +#define DEBUG_MAILDIR 0x02 +#define DEBUG_NET 0x04 +#define DEBUG_NET_ALL 0x08 +#define DEBUG_SYNC 0x10 +#define DEBUG_ALL (0xFF & ~DEBUG_NET_ALL) +#define QUIET 0x100 +#define VERYQUIET 0x200 +#define PROGRESS 0x400 +#define VERBOSE 0x800 +#define KEEPJOURNAL 0x1000 +#define ZERODELAY 0x2000 extern int DFlags; extern int UseFSync; @@ -86,10 +90,12 @@ void stats( void ); /* util.c */ -void ATTR_PRINTFLIKE(1, 2) debug( const char *, ... ); -void ATTR_PRINTFLIKE(1, 2) debugn( const char *, ... ); +void vdebug( int, const char *, va_list va ); +void vdebugn( int, const char *, va_list va ); void ATTR_PRINTFLIKE(1, 2) info( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) infon( const char *, ... ); +void ATTR_PRINTFLIKE(1, 2) progress( const char *, ... ); +void ATTR_PRINTFLIKE(1, 2) notice( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) warn( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) error( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... ); diff --git a/src/drv_imap.c b/src/drv_imap.c @@ -286,7 +286,7 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd ) } bufl = nfsnprintf( buf, sizeof(buf), buffmt, cmd->tag, cmd->cmd, cmd->param.data_len ); - if (DFlags & VERBOSE) { + if (DFlags & DEBUG_NET) { if (ctx->num_in_progress) printf( "(%d in progress) ", ctx->num_in_progress ); if (starts_with( cmd->cmd, -1, "LOGIN", 5 )) @@ -743,7 +743,7 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts ) if (bytes > 0) goto postpone; - if (DFlags & XVERBOSE) { + if (DFlags & DEBUG_NET_ALL) { printf( "%s=========\n", ctx->label ); fwrite( cur->val, cur->len, 1, stdout ); printf( "%s=========\n", ctx->label ); @@ -755,7 +755,7 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts ) goto postpone; if (s == (void *)~0) goto badeof; - if (DFlags & VERBOSE) { + if (DFlags & DEBUG_NET) { printf( "%s%s\n", ctx->label, s ); fflush( stdout ); } @@ -1243,7 +1243,7 @@ imap_socket_read( void *aux ) /* A clean shutdown sequence ends with bad_callback as well (see imap_cleanup()). */ break; } - if (DFlags & VERBOSE) { + if (DFlags & DEBUG_NET) { printf( "%s%s\n", ctx->label, cmd ); fflush( stdout ); } @@ -1895,12 +1895,12 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char * iov[0].takeOwn = GiveOwn; iovcnt = 1; - if (DFlags & VERBOSE) { + if (DFlags & DEBUG_NET) { printf( "%s>+> %s\n", ctx->label, enc ); fflush( stdout ); } } else { - if (DFlags & VERBOSE) { + if (DFlags & DEBUG_NET) { printf( "%s>+>\n", ctx->label ); fflush( stdout ); } diff --git a/src/drv_maildir.c b/src/drv_maildir.c @@ -85,6 +85,16 @@ static struct flock lck; static int MaildirCount; +static void ATTR_PRINTFLIKE(1, 2) +debug( const char *msg, ... ) +{ + va_list va; + + va_start( va, msg ); + vdebug( DEBUG_SYNC, msg, va ); + va_end( va ); +} + static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; static uchar @@ -371,7 +381,7 @@ maildir_clear_tmp( char *buf, int bufsz, int bl ) /* This should happen infrequently enough that it won't be * bothersome to the user to display when it occurs. */ - info( "Maildir notice: removing stale file %s\n", buf ); + notice( "Maildir notice: removing stale file %s\n", buf ); if (unlink( buf ) && errno != ENOENT) sys_error( "Maildir error: cannot remove %s", buf ); } @@ -515,7 +525,7 @@ maildir_init_uidval( maildir_store_t *ctx ) static int maildir_init_uidval_new( maildir_store_t *ctx ) { - info( "Maildir notice: no UIDVALIDITY, creating new.\n" ); + notice( "Maildir notice: no UIDVALIDITY, creating new.\n" ); return maildir_init_uidval( ctx ); } @@ -768,7 +778,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist ) * tell if there were further modifications during this second. So wait. * This has the nice side effect that we wait for "batches" of changes to * complete. On the downside, it can potentially block indefinitely. */ - info( "Maildir notice: sleeping due to recent directory modification.\n" ); + notice( "Maildir notice: sleeping due to recent directory modification.\n" ); sleep( 1 ); /* FIXME: should make this async */ goto restat; } @@ -900,7 +910,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist ) maildir_free_scan( msglist ); return DRV_BOX_BAD; #else - info( "Maildir notice: duplicate UID; changing UIDVALIDITY.\n"); + notice( "Maildir notice: duplicate UID; changing UIDVALIDITY.\n"); if ((ret = maildir_init_uid( ctx )) != DRV_OK) { maildir_free_scan( msglist ); return ret; diff --git a/src/main.c b/src/main.c @@ -79,9 +79,9 @@ PACKAGE " " VERSION " - mailbox synchronizer\n" " -C, --create create mailboxes if nonexistent\n" " -X, --expunge expunge deleted messages\n" " -c, --config CONFIG read an alternate config file (default: ~/." EXE "rc)\n" -" -D, --debug print debugging messages\n" -" -V, --verbose verbose mode (display network traffic)\n" -" -q, --quiet don't display progress info\n" +" -D, --debug debugging modes (see manual)\n" +" -V, --verbose display what is happening\n" +" -q, --quiet don't display progress counters\n" " -v, --version display version\n" " -h, --help display this help message\n" "\nIf neither --pull nor --push are specified, both are active.\n" @@ -137,7 +137,7 @@ stats( void ) int t, l, ll, cls; static int cols = -1; - if (DFlags & QUIET) + if (!(DFlags & PROGRESS)) return; if (cols < 0 && (!(cs = getenv( "COLUMNS" )) || !(cols = atoi( cs )))) @@ -152,7 +152,7 @@ stats( void ) if (l > cls) buf[t][cls - 1] = '~'; } - infon( "\v\r%s M: %.*s S: %.*s", buf[2], cls, buf[0], cls, buf[1] ); + progress( "\r%s M: %.*s S: %.*s", buf[2], cls, buf[0], cls, buf[1] ); } static int @@ -424,13 +424,25 @@ main( int argc, char **argv ) else DFlags |= QUIET; } else if (!strcmp( opt, "verbose" )) { - if (DFlags & VERBOSE) - DFlags |= XVERBOSE; + DFlags |= VERBOSE; + } else if (starts_with( opt, -1, "debug", 5 )) { + opt += 5; + if (!*opt) + op = VERBOSE | DEBUG_ALL; + else if (!strcmp( opt, "-crash" )) + op = DEBUG_CRASH; + else if (!strcmp( opt, "-maildir" )) + op = VERBOSE | DEBUG_MAILDIR; + else if (!strcmp( opt, "-net" )) + op = VERBOSE | DEBUG_NET; + else if (!strcmp( opt, "-net-all" )) + op = VERBOSE | DEBUG_NET_ALL; + else if (!strcmp( opt, "-sync" )) + op = VERBOSE | DEBUG_SYNC; else - DFlags |= VERBOSE | QUIET; - } else if (!strcmp( opt, "debug" )) - DFlags |= DEBUG | QUIET; - else if (!strcmp( opt, "pull" )) + goto badopt; + DFlags |= op; + } else if (!strcmp( opt, "pull" )) cops |= XOP_PULL, ops[M] |= XOP_HAVE_TYPE; else if (!strcmp( opt, "push" )) cops |= XOP_PUSH, ops[M] |= XOP_HAVE_TYPE; @@ -595,16 +607,34 @@ main( int argc, char **argv ) DFlags |= QUIET; break; case 'V': - if (DFlags & VERBOSE) - DFlags |= XVERBOSE; - else - DFlags |= VERBOSE | QUIET; + DFlags |= VERBOSE; break; case 'D': - if (*ochar == 'C') - DFlags |= CRASHDEBUG, ochar++; - else - DFlags |= CRASHDEBUG | DEBUG | QUIET; + for (op = 0; *ochar; ochar++) { + switch (*ochar) { + case 'C': + op |= DEBUG_CRASH; + break; + case 'm': + op |= DEBUG_MAILDIR | VERBOSE; + break; + case 'n': + op |= DEBUG_NET | VERBOSE; + break; + case 'N': + op |= DEBUG_NET_ALL | VERBOSE; + break; + case 's': + op |= DEBUG_SYNC | VERBOSE; + break; + default: + error( "Unknown -D flag '%c'\n", *ochar ); + return 1; + } + } + if (!op) + op = DEBUG_ALL | VERBOSE; + DFlags |= op; break; case 'J': DFlags |= KEEPJOURNAL; @@ -622,8 +652,11 @@ main( int argc, char **argv ) } } + if (!(DFlags & (QUIET | DEBUG_ALL)) && isatty( 1 )) + DFlags |= PROGRESS; + #ifdef __linux__ - if (DFlags & CRASHDEBUG) { + if (DFlags & DEBUG_CRASH) { signal( SIGSEGV, crashHandler ); signal( SIGBUS, crashHandler ); signal( SIGILL, crashHandler ); diff --git a/src/mbsync.1 b/src/mbsync.1 @@ -1,7 +1,7 @@ .ig \" mbsync - mailbox synchronizer \" Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> -\" Copyright (C) 2002-2004,2011-2013 Oswald Buddenhagen <ossi@users.sf.net> +\" Copyright (C) 2002-2004,2011-2015 Oswald Buddenhagen <ossi@users.sf.net> \" Copyright (C) 2004 Theodore Y. Ts'o <tytso@mit.edu> \" \" This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@ \" As a special exception, mbsync may be linked with the OpenSSL library, \" despite that library's more restrictive license. .. -.TH mbsync 1 "2013 Dec 14" +.TH mbsync 1 "2015 Mar 22" .. .SH NAME mbsync - synchronize IMAP4 and Maildir mailboxes @@ -78,13 +78,28 @@ Display a summary of command line options. Display version information. .TP \fB-V\fR, \fB--verbose\fR -Enable \fIverbose\fR mode, which displays the IMAP4 network traffic. +Enable \fIverbose\fR mode, which displays what is currently happening. .TP -\fB-D\fR, \fB--debug\fR -Enable printing \fIdebug\fR information. +\fB-D\fR[\fBC\fR][\fBm\fR][\fBn\fR|\fBN\fR][\fBs\fR]\fR]\fR,\ + \fB--debug\fR[\fB-crash\fR|\fB-maildir\fR|\fB-net\fR|\fB-net-all\fR|\fB-sync\fR] +Enable debugging categories: +.in +4 +\fBC\fR, \fBcrash\fR - use built-in crash handler +.br +\fBm\fR, \fBmaildir\fR - print maildir debug info +.br +\fBn\fR, \fBnet\fR - print network traffic (protocol only) +.br +\fBN\fR, \fBnet-all\fR - print network traffic (including payloads) +.br +\fBs\fR, \fBsync\fR - print synchronization debug info +.in -4 +All categories except \fBcrash\fR implictly enable \fIverbose\fR mode. +Without category specification, all categories except net-all are enabled. .TP \fB-q\fR, \fB--quiet\fR -Suppress informational messages. +Suppress progress counters (this is implicit if stdout is no TTY, +or any debugging categories are enabled) and notices. If specified twice, suppress warning messages as well. .. .SH CONFIGURATION diff --git a/src/sync.c b/src/sync.c @@ -45,6 +45,26 @@ group_conf_t *groups; const char *str_ms[] = { "master", "slave" }, *str_hl[] = { "push", "pull" }; +static void ATTR_PRINTFLIKE(1, 2) +debug( const char *msg, ... ) +{ + va_list va; + + va_start( va, msg ); + vdebug( DEBUG_SYNC, msg, va ); + va_end( va ); +} + +static void ATTR_PRINTFLIKE(1, 2) +debugn( const char *msg, ... ) +{ + va_list va; + + va_start( va, msg ); + vdebugn( DEBUG_SYNC, msg, va ); + va_end( va ); +} + void Fclose( FILE *f, int safe ) { @@ -1347,7 +1367,7 @@ box_loaded( int sts, void *aux ) if (tmsg->srec) /* found by TUID */ continue; uid = tmsg->uid; - if (DFlags & DEBUG) { + if (DFlags & DEBUG_SYNC) { make_flags( tmsg->flags, fbuf ); printf( svars->ctx[t]->opts & OPEN_SIZE ? " message %5d, %-4s, %6lu: " : " message %5d, %-4s: ", uid, fbuf, tmsg->size ); } @@ -1413,7 +1433,7 @@ box_loaded( int sts, void *aux ) srec->uid[S] = 0; } else { if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS) && srec->msg[t]->flags != srec->flags) - info( "Info: conflicting changes in (%d,%d)\n", srec->uid[M], srec->uid[S] ); + notice( "Notice: conflicting changes in (%d,%d)\n", srec->uid[M], srec->uid[S] ); if (svars->chan->ops[t] & OP_DELETE) { debug( " %sing delete\n", str_hl[t] ); srec->aflags[t] = F_DELETED; @@ -1439,7 +1459,7 @@ box_loaded( int sts, void *aux ) } srec->aflags[t] = sflags & ~srec->flags; srec->dflags[t] = ~sflags & srec->flags; - if (DFlags & DEBUG) { + if (DFlags & DEBUG_SYNC) { char afbuf[16], dfbuf[16]; /* enlarge when support for keywords is added */ make_flags( srec->aflags[t], afbuf ); make_flags( srec->dflags[t], dfbuf ); diff --git a/src/util.c b/src/util.c @@ -53,39 +53,43 @@ printn( const char *msg, va_list va ) } void -debug( const char *msg, ... ) +vdebug( int cat, const char *msg, va_list va ) { - va_list va; - - if (DFlags & DEBUG) { - va_start( va, msg ); + if (DFlags & cat) { vprintf( msg, va ); - va_end( va ); fflush( stdout ); need_nl = 0; } } void -debugn( const char *msg, ... ) +vdebugn( int cat, const char *msg, va_list va ) { - va_list va; - - if (DFlags & DEBUG) { - va_start( va, msg ); + if (DFlags & cat) { vprintf( msg, va ); - va_end( va ); fflush( stdout ); need_nl = 1; } } void +progress( const char *msg, ... ) +{ + va_list va; + + va_start( va, msg ); + vprintf( msg, va ); + va_end( va ); + fflush( stdout ); + need_nl = 1; +} + +void info( const char *msg, ... ) { va_list va; - if (!(DFlags & QUIET)) { + if (DFlags & VERBOSE) { va_start( va, msg ); printn( msg, va ); va_end( va ); @@ -98,7 +102,7 @@ infon( const char *msg, ... ) { va_list va; - if (!(DFlags & QUIET)) { + if (DFlags & VERBOSE) { va_start( va, msg ); printn( msg, va ); va_end( va ); @@ -107,6 +111,19 @@ infon( const char *msg, ... ) } void +notice( const char *msg, ... ) +{ + va_list va; + + if (!(DFlags & QUIET)) { + va_start( va, msg ); + printn( msg, va ); + va_end( va ); + need_nl = 0; + } +} + +void warn( const char *msg, ... ) { va_list va;