commit c19043a2a513c9638443dbc803089e205bdbbbef
Author: Oswald Buddenhagen <o...@kde.org>
Date:   Sun Apr 10 15:32:25 2011 +0200

    unify error reporting
    
    - introduce sys_error() and use it instead of perror() and
      error(strerror()) in all expected error conditions
    - perror() is used only for "something's really wrong with the system"
      kind of errors
    - file names, etc. are quoted if they are not validated yet, so e.g. an
      empty string becomes immediately obvious
    - improve and unify language
    - add missing newlines

 TODO                 |    2 -
 src/compat/config.c  |    2 +-
 src/compat/convert.c |   20 ++++-----
 src/compat/isync.h   |    1 +
 src/compat/main.c    |    9 ++--
 src/compat/util.c    |   13 ++++++
 src/config.c         |    3 +-
 src/drv_imap.c       |    7 +--
 src/drv_maildir.c    |   99 ++++++++++++++++++++++++------------------
 src/isync.h          |    3 +
 src/mdconvert.c      |   46 +++++++++++++++-----
 src/socket.c         |   49 +++++++++++----------
 src/sync.c           |   10 ++--
 src/util.c           |   17 +++++++
 14 files changed, 174 insertions(+), 107 deletions(-)

diff --git a/TODO b/TODO
index b7dd5b2..c3fdb35 100644
--- a/TODO
+++ b/TODO
@@ -15,8 +15,6 @@ quotas are weird, they make close() fail.
 
 clarify error cases of transactions.
 
-cleanup/improve error messages in the drivers.
-
 sync.c does not consider UID 0 valid, which is wrong. fixing this requires
 an incompatible change or a remapping hack in sync state files.
 
diff --git a/src/compat/config.c b/src/compat/config.c
index 85a641d..02115b9 100644
--- a/src/compat/config.c
+++ b/src/compat/config.c
@@ -97,7 +97,7 @@ load_config( const char *path, config_t ***stor )
 
        if (!(fp = fopen( path, "r" ))) {
                if (errno != ENOENT)
-                       perror( "fopen" );
+                       sys_error( "Cannot read config file '%s'", path );
                return;
        }
        if (!Quiet && !Debug && !Verbose)
diff --git a/src/compat/convert.c b/src/compat/convert.c
index 0bd0f15..3bd8879 100644
--- a/src/compat/convert.c
+++ b/src/compat/convert.c
@@ -28,7 +28,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/stat.h>
-#include <errno.h>
 #include <time.h>
 
 #include <db.h>
@@ -97,10 +96,9 @@ convert( config_t *box )
        for (i = 0; i < 3; i++) {
                nfsnprintf( buf, sizeof(buf), "%s/%s", mboxdir, subdirs[i] );
                if (stat( buf, &sb )) {
-                       fprintf( stderr, "ERROR: stat %s: %s (errno %d)\n", buf,
-                                strerror(errno), errno );
+                       sys_error( "ERROR: cannot access %s", buf );
                        fprintf( stderr,
-                                "ERROR: %s does not appear to be a valid 
maildir style mailbox\n",
+                                "ERROR: '%s' does not appear to be a valid 
maildir style mailbox\n",
                                 mboxdir );
                        goto err1;
                }
@@ -111,7 +109,7 @@ convert( config_t *box )
        nfsnprintf( sname, sizeof(sname), "%s/.mbsyncstate", mboxdir );
 
        if ((fd = open( ilname, O_WRONLY|O_CREAT, 0600 )) < 0) {
-               perror( ilname );
+               sys_error( "Cannot create %s", ilname );
                goto err1;
        }
 #if SEEK_SET != 0
@@ -121,20 +119,20 @@ convert( config_t *box )
        lck.l_type = F_WRLCK;
 #endif
        if (fcntl( fd, F_SETLKW, &lck )) {
-               perror( ilname );
+               sys_error( "Cannot lock %s", ilname );
          err2:
                close( fd );
                goto err1;
        }
 
        if (!(fp = fopen( iuvname, "r" ))) {
-               perror( iuvname );
+               sys_error( "Cannot open %s", iuvname );
                goto err2;
        }
        fscanf( fp, "%d", &uidval );
        fclose( fp );
        if (!(fp = fopen( imuname, "r" ))) {
-               perror( imuname );
+               sys_error( "Cannot open %s", imuname );
                goto err2;
        }
        fscanf( fp, "%d", &maxuid );
@@ -162,7 +160,7 @@ convert( config_t *box )
        for (i = 0; i < 2; i++) {
                nfsnprintf( buf, sizeof(buf), "%s/%s/", mboxdir, subdirs[i] );
                if (!(d = opendir( buf ))) {
-                       perror( "opendir" );
+                       sys_error( "Cannot list %s", buf );
                  err4:
                        free( msgs );
                        if (db)
@@ -199,7 +197,7 @@ convert( config_t *box )
        qsort( msgs, nmsgs, sizeof(msg_t), compare_uids );
 
        if (!(fp = fopen( sname, "w" ))) {
-               perror( sname );
+               sys_error( "Cannot create %s", sname );
                goto err4;
        }
        if (box->max_messages) {
@@ -238,7 +236,7 @@ convert( config_t *box )
                rename( iumname, diumname );
        } else {
                if (!(fp = fopen( uvname, "w" ))) {
-                       perror( uvname );
+                       sys_error( "Cannot create %s", uvname );
                        goto err4;
                }
                fprintf( fp, "%d\n%d\n", uidval, maxuid );
diff --git a/src/compat/isync.h b/src/compat/isync.h
index 86dddef..09ec283 100644
--- a/src/compat/isync.h
+++ b/src/compat/isync.h
@@ -98,4 +98,5 @@ char *nfstrdup( const char *str );
 int nfvasprintf( char **str, const char *fmt, va_list va );
 int nfasprintf( char **str, const char *fmt, ... );
 int nfsnprintf( char *buf, int blen, const char *fmt, ... );
+void sys_error( const char *, ... );
 void ATTR_NORETURN oob( void );
diff --git a/src/compat/main.c b/src/compat/main.c
index 1220e5a..10ade7f 100644
--- a/src/compat/main.c
+++ b/src/compat/main.c
@@ -29,7 +29,6 @@
 #include <limits.h>
 #include <pwd.h>
 #include <stdio.h>
-#include <errno.h>
 #include <string.h>
 #include <ctype.h>
 #include <dirent.h>
@@ -336,7 +335,7 @@ main( int argc, char **argv )
                        struct dirent *de;
 
                        if (!(dir = opendir( xmaildir ))) {
-                               fprintf( stderr, "%s: %s\n", xmaildir, 
strerror(errno) );
+                               sys_error( "Cannot list '%s'", xmaildir );
                                return 1;
                        }
                        while ((de = readdir( dir ))) {
@@ -379,13 +378,13 @@ main( int argc, char **argv )
                        outconfig = path2;
                }
                if ((fd = creat( outconfig, 0666 )) < 0) {
-                       fprintf( stderr, "Error: cannot write new config %s: 
%s\n", outconfig, strerror(errno) );
+                       sys_error( "Error: cannot create config file '%s'", 
outconfig );
                        return 1;
                }
        } else {
                strcpy( path2, "/tmp/mbsyncrcXXXXXX" );
                if ((fd = mkstemp( path2 )) < 0) {
-                       fprintf( stderr, "Can't create temp file\n" );
+                       sys_error( "Error: cannot create temporary config file" 
);
                        return 1;
                }
        }
@@ -432,6 +431,6 @@ main( int argc, char **argv )
                                add_arg( &args, find_box( argv[optind] 
)->channel_name );
        }
        execvp( args[0], args );
-       perror( args[0] );
+       sys_error( "Cannot execute %s", args[0] );
        return 1;
 }
diff --git a/src/compat/util.c b/src/compat/util.c
index 7ac085b..1cb0f79 100644
--- a/src/compat/util.c
+++ b/src/compat/util.c
@@ -27,6 +27,19 @@
 #include <pwd.h>
 #include <ctype.h>
 
+void
+sys_error( const char *msg, ... )
+{
+       va_list va;
+       char buf[1024];
+
+       va_start( va, msg );
+       if ((unsigned)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
+               oob();
+       va_end( va );
+       perror( buf );
+}
+
 char *
 next_arg( char **s )
 {
diff --git a/src/config.c b/src/config.c
index ef7641a..ed0466f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -25,7 +25,6 @@
 
 #include <unistd.h>
 #include <limits.h>
-#include <errno.h>
 #include <pwd.h>
 #include <sys/types.h>
 #include <string.h>
@@ -272,7 +271,7 @@ load_config( const char *where, int pseudo )
                info( "Reading configuration file %s\n", cfile.file );
 
        if (!(cfile.fp = fopen( cfile.file, "r" ))) {
-               perror( "Cannot open config file" );
+               sys_error( "Cannot open config file '%s'", cfile.file );
                return 1;
        }
        buf[sizeof(buf) - 1] = 0;
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 574e3a4..a22c4c6 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -30,7 +30,6 @@
 #include <stdio.h>
 #include <stddef.h>
 #include <limits.h>
-#include <errno.h>
 #include <string.h>
 #include <ctype.h>
 
@@ -841,7 +840,7 @@ imap_socket_read( void *aux )
                if (*arg == '*') {
                        arg = next_arg( &cmd );
                        if (!arg) {
-                               error( "IMAP error: unable to parse untagged 
response\n" );
+                               error( "IMAP error: malformed untagged 
response\n" );
                                break;
                        }
 
@@ -1838,8 +1837,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, 
int *err )
                else if (!strcasecmp( "CertificateFile", cfg->cmd )) {
                        server->sconf.cert_file = expand_strdup( cfg->val );
                        if (access( server->sconf.cert_file, R_OK )) {
-                               error( "%s:%d: CertificateFile '%s': %s\n",
-                                      cfg->file, cfg->line, 
server->sconf.cert_file, strerror( errno ) );
+                               sys_error( "%s:%d: CertificateFile '%s'",
+                                          cfg->file, cfg->line, 
server->sconf.cert_file );
                                *err = 1;
                        }
                } else if (!strcasecmp( "RequireSSL", cfg->cmd ))
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 1fe3c51..2173e60 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -101,7 +101,7 @@ maildir_open_store( store_conf_t *conf,
        struct stat st;
 
        if (stat( conf->path, &st ) || !S_ISDIR(st.st_mode)) {
-               error( "Maildir error: cannot open store %s\n", conf->path );
+               error( "Maildir error: cannot open store '%s'\n", conf->path );
                cb( 0, aux );
                return;
        }
@@ -173,7 +173,7 @@ maildir_list( store_t *gctx,
        struct dirent *de;
 
        if (!(dir = opendir( gctx->conf->path ))) {
-               error( "%s: %s\n", gctx->conf->path, strerror(errno) );
+               sys_error( "Maildir error: cannot list %s", gctx->conf->path );
                maildir_invoke_bad_callback( gctx );
                cb( DRV_CANCELED, aux );
                return;
@@ -240,16 +240,14 @@ maildir_validate( const char *prefix, const char *box, 
int create, maildir_store
                if (errno == ENOENT) {
                        if (create) {
                                if (mkdir( buf, 0700 )) {
-                                       error( "Maildir error: mkdir %s: %s 
(errno %d)\n",
-                                              buf, strerror(errno), errno );
+                                       sys_error( "Maildir error: cannot 
create mailbox '%s'", buf );
                                        maildir_invoke_bad_callback( &ctx->gen 
);
                                        return DRV_CANCELED;
                                }
                                for (i = 0; i < 3; i++) {
                                        memcpy( buf + bl, subdirs[i], 4 );
                                        if (mkdir( buf, 0700 )) {
-                                               error( "Maildir error: mkdir 
%s: %s (errno %d)\n",
-                                                      buf, strerror(errno), 
errno );
+                                               sys_error( "Maildir error: 
cannot create directory %s", buf );
                                                return DRV_BOX_BAD;
                                        }
                                }
@@ -258,8 +256,7 @@ maildir_validate( const char *prefix, const char *box, int 
create, maildir_store
                                return DRV_BOX_BAD;
                        }
                } else {
-                       error( "Maildir error: stat %s: %s (errno %d)\n",
-                              buf, strerror(errno), errno );
+                       sys_error( "Maildir error: cannot access mailbox '%s'", 
buf );
                        return DRV_BOX_BAD;
                }
        } else {
@@ -273,8 +270,7 @@ maildir_validate( const char *prefix, const char *box, int 
create, maildir_store
                memcpy( buf + bl, "tmp/", 5 );
                bl += 4;
                if (!(dirp = opendir( buf ))) {
-                       error( "Maildir error: opendir: %s: %s (errno %d)\n",
-                              buf, strerror(errno), errno );
+                       sys_error( "Maildir error: cannot list %s", buf );
                        return DRV_BOX_BAD;
                }
                time( &now );
@@ -282,16 +278,14 @@ maildir_validate( const char *prefix, const char *box, 
int create, maildir_store
                        nfsnprintf( buf + bl, sizeof(buf) - bl, "%s", 
entry->d_name );
                        if (stat( buf, &st )) {
                                if (errno != ENOENT)
-                                       error( "Maildir error: stat: %s: %s 
(errno %d)\n",
-                                              buf, strerror(errno), errno );
+                                       sys_error( "Maildir error: cannot 
access %s", buf );
                        } else if (S_ISREG(st.st_mode) && now - st.st_ctime >= 
_24_HOURS) {
                                /* 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 );
                                if (unlink( buf ) && errno != ENOENT)
-                                       error( "Maildir error: unlink: %s: %s 
(errno %d)\n",
-                                              buf, strerror(errno), errno );
+                                       sys_error( "Maildir error: cannot 
remove %s", buf );
                        }
                }
                closedir( dirp );
@@ -360,9 +354,8 @@ maildir_store_uid( maildir_store_t *ctx )
 }
 
 static int
-maildir_init_uid( maildir_store_t *ctx, const char *msg )
+maildir_init_uid( maildir_store_t *ctx )
 {
-       info( "Maildir notice: %s.\n", msg ? msg : "cannot read UIDVALIDITY, 
creating new" );
        ctx->gen.uidvalidity = time( 0 );
        ctx->nuid = 0;
        ctx->uvok = 0;
@@ -377,6 +370,13 @@ maildir_init_uid( maildir_store_t *ctx, const char *msg )
 }
 
 static int
+maildir_init_uid_new( maildir_store_t *ctx )
+{
+       info( "Maildir notice: no UIDVALIDITY, creating new.\n" );
+       return maildir_init_uid( ctx );
+}
+
+static int
 maildir_uidval_lock( maildir_store_t *ctx )
 {
        int n;
@@ -402,7 +402,7 @@ maildir_uidval_lock( maildir_store_t *ctx )
        lseek( ctx->uvfd, 0, SEEK_SET );
        if ((n = read( ctx->uvfd, buf, sizeof(buf) )) <= 0 ||
            (buf[n] = 0, sscanf( buf, "%d\n%d", &ctx->gen.uidvalidity, 
&ctx->nuid ) != 2)) {
-               return maildir_init_uid( ctx, 0 );
+               return maildir_init_uid_new( ctx );
        } else
                ctx->uvok = 1;
        return DRV_OK;
@@ -532,7 +532,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
                for (i = 0; i < 2; i++) {
                        memcpy( buf + bl, subdirs[i], 4 );
                        if (!(d = opendir( buf ))) {
-                               perror( buf );
+                               sys_error( "Maildir error: cannot list %s", buf 
);
 #ifdef USE_DB
                                if (!ctx->db)
 #endif /* USE_DB */
@@ -633,7 +633,8 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
                        entry = &msglist->ents[i];
                        if (entry->uid != INT_MAX) {
                                if (uid == entry->uid) {
-                                       if ((ret = maildir_init_uid( ctx, 
"duplicate UID; changing UIDVALIDITY" )) != DRV_OK) {
+                                       info( "Maildir notice: duplicate UID; 
changing UIDVALIDITY.\n");
+                                       if ((ret = maildir_init_uid( ctx )) != 
DRV_OK) {
                                                maildir_free_scan( msglist );
                                                return ret;
                                        }
@@ -670,13 +671,14 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
                                memcpy( nbuf, buf, bl + 4 );
                                nfsnprintf( nbuf + bl + 4, sizeof(nbuf) - bl - 
4, "%s", entry->base );
                                if (rename( nbuf, buf )) {
-                                 notok:
                                        if (errno != ENOENT) {
-                                               perror( buf );
+                                               sys_error( "Maildir error: 
cannot rename %s to %s", nbuf, buf );
+                                         fail:
                                                maildir_uidval_unlock( ctx );
                                                maildir_free_scan( msglist );
                                                return DRV_BOX_BAD;
                                        }
+                                 retry:
                                        maildir_free_scan( msglist );
                                        goto again;
                                }
@@ -685,13 +687,23 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
                                memcpy( entry->base, buf + bl + 4, fnl );
                        }
                        if (ctx->gen.opts & OPEN_SIZE) {
-                               if (stat( buf, &st ))
-                                       goto notok;
+                               if (stat( buf, &st )) {
+                                       if (errno != ENOENT) {
+                                               sys_error( "Maildir error: 
cannot stat %s", buf );
+                                               goto fail;
+                                       }
+                                       goto retry;
+                               }
                                entry->size = st.st_size;
                        }
                        if (ctx->gen.opts & OPEN_FIND) {
-                               if (!(f = fopen( buf, "r" )))
-                                       goto notok;
+                               if (!(f = fopen( buf, "r" ))) {
+                                       if (errno != ENOENT) {
+                                               sys_error( "Maildir error: 
cannot open %s", buf );
+                                               goto fail;
+                                       }
+                                       goto retry;
+                               }
                                while (fgets( nbuf, sizeof(nbuf), f )) {
                                        if (!nbuf[0] || nbuf[0] == '\n')
                                                break;
@@ -767,7 +779,7 @@ maildir_select( store_t *gctx, int create,
        nfsnprintf( uvpath, sizeof(uvpath), "%s/.uidvalidity", gctx->path );
 #ifndef USE_DB
        if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) < 0) {
-               perror( uvpath );
+               sys_error( "Maildir error: cannot write %s", uvpath );
                cb( DRV_BOX_BAD, aux );
                return;
        }
@@ -783,7 +795,7 @@ maildir_select( store_t *gctx, int create,
                                if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 
0600 )) >= 0)
                                        goto fnok;
                        }
-                       perror( uvpath );
+                       sys_error( "Maildir error: cannot write %s", uvpath );
                        cb( DRV_BOX_BAD, aux );
                        return;
                }
@@ -793,7 +805,7 @@ maildir_select( store_t *gctx, int create,
 #endif
                lck.l_type = F_WRLCK;
                if (fcntl( ctx->uvfd, F_SETLKW, &lck )) {
-                       perror( uvpath );
+                       sys_error( "Maildir error: cannot lock %s", uvpath );
                  bork:
                        close( ctx->uvfd );
                        ctx->uvfd = -1;
@@ -817,7 +829,7 @@ maildir_select( store_t *gctx, int create,
                                ctx->db->err( ctx->db, ret, "Maildir error: 
db->get()" );
                                goto dbork;
                        }
-                       if (maildir_init_uid( ctx, 0 ) != DRV_OK)
+                       if (maildir_init_uid_new( ctx ) != DRV_OK)
                                goto dbork;
                } else {
                        ctx->gen.uidvalidity = ((int *)value.data)[0];
@@ -926,12 +938,13 @@ maildir_rescan( maildir_store_t *ctx )
 }
 
 static int
-maildir_again( maildir_store_t *ctx, maildir_message_t *msg, const char *fn )
+maildir_again( maildir_store_t *ctx, maildir_message_t *msg,
+               const char *err, const char *fn, const char *fn2 )
 {
        int ret;
 
        if (errno != ENOENT) {
-               perror( fn );
+               sys_error( err, fn, fn2 );
                return DRV_BOX_BAD;
        }
        if ((ret = maildir_rescan( ctx )) != DRV_OK)
@@ -953,7 +966,7 @@ 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) {
+               if ((ret = maildir_again( ctx, msg, "Cannot open %s", buf, 0 )) 
!= DRV_OK) {
                        cb( ret, aux );
                        return;
                }
@@ -962,7 +975,7 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, 
msg_data_t *data,
        data->len = st.st_size;
        data->data = nfmalloc( data->len );
        if (read( fd, data->data, data->len ) != data->len) {
-               perror( buf );
+               sys_error( "Maildir error: cannot read %s", buf );
                close( fd );
                cb( DRV_MSG_BAD, aux );
                return;
@@ -1028,7 +1041,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
        nfsnprintf( buf, sizeof(buf), "%s%s/tmp/%s%s", prefix, box, base, fbuf 
);
        if ((fd = open( buf, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) {
                if (errno != ENOENT) {
-                       perror( buf );
+                       sys_error( "Maildir error: cannot create %s", buf );
                        free( data->data );
                        cb( DRV_BOX_BAD, 0, aux );
                        return;
@@ -1039,7 +1052,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
                        return;
                }
                if ((fd = open( buf, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) {
-                       perror( buf );
+                       sys_error( "Maildir error: cannot create %s", buf );
                        free( data->data );
                        cb( DRV_BOX_BAD, 0, aux );
                        return;
@@ -1049,23 +1062,23 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
        free( data->data );
        if (ret != data->len) {
                if (ret < 0)
-                       perror( buf );
+                       sys_error( "Maildir error: cannot write %s", buf );
                else
-                       error( "Maildir error: %s: partial write\n", buf );
+                       error( "Maildir error: cannot write %s. Disk full?\n", 
buf );
                close( fd );
                cb( DRV_BOX_BAD, 0, aux );
                return;
        }
        if (close( fd ) < 0) {
                /* Quota exceeded may cause this. */
-               perror( buf );
+               sys_error( "Maildir error: cannot write %s", buf );
                cb( DRV_BOX_BAD, 0, aux );
                return;
        }
        /* Moving seen messages to cur/ is strictly speaking incorrect, but 
makes mutt happy. */
        nfsnprintf( nbuf, sizeof(nbuf), "%s%s/%s/%s%s", prefix, box, 
subdirs[!(data->flags & F_SEEN)], base, fbuf );
        if (rename( buf, nbuf )) {
-               perror( nbuf );
+               sys_error( "Maildir error: cannot rename %s to %s", buf, nbuf );
                cb( DRV_BOX_BAD, 0, aux );
                return;
        }
@@ -1131,7 +1144,7 @@ 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) {
+               if ((ret = maildir_again( ctx, msg, "Maildir error: cannot 
rename %s to %s", buf, nbuf )) != DRV_OK) {
                        cb( ret, aux );
                        return;
                }
@@ -1189,12 +1202,12 @@ maildir_trash_msg( store_t *gctx, message_t *gmsg,
                        if (!rename( buf, nbuf ))
                                break;
                        if (errno != ENOENT) {
-                               perror( nbuf );
+                               sys_error( "Maildir error: cannot move %s to 
%s", buf, nbuf );
                                cb( DRV_BOX_BAD, aux );
                                return;
                        }
                }
-               if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
+               if ((ret = maildir_again( ctx, msg, "Maildir error: cannot move 
%s to %s", buf, nbuf )) != DRV_OK) {
                        cb( ret, aux );
                        return;
                }
@@ -1232,7 +1245,7 @@ maildir_close( store_t *gctx,
                                        if (errno == ENOENT)
                                                retry = 1;
                                        else
-                                               perror( buf );
+                                               sys_error( "Maildir error: 
cannot remove %s", buf );
                                } else {
                                        msg->status |= M_DEAD;
                                        gctx->count--;
diff --git a/src/isync.h b/src/isync.h
index e72c627..c9b5798 100644
--- a/src/isync.h
+++ b/src/isync.h
@@ -83,6 +83,7 @@ typedef struct {
        int fd;
        int state;
        const server_conf_t *conf; /* needed during connect */
+       char *name;
 #ifdef HAVE_LIBSSL
        SSL *ssl;
 #endif
@@ -366,6 +367,7 @@ static INLINE void socket_init( conn_t *conn,
        conn->write_callback = write_callback;
        conn->callback_aux = aux;
        conn->fd = -1;
+       conn->name = 0;
        conn->write_buf_append = &conn->write_buf;
 }
 void socket_connect( conn_t *conn, void (*cb)( int ok, void *aux ) );
@@ -397,6 +399,7 @@ void info( const char *, ... );
 void infon( const char *, ... );
 void warn( const char *, ... );
 void error( const char *, ... );
+void sys_error( const char *, ... );
 
 char *next_arg( char ** );
 
diff --git a/src/mdconvert.c b/src/mdconvert.c
index c2fbf25..bd4b7cb 100644
--- a/src/mdconvert.c
+++ b/src/mdconvert.c
@@ -35,6 +35,32 @@
 
 #define EXE "mdconvert"
 
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+# define ATTR_NORETURN __attribute__((noreturn))
+#else
+# define ATTR_NORETURN
+#endif
+
+static void ATTR_NORETURN
+oob( void )
+{
+       fputs( "Fatal: buffer too small. Please report a bug.\n", stderr );
+       abort();
+}
+
+static void
+sys_error( const char *msg, ... )
+{
+       va_list va;
+       char buf[1024];
+
+       va_start( va, msg );
+       if ((unsigned)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
+               oob();
+       va_end( va );
+       perror( buf );
+}
+
 static int
 nfsnprintf( char *buf, int blen, const char *fmt, ... )
 {
@@ -42,10 +68,8 @@ nfsnprintf( char *buf, int blen, const char *fmt, ... )
        va_list va;
 
        va_start( va, fmt );
-       if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= 
(unsigned)blen) {
-               fputs( "Fatal: buffer too small. Please report a bug.\n", 
stderr );
-               abort();
-       }
+       if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= 
(unsigned)blen)
+               oob();
        va_end( va );
        return ret;
 }
@@ -81,15 +105,15 @@ convert( const char *box, int altmap )
        nfsnprintf( tdpath, sizeof(tdpath), "%s.tmp", dpath );
        if ((sfd = open( spath, O_RDWR )) < 0) {
                if (errno != ENOENT)
-                       perror( spath );
+                       sys_error( "Cannot open %s", spath );
                return 1;
        }
        if (fcntl( sfd, F_SETLKW, &lck )) {
-               perror( spath );
+               sys_error( "Cannot lock %s", spath );
                goto sbork;
        }
        if ((dfd = open( tdpath, O_RDWR|O_CREAT, 0600 )) < 0) {
-               perror( tdpath );
+               sys_error( "Cannot create %s", tdpath );
                goto sbork;
        }
        if (db_create( &db, 0, 0 )) {
@@ -138,7 +162,7 @@ convert( const char *box, int altmap )
        for (i = 0; i < 2; i++) {
                bl = nfsnprintf( buf, sizeof(buf), "%s/%s/", box, subdirs[i] );
                if (!(d = opendir( buf ))) {
-                       perror( "opendir" );
+                       sys_error( "Cannot list %s", buf );
                        goto dbork;
                }
                while ((e = readdir( d ))) {
@@ -185,7 +209,7 @@ convert( const char *box, int altmap )
                        if (rename( buf, buf2 )) {
                                if (errno == ENOENT)
                                        goto again;
-                               perror( buf );
+                               sys_error( "Cannot rename %s to %s", buf, buf2 
);
                          ebork:
                                closedir( d );
                                goto dbork;
@@ -198,11 +222,11 @@ convert( const char *box, int altmap )
        db->close( db, 0 );
        close( dfd );
        if (rename( tdpath, dpath )) {
-               perror( dpath );
+               sys_error( "Cannot rename %s to %s", tdpath, dpath );
                return 1;
        }
        if (unlink( spath ))
-               perror( spath );
+               sys_error( "Cannot remove %s", spath );
        close( sfd );
        return 0;
 }
diff --git a/src/socket.c b/src/socket.c
index bf8a837..ca44bb3 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -79,15 +79,15 @@ ssl_return( const char *func, conn_t *conn, int ret )
        case SSL_ERROR_SSL:
                if (!(err = ERR_get_error())) {
                        if (ret == 0)
-                               error( "SSL_%s: unexpected EOF\n", func );
+                               error( "Socket error: secure %s %s: unexpected 
EOF\n", func, conn->name );
                        else
-                               error( "SSL_%s: %s\n", func, strerror( errno ) 
);
+                               sys_error( "Socket error: secure %s %s", func, 
conn->name );
                } else {
-                       error( "SSL_%s: %s\n", func, ERR_error_string( err, 0 ) 
);
+                       error( "Socket error: secure %s %s: %s\n", func, 
conn->name, ERR_error_string( err, 0 ) );
                }
                break;
        default:
-               error( "SSL_%s: unhandled SSL error %d\n", func, err );
+               error( "Socket error: secure %s %s: unhandled SSL error %d\n", 
func, conn->name, err );
                break;
        }
        if (conn->state == SCK_STARTTLS)
@@ -148,11 +148,11 @@ verify_cert( const server_conf_t *conf, conn_t *sock )
 
        while (conf->cert_file) { /* while() instead of if() so break works */
                if (X509_cmp_current_time( X509_get_notBefore( cert )) >= 0) {
-                       error( "Server certificate is not yet valid" );
+                       error( "Server certificate is not yet valid\n" );
                        break;
                }
                if (X509_cmp_current_time( X509_get_notAfter( cert )) <= 0) {
-                       error( "Server certificate has expired" );
+                       error( "Server certificate has expired\n" );
                        break;
                }
                if (!X509_digest( cert, EVP_sha1(), md, &n )) {
@@ -160,8 +160,7 @@ verify_cert( const server_conf_t *conf, conn_t *sock )
                        break;
                }
                if (!(fp = fopen( conf->cert_file, "rt" ))) {
-                       error( "Unable to load CertificateFile '%s': %s\n",
-                              conf->cert_file, strerror( errno ) );
+                       sys_error( "Unable to load CertificateFile '%s'", 
conf->cert_file );
                        return -1;
                }
                err = -1;
@@ -197,7 +196,7 @@ verify_cert( const server_conf_t *conf, conn_t *sock )
        X509_STORE_CTX_cleanup( &xsc );
        if (!err)
                return 0;
-       error( "Error, can't verify certificate: %s (%d)\n",
+       error( "Error, cannot verify certificate: %s (%d)\n",
               X509_verify_cert_error_string( err ), err );
 
        X509_NAME_oneline( X509_get_subject_name( cert ), buf, sizeof(buf) );
@@ -286,7 +285,7 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void 
*aux ) )
 static void
 start_tls_p2( conn_t *conn )
 {
-       switch (ssl_return( "connect", conn, SSL_connect( conn->ssl ) )) {
+       switch (ssl_return( "connect to", conn, SSL_connect( conn->ssl ) )) {
        case -1:
                start_tls_p3( conn, 0 );
                break;
@@ -337,7 +336,8 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux 
) )
 
        /* open connection to IMAP server */
        if (conf->tunnel) {
-               infon( "Starting tunnel '%s'... ", conf->tunnel );
+               nfasprintf( &sock->name, "tunnel '%s'", conf->tunnel );
+               infon( "Starting %s... ", sock->name );
 
                if (socketpair( PF_UNIX, SOCK_STREAM, 0, a )) {
                        perror( "socketpair" );
@@ -387,11 +387,12 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void 
*aux ) )
                fcntl( s, F_SETFL, O_NONBLOCK );
                add_fd( s, socket_fd_cb, sock );
 
-               infon( "Connecting to %s (%s:%hu) ... ",
-                      conf->host, inet_ntoa( addr.sin_addr ), ntohs( 
addr.sin_port ) );
+               nfasprintf( &sock->name, "%s (%s:%hu)",
+                           conf->host, inet_ntoa( addr.sin_addr ), ntohs( 
addr.sin_port ) );
+               infon( "Connecting to %s... ", sock->name );
                if (connect( s, (struct sockaddr *)&addr, sizeof(addr) )) {
                        if (errno != EINPROGRESS) {
-                               perror( "connect" );
+                               sys_error( "Cannot connect to %s", sock->name );
                                socket_close_internal( sock );
                                goto bail;
                        }
@@ -416,19 +417,17 @@ socket_connected( conn_t *conn )
        int soerr;
        socklen_t selen = sizeof(soerr);
 
-       infon( "Connecting to %s: ", conn->conf->host );
        if (getsockopt( conn->fd, SOL_SOCKET, SO_ERROR, &soerr, &selen )) {
                perror( "getsockopt" );
                exit( 1 );
        }
        if (soerr) {
                errno = soerr;
-               perror( "connect" );
+               sys_error( "Cannot connect to %s", conn->name );
                socket_close_internal( conn );
                socket_connect_bail( conn );
                return;
        }
-       info( "ok\n" );
        socket_connected2( conn );
 }
 
@@ -443,6 +442,8 @@ socket_connected2( conn_t *conn )
 static void
 socket_connect_bail( conn_t *conn )
 {
+       free( conn->name );
+       conn->name = 0;
        conn->callbacks.connect( 0, conn->callback_aux );
 }
 
@@ -453,6 +454,8 @@ socket_close( conn_t *sock )
 {
        if (sock->fd >= 0)
                socket_close_internal( sock );
+       free( sock->name );
+       sock->name = 0;
 #ifdef HAVE_LIBSSL
        if (sock->ssl) {
                SSL_free( sock->ssl );
@@ -478,7 +481,7 @@ socket_fill( conn_t *sock )
        buf = sock->buf + n;
 #ifdef HAVE_LIBSSL
        if (sock->ssl) {
-               if ((n = ssl_return( "read", sock, SSL_read( sock->ssl, buf, 
len ) )) <= 0)
+               if ((n = ssl_return( "read from", sock, SSL_read( sock->ssl, 
buf, len ) )) <= 0)
                        return;
                if (n == len && SSL_pending( sock->ssl ))
                        fake_fd( sock->fd, POLLIN );
@@ -486,11 +489,11 @@ socket_fill( conn_t *sock )
 #endif
        {
                if ((n = read( sock->fd, buf, len )) < 0) {
-                       perror( "read" );
+                       sys_error( "Socket error: read from %s", sock->name );
                        socket_fail( sock );
                        return;
                } else if (!n) {
-                       error( "read: unexpected EOF\n" );
+                       error( "Socket error: read from %s: unexpected EOF\n", 
sock->name );
                        socket_fail( sock );
                        return;
                }
@@ -549,12 +552,12 @@ do_write( conn_t *sock, char *buf, int len )
        assert( sock->fd >= 0 );
 #ifdef HAVE_LIBSSL
        if (sock->ssl)
-               return ssl_return( "write", sock, SSL_write( sock->ssl, buf, 
len ) );
+               return ssl_return( "write to", sock, SSL_write( sock->ssl, buf, 
len ) );
 #endif
        n = write( sock->fd, buf, len );
        if (n < 0) {
                if (errno != EAGAIN && errno != EWOULDBLOCK) {
-                       perror( "write" );
+                       sys_error( "Socket error: write to %s", sock->name );
                        socket_fail( sock );
                } else {
                        n = 0;
@@ -646,7 +649,7 @@ socket_fd_cb( int events, void *aux )
        conn_t *conn = (conn_t *)aux;
 
        if (events & POLLERR) {
-               error( "Unidentified socket error.\n" );
+               error( "Unidentified socket error from %s.\n", conn->name );
                socket_fail( conn );
                return;
        }
diff --git a/src/sync.c b/src/sync.c
index 9db8228..d72ae62 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -40,7 +40,7 @@ void
 Fclose( FILE *f )
 {
        if (fclose( f ) == EOF) {
-               perror( "cannot close file" );
+               sys_error( "Error: cannot close file. Disk full?" );
                exit( 1 );
        }
 }
@@ -55,7 +55,7 @@ Fprintf( FILE *f, const char *msg, ... )
        r = vfprintf( f, msg, va );
        va_end( va );
        if (r < 0) {
-               perror( "cannot write file" );
+               sys_error( "Error: cannot write file. Disk full?" );
                exit( 1 );
        }
 }
@@ -624,12 +624,12 @@ box_selected( int sts, void *aux )
                }
                free( csname );
                if (!(s = strrchr( svars->dname, '/' ))) {
-                       error( "Error: invalid SyncState '%s'\n", svars->dname 
);
+                       error( "Error: invalid SyncState location '%s'\n", 
svars->dname );
                        goto sbail;
                }
                *s = 0;
                if (mkdir( svars->dname, 0700 ) && errno != EEXIST) {
-                       error( "Error: cannot create SyncState directory '%s': 
%s\n", svars->dname, strerror(errno) );
+                       sys_error( "Error: cannot create SyncState directory 
'%s'", svars->dname );
                        goto sbail;
                }
                *s = '/';
@@ -645,7 +645,7 @@ box_selected( int sts, void *aux )
        lck.l_type = F_WRLCK;
 #endif
        if ((svars->lfd = open( svars->lname, O_WRONLY|O_CREAT, 0666 )) < 0) {
-               error( "Error: cannot create lock file %s: %s\n", svars->lname, 
strerror(errno) );
+               sys_error( "Error: cannot create lock file %s", svars->lname );
                svars->ret = SYNC_FAIL;
                sync_bail2( svars );
                return;
diff --git a/src/util.c b/src/util.c
index 2c4179c..11ce4fc 100644
--- a/src/util.c
+++ b/src/util.c
@@ -120,6 +120,23 @@ error( const char *msg, ... )
        va_end( va );
 }
 
+void
+sys_error( const char *msg, ... )
+{
+       va_list va;
+       char buf[1024];
+
+       if (need_nl) {
+               putchar( '\n' );
+               need_nl = 0;
+       }
+       va_start( va, msg );
+       if ((unsigned)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
+               oob();
+       va_end( va );
+       perror( buf );
+}
+
 char *
 next_arg( char **s )
 {

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to