isync

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

commit cbac8aa75ce041384155d360f040aec5049d1de5
parent 094bc883e84ab2bc0e970512dd3b9502eb9c888c
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date:   Sun,  1 Oct 2017 15:21:05 +0200

delete the compat wrapper

it was deprecated in 1.2. until 1.4 gets released, enough time will have
passed for sure.

Diffstat:
MNEWS | 4++++
MREADME | 3+--
Mconfigure.ac | 2+-
Mdebian/README.Debian | 13+++++++------
Mdebian/control | 5-----
Msrc/Makefile.am | 5-----
Dsrc/compat/.gitignore | 1-
Dsrc/compat/Makefile.am | 12------------
Dsrc/compat/config.c | 551-------------------------------------------------------------------------------
Dsrc/compat/convert.c | 265-------------------------------------------------------------------------------
Dsrc/compat/isync.1 | 328-------------------------------------------------------------------------------
Dsrc/compat/isync.h | 116-------------------------------------------------------------------------------
Dsrc/compat/isyncrc.sample | 55-------------------------------------------------------
Dsrc/compat/main.c | 438-------------------------------------------------------------------------------
Dsrc/compat/util.c | 208-------------------------------------------------------------------------------
Msrc/mbsync.1 | 2+-
16 files changed, 14 insertions(+), 1994 deletions(-)

diff --git a/NEWS b/NEWS @@ -1,3 +1,7 @@ +[1.4.0] + +The 'isync' compatibility wrapper was removed. + [1.3.0] Network timeout handling has been added. diff --git a/README b/README @@ -23,8 +23,7 @@ Mailboxes can be safely modified while ``mbsync'' operates. Multiple replicas of each mailbox can be maintained. isync is the project name, while mbsync is the current executable name; this -change was necessary because of massive changes in the user interface. An -isync executable still exists; it is a compatibility wrapper around mbsync. +change was necessary because of massive changes in the user interface. * Features diff --git a/configure.ac b/configure.ac @@ -179,7 +179,7 @@ fi AM_CONDITIONAL(with_compat, test "x$ob_cv_enable_compat" != xno -a "x$ac_cv_berkdb4" = xyes) AM_CONDITIONAL(with_mdconvert, test "x$ac_cv_berkdb4" = xyes) -AC_CONFIG_FILES([Makefile src/Makefile src/compat/Makefile isync.spec]) +AC_CONFIG_FILES([Makefile src/Makefile isync.spec]) AC_OUTPUT AC_MSG_RESULT() diff --git a/debian/README.Debian b/debian/README.Debian @@ -3,10 +3,11 @@ A note from isync's web site: isync can be integrated into Mutt fairly easily with a few hooks: folder-hook ~A bind index $ <sync-mailbox> - folder-hook +maildir 'macro index $ "<sync-mailbox>!isync -e maildir\n"' + folder-hook +maildir 'macro index $ "<sync-mailbox>!mbsync the_channel:maildir\n"' -where maildir is the name of the local mailbox (or its alias). This works well -so long as you are not modifying the IMAP mailbox outside of Mutt. However, if -you are using another mail program simultaneously Mutt will have the wrong idea -of the local mailbox flags and messages will start disappearing from its index -display (don't worry, they are still on disk). +where the_channel is the Channel used to sync this mailbox, and maildir is the +name of the local mailbox itself. This works well so long as you are not +modifying the IMAP mailbox outside of Mutt. However, if you are using another +mail program simultaneously, Mutt will have the wrong idea of the local mailbox +flags and messages will start disappearing from its index display (don't worry, +they are still on disk). diff --git a/debian/control b/debian/control @@ -26,11 +26,6 @@ Description: IMAP and MailDir mailbox synchronizer deletions and flag changes can be propagated both ways. isync is suitable for use in IMAP-disconnected mode. . - The main application was much improved in version 1.0. Those improvements - lead to interface changes and the application being renamed to mbsync. The - application isync is now only a wrapper to keep compatibility with earlier - versions. - . Features: * Fine-grained selection of synchronization operations to perform * Synchronizes single mailboxes or entire mailbox collections diff --git a/src/Makefile.am b/src/Makefile.am @@ -1,8 +1,3 @@ -if with_compat -compat_dir = compat -endif -SUBDIRS = $(compat_dir) - mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c drv_proxy.c mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) noinst_HEADERS = common.h config.h driver.h sync.h socket.h diff --git a/src/compat/.gitignore b/src/compat/.gitignore @@ -1 +0,0 @@ -/isync diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am @@ -1,12 +0,0 @@ -bin_PROGRAMS = isync - -isync_SOURCES = main.c config.c convert.c util.c -isync_LDADD = $(DB_LIBS) -noinst_HEADERS = isync.h - -man_MANS = isync.1 - -exampledir = $(docdir)/examples -example_DATA = isyncrc.sample - -EXTRA_DIST = $(example_DATA) $(man_MANS) diff --git a/src/compat/config.c b/src/compat/config.c @@ -1,551 +0,0 @@ -/* - * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer - * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> - * Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "isync.h" - -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include <pwd.h> -#include <sys/types.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> - -static char * -my_strndup( const char *s, size_t nchars ) -{ - char *r = nfmalloc( sizeof(char) * (nchars + 1) ); - memcpy( r, s, nchars ); - r[nchars] = 0; - return r; -} - -char * -expand_strdup( const char *s ) -{ - struct passwd *pw; - const char *p, *q; - char *r; - - if (*s == '~') { - s++; - if (!*s) { - p = 0; - q = Home; - } else if (*s == '/') { - p = s + 1; - q = Home; - } else { - if ((p = strchr( s, '/' ))) { - r = my_strndup( s, (int)(p - s) ); - pw = getpwnam( r ); - free( r ); - p++; - } else - pw = getpwnam( s ); - if (!pw) - return 0; - q = pw->pw_dir; - } - nfasprintf( &r, "%s/%s", q, p ? p : "" ); - return r; - } else if (*s != '/' && xmaildir) { - nfasprintf( &r, "%s/%s", xmaildir, s ); - return r; - } else - return nfstrdup( s ); -} - -static int -is_true( const char *val ) -{ - return - !strcasecmp( val, "yes" ) || - !strcasecmp( val, "true" ) || - !strcasecmp( val, "on" ) || - !strcmp( val, "1" ); -} - -void -load_config( const char *path, config_t ***stor ) -{ - config_t **sstor, *cfg; - FILE *fp; - char *p, *cmd, *val; - int line = 0; - char buf[1024]; - - if (!(fp = fopen( path, "r" ))) { - if (errno != ENOENT) - sys_error( "Cannot read config file '%s'", path ); - return; - } - if (!Quiet && !Debug && !Verbose) - printf( "Reading configuration file %s\n", path ); - buf[sizeof(buf) - 1] = 0; - cfg = &global; - while (fgets( buf, sizeof(buf) - 1, fp )) { - p = buf; - cmd = next_arg( &p ); - val = next_arg( &p ); - line++; - if (!cmd || *cmd == '#') - continue; - if (!val) { - fprintf( stderr, "%s:%d: parameter missing\n", path, line ); - continue; - } - if (!strcasecmp( "Mailbox", cmd )) { - if (o2o) - break; - cfg = **stor = nfmalloc( sizeof(config_t) ); - *stor = &cfg->next; - memcpy( cfg, &global, sizeof(config_t) ); - /* not expanded at this point */ - cfg->path = nfstrdup( val ); - } else if (!strcasecmp( "OneToOne", cmd )) { - if (boxes) { - forbid: - fprintf( stderr, - "%s:%d: keyword '%s' allowed only in global section\n", - path, line, cmd ); - continue; - } - o2o = is_true( val ); - } else if (!strcasecmp( "Maildir", cmd )) { - if (boxes) - goto forbid; - maildir = nfstrdup( val ); - xmaildir = expand_strdup( val ); - } else if (!strcasecmp( "Folder", cmd )) { - if (boxes) - goto forbid; - folder = nfstrdup( val ); - } else if (!strcasecmp( "Inbox", cmd )) { - if (boxes) - goto forbid; - inbox = nfstrdup( val ); - } else if (!strcasecmp( "Host", cmd )) { - if (starts_with( val, -1, "imaps:", 6 )) { - val += 6; - cfg->use_imaps = 1; - cfg->port = 993; - cfg->use_sslv3 = 1; - } - cfg->host = nfstrdup( val ); - } else if (!strcasecmp( "User", cmd )) - cfg->user = nfstrdup( val ); - else if (!strcasecmp( "Pass", cmd )) - cfg->pass = nfstrdup( val ); - else if (!strcasecmp ( "Port", cmd )) - cfg->port = atoi( val ); - else if (!strcasecmp ( "Box", cmd )) - cfg->box = nfstrdup( val ); - else if (!strcasecmp ( "Alias", cmd )) { - if (!boxes) { - fprintf( stderr, - "%s:%d: keyword 'Alias' allowed only in mailbox specification\n", - path, line ); - continue; - } - cfg->alias = nfstrdup( val ); - } else if (!strcasecmp( "MaxSize", cmd )) - cfg->max_size = atol( val ); - else if (!strcasecmp ( "MaxMessages", cmd )) - cfg->max_messages = atol( val ); - else if (!strcasecmp ( "UseNamespace", cmd )) - cfg->use_namespace = is_true( val ); - else if (!strcasecmp ( "CopyDeletedTo", cmd )) - cfg->copy_deleted_to = nfstrdup( val ); - else if (!strcasecmp ( "Tunnel", cmd )) - cfg->tunnel = nfstrdup( val ); - else if (!strcasecmp ( "Expunge", cmd )) - cfg->expunge = is_true( val ); - else if (!strcasecmp( "Delete", cmd )) - cfg->delete = is_true( val ); - else if (!strcasecmp( "CertificateFile", cmd )) - cfg->cert_file = expand_strdup( val ); - else if (!strcasecmp( "RequireSSL", cmd )) - cfg->require_ssl = is_true( val ); - else if (!strcasecmp( "UseSSLv2", cmd )) - fprintf( stderr, "Warning: UseSSLv2 is no longer supported\n" ); - else if (!strcasecmp( "UseSSLv3", cmd )) - cfg->use_sslv3 = is_true( val ); - else if (!strcasecmp( "UseTLSv1", cmd )) - cfg->use_tlsv1 = is_true( val ); - else if (!strcasecmp( "RequireCRAM", cmd )) - cfg->require_cram = is_true( val ); - else if (buf[0]) - fprintf( stderr, "%s:%d: unknown keyword '%s'\n", path, line, cmd ); - } - fclose( fp ); - if (o2o) { - if (!global.host && !global.tunnel) { - fprintf( stderr, "Neither Host nor Tunnel given to OneToOne. Aborting.\n" ); - exit( 1 ); - } - } else - for (sstor = &boxes; (cfg = *sstor); ) { - if (!cfg->host && !cfg->tunnel) { - fprintf( stderr, "Mailbox '%s' has neither Host nor Tunnel. Skipping.\n", - cfg->alias ? cfg->alias : cfg->path ); - if (&cfg->next == *stor) - *stor = sstor; - *sstor = cfg->next; - continue; - } - sstor = &cfg->next; - } -} - -static const char * -tb( int on ) -{ - return on ? "yes" : "no"; -} - -static const char * -quotify( const char *str ) -{ - char *ostr; - int i; - - for (i = 0; str[i]; i++) { - if (isspace( str[i] )) { - nfasprintf( &ostr, "\"%s\"", str ); - return ostr; - } - } - return str; -} - -static void -write_imap_server( FILE *fp, config_t *cfg ) -{ - config_t *pbox; - char *p, *p2; - int hl, a1, a2, a3, a4; - char buf[128], ubuf[64]; - static int tunnels; - - /* The old server names determine the derived store names. They are kinda stupid, - * but can't be changed, because store names are encoded in state file names. */ - if (cfg->tunnel) - nfasprintf( (char **)&cfg->old_server_name, "tunnel%d", ++tunnels ); - else { - if (sscanf( cfg->host, "%d.%d.%d.%d", &a1, &a2, &a3, &a4 ) == 4) - hl = nfsnprintf( buf, sizeof(buf), "%s", cfg->host ); - else { - /* XXX this does not avoid clashes. add port? */ - p = strrchr( cfg->host, '.' ); - if (!p) - hl = nfsnprintf( buf, sizeof(buf), "%s", cfg->host ); - else { - hl = nfsnprintf( buf, sizeof(buf), "%.*s", p - cfg->host, cfg->host ); - p2 = strrchr( buf, '.' ); - if (p2) - hl = sprintf( buf, "%s", p2 + 1 ); - } - } - if (boxes) /* !o2o */ - for (pbox = boxes; pbox != cfg; pbox = pbox->next) - if (equals( pbox->old_server_name, -1, buf, hl )) { - nfasprintf( (char **)&cfg->old_server_name, "%s-%d", buf, ++pbox->old_servers ); - goto gotsrv; - } - cfg->old_server_name = nfstrdup( buf ); - cfg->old_servers = 1; - gotsrv: ; - } - - /* The "new" server names determine the names of the accounts themselves. - * They are optimized for descriptiveness, e.g. in password prompts. */ - if (cfg->user) - nfsnprintf( ubuf, sizeof(ubuf), "%s@", cfg->user ); - else - ubuf[0] = 0; - if (!cfg->host) - hl = nfsnprintf( buf, sizeof(buf), "%stunnel", ubuf ); - else { - if (cfg->port != (cfg->use_imaps ? 993 : 143)) - hl = nfsnprintf( buf, sizeof(buf), "%s%s_%d", ubuf, cfg->host, cfg->port ); - else - hl = nfsnprintf( buf, sizeof(buf), "%s%s", ubuf, cfg->host ); - } - if (boxes) /* !o2o */ - for (pbox = boxes; pbox != cfg; pbox = pbox->next) - if (equals( pbox->server_name, -1, buf, hl )) { - nfasprintf( (char **)&cfg->server_name, "%s-%d", buf, ++pbox->servers ); - goto ngotsrv; - } - cfg->server_name = nfstrdup( buf ); - cfg->servers = 1; - ngotsrv: ; - - fprintf( fp, "IMAPAccount %s\n", cfg->server_name ); - if (cfg->tunnel) - fprintf( fp, "Tunnel \"%s\"\n", cfg->tunnel ); - else { - if (cfg->use_imaps) - fprintf( fp, "Host imaps:%s\n", cfg->host ); - else - fprintf( fp, "Host %s\n", cfg->host ); - fprintf( fp, "Port %d\n", cfg->port ); - } - if (cfg->user) - fprintf( fp, "User %s\n", quotify( cfg->user ) ); - if (cfg->pass) - fprintf( fp, "Pass %s\n", quotify( cfg->pass ) ); - fprintf( fp, "RequireCRAM %s\nRequireSSL %s\n" - "UseSSLv3 %s\nUseTLSv1 %s\nUseTLSv1.1 %s\nUseTLSv1.2 %s\n", - tb(cfg->require_cram), tb(cfg->require_ssl), - tb(cfg->use_sslv3), tb(cfg->use_tlsv1), tb(cfg->use_tlsv1), tb(cfg->use_tlsv1) ); - if ((cfg->use_imaps || cfg->use_sslv3 || cfg->use_tlsv1) && cfg->cert_file) - fprintf( fp, "CertificateFile %s\n", quotify( cfg->cert_file ) ); - fputc( '\n', fp ); -} - -static void -write_imap_store( FILE *fp, config_t *cfg ) -{ - if (cfg->stores > 1) - nfasprintf( (char **)&cfg->store_name, "%s-%d", cfg->old_server_name, cfg->stores ); - else - cfg->store_name = cfg->old_server_name; - fprintf( fp, "IMAPStore %s\nAccount %s\n", - cfg->store_name, cfg->server_name ); - if (*folder) - fprintf( fp, "Path %s\n", quotify( folder ) ); - else - fprintf( fp, "UseNamespace %s\n", tb(cfg->use_namespace) ); - if (inbox) - fprintf( fp, "MapInbox %s\n", quotify( inbox ) ); - if (cfg->copy_deleted_to) - fprintf( fp, "Trash %s\n", quotify( cfg->copy_deleted_to ) ); - fputc( '\n', fp ); -} - -static void -write_channel_parm( FILE *fp, config_t *cfg ) -{ - if (cfg->max_size) - fprintf( fp, "MaxSize %d\n", cfg->max_size ); - if (cfg->max_messages) - fprintf( fp, "MaxMessages %d\n", cfg->max_messages ); - if (cfg->delete && !global.delete && !delete) - fputs( "Sync All\n", fp ); - if (cfg->expunge && !global.expunge && !expunge) - fputs( "Expunge Both\n", fp ); - fputc( '\n', fp ); -} - -static int -mstrcmp( const char *s1, const char *s2 ) -{ - if (s1 == s2) - return 0; - if (!s1 || !s2) - return 1; - return strcmp( s1, s2 ); -} - -void -write_config( int fd ) -{ - FILE *fp; - const char *cn, *scn; - char *path, *local_box, *local_store; - config_t *box, *sbox, *pbox; - int pl; - - if (!(fp = fdopen( fd, "w" ))) { - perror( "fdopen" ); - return; - } - - fputs( "SyncState *\n", fp ); - if (!global.delete && !delete) - fputs( "Sync New ReNew Flags\n", fp ); - if (global.expunge || expunge) - fputs( "Expunge Both\n", fp ); - fputc( '\n', fp ); - if (o2o) { - write_imap_server( fp, &global ); - write_imap_store( fp, &global ); - fprintf( fp, "MaildirStore local\nPath %s/\n", quotify( maildir ) ); - if (!inbox) { /* just in case listing actually produces an INBOX ... */ - nfasprintf( (char **)&inbox, "%s/INBOX", maildir ); - fprintf( fp, "Inbox %s\n", quotify( inbox ) ); - } - if (altmap > 0) - fputs( "AltMap yes\n", fp ); - fprintf( fp, "\nChannel o2o\nMaster :%s:\nSlave :local:\nPattern %%\n", global.store_name ); - write_channel_parm( fp, &global ); - } else { - for (box = boxes; box; box = box->next) { - for (pbox = boxes; pbox != box; pbox = pbox->next) { - if (box->tunnel) { - if (mstrcmp( pbox->tunnel, box->tunnel )) - continue; - } else { - if (mstrcmp( pbox->host, box->host ) || - pbox->use_imaps != box->use_imaps || - pbox->port != box->port) - continue; - } - if (mstrcmp( pbox->user, box->user ) || - mstrcmp( pbox->pass, box->pass )) /* nonsense */ - continue; - if ((box->use_imaps || - box->use_sslv3 || box->use_tlsv1) && - mstrcmp( pbox->cert_file, box->cert_file )) /* nonsense */ - continue; - if (pbox->use_imaps != box->use_imaps || - pbox->use_sslv3 != box->use_sslv3 || - pbox->use_tlsv1 != box->use_tlsv1) - continue; - box->server_name = pbox->server_name; - for (sbox = boxes; sbox != box; sbox = sbox->next) { - if (sbox->server_name != box->server_name || - mstrcmp( sbox->copy_deleted_to, box->copy_deleted_to ) || - (!*folder && sbox->use_namespace != box->use_namespace)) - continue; - box->store_name = sbox->store_name; - goto gotall; - } - box->stores = ++pbox->stores; - goto gotsrv; - } - write_imap_server( fp, box ); - box->stores = 1; - gotsrv: - write_imap_store( fp, box ); - gotall: - - path = expand_strdup( box->path ); - if (starts_with( path, -1, Home, HomeLen ) && path[HomeLen] == '/') - nfasprintf( &path, "~%s", path + HomeLen ); - local_store = local_box = strrchr( path, '/' ) + 1; - pl = local_store - path; - /* try to re-use existing store */ - for (pbox = boxes; pbox != box; pbox = pbox->next) - if (pbox->local_store_path && equals( pbox->local_store_path, -1, path, pl )) - goto gotstor; - box->local_store_path = my_strndup( path, pl ); - /* derive a suitable name */ - if (!strcmp( box->local_store_path, "/var/mail/" ) || !strcmp( box->local_store_path, "/var/spool/mail/" )) { - local_store = nfstrdup( "spool" ); - } else if (!strcmp( box->local_store_path, "~/" )) { - local_store = nfstrdup( "home" ); - } else { - local_store = memrchr( box->local_store_path, '/', pl - 1 ); - if (local_store) { - local_store = my_strndup( local_store + 1, pl - 2 - (local_store - box->local_store_path) ); - for (pl = 0; local_store[pl]; pl++) - local_store[pl] = tolower( local_store[pl] ); - } else { - local_store = nfstrdup( "local" ); - } - } - /* avoid name clashes with imap stores */ - for (pbox = boxes; pbox != box; pbox = pbox->next) - if (!strcmp( pbox->store_name, local_store )) { - nfasprintf( &local_store, "local_%s", local_store ); - goto gotsdup; - } - gotsdup: - /* avoid name clashes with other local stores */ - for (pbox = boxes; pbox != box; pbox = pbox->next) - if (pbox->local_store_name && !strcmp( pbox->local_store_name, local_store )) { - nfasprintf( (char **)&box->local_store_name, "%s-%d", local_store, ++pbox->local_stores ); - goto gotdup; - } - box->local_store_name = local_store; - box->local_stores = 1; - gotdup: - fprintf( fp, "MaildirStore %s\nPath %s\n", box->local_store_name, quotify( box->local_store_path ) ); - if (altmap > 0) - fputs( "AltMap yes\n", fp ); - fputc( '\n', fp ); - pbox = box; - gotstor: - - if (box->alias) - cn = box->alias; - else { - cn = strrchr( box->path, '/' ); - if (cn) - cn++; - else - cn = box->path; - } - for (sbox = boxes; sbox != box; sbox = sbox->next) { - if (sbox->alias) - scn = sbox->alias; - else { - scn = strrchr( sbox->path, '/' ); - if (scn) - scn++; - else - scn = sbox->path; - } - if (mstrcmp( cn, scn )) - continue; - nfasprintf( (char **)&box->channel_name, "%s-%d", cn, ++sbox->channels ); - goto gotchan; - } - box->channels = 1; - box->channel_name = cn; - gotchan: - - fprintf( fp, "Channel %s\nMaster :%s:%s\nSlave :%s:%s\n", - box->channel_name, box->store_name, quotify( box->box ), pbox->local_store_name, quotify( local_box ) ); - write_channel_parm( fp, box ); - } - - } - - fclose( fp ); -} - -config_t * -find_box( const char *s ) -{ - config_t *p; - char *t; - - if (starts_with( s, -1, Home, HomeLen ) && s[HomeLen] == '/') - s += HomeLen + 1; - for (p = boxes; p; p = p->next) { - if (!strcmp( s, p->path ) || (p->alias && !strcmp( s, p->alias ))) - return p; - /* check to see if the full pathname was specified on the - * command line. - */ - t = expand_strdup( p->path ); - if (!strcmp( s, t )) { - free( t ); - return p; - } - free( t ); - } - return 0; -} diff --git a/src/compat/convert.c b/src/compat/convert.c @@ -1,265 +0,0 @@ -/* - * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer - * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> - * Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "isync.h" - -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> -#include <sys/stat.h> -#include <time.h> - -#include <db.h> - -static const char *subdirs[] = { "cur", "new", "tmp" }; - -static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; - -static int -parse_info( const char *s ) -{ - unsigned i; - int flags; - - flags = 0; - if (s && *(s + 1) == '2' && *(s + 2) == ',') - for (s += 3, i = 0; i < as(Flags); i++) - if (strchr( s, Flags[i] )) - flags |= (1 << i); - return flags; -} - -typedef struct { - int uid, flags; -} msg_t; - -static int -compare_uids( const void *l, const void *r ) -{ - return ((msg_t *)l)->uid - ((msg_t *)r)->uid; -} - -static DBT key, value; -static struct flock lck; - -void -convert( config_t *box ) -{ - DIR *d; - struct dirent *e; - char *s, *p, *mboxdir; - FILE *fp; - msg_t *msgs; - DB *db; - int i, ret, fd, uidval, maxuid, uid, rmsgs, nmsgs, uv[2]; - unsigned u; - struct stat sb; - char buf[_POSIX_PATH_MAX], diumname[_POSIX_PATH_MAX], - uvname[_POSIX_PATH_MAX], sname[_POSIX_PATH_MAX], - iuvname[_POSIX_PATH_MAX], imuname[_POSIX_PATH_MAX], - ilname[_POSIX_PATH_MAX], iumname[_POSIX_PATH_MAX]; - - mboxdir = expand_strdup( box->path ); - nfsnprintf( iuvname, sizeof(iuvname), "%s/isyncuidvalidity", mboxdir ); - nfsnprintf( diumname, sizeof(iumname), "%s/.isyncuidmap.db", mboxdir ); - nfsnprintf( uvname, sizeof(uvname), "%s/.uidvalidity", mboxdir ); - if (stat( iuvname, &sb )) { - if (!stat( diumname, &sb )) - altmap++; - else if (!stat( uvname, &sb )) - altmap--; - err1: - free( mboxdir ); - return; - } - for (i = 0; i < 3; i++) { - nfsnprintf( buf, sizeof(buf), "%s/%s", mboxdir, subdirs[i] ); - if (stat( buf, &sb )) { - sys_error( "ERROR: cannot access %s", buf ); - fprintf( stderr, - "ERROR: '%s' does not appear to be a valid maildir style mailbox\n", - mboxdir ); - goto err1; - } - } - nfsnprintf( iumname, sizeof(iumname), "%s/isyncuidmap.db", mboxdir ); - nfsnprintf( imuname, sizeof(imuname), "%s/isyncmaxuid", mboxdir ); - nfsnprintf( ilname, sizeof(ilname), "%s/isynclock", mboxdir ); - nfsnprintf( sname, sizeof(sname), "%s/.mbsyncstate", mboxdir ); - - if ((fd = open( ilname, O_WRONLY|O_CREAT, 0600 )) < 0) { - sys_error( "Cannot create %s", ilname ); - goto err1; - } -#if SEEK_SET != 0 - lck.l_whence = SEEK_SET; -#endif -#if F_WRLCK != 0 - lck.l_type = F_WRLCK; -#endif - if (fcntl( fd, F_SETLKW, &lck )) { - sys_error( "Cannot lock %s", ilname ); - err2: - close( fd ); - goto err1; - } - - if (!(fp = fopen( iuvname, "r" ))) { - sys_error( "Cannot open %s", iuvname ); - goto err2; - } - if (fscanf( fp, "%d", &uidval ) != 1) { - sys_error( "Cannot read %s", iuvname ); - err3: - fclose( fp ); - goto err2; - } - fclose( fp ); - if (!(fp = fopen( imuname, "r" ))) { - sys_error( "Cannot open %s", imuname ); - goto err2; - } - if (fscanf( fp, "%d", &maxuid ) != 1) { - sys_error( "Cannot read %s", imuname ); - goto err3; - } - fclose( fp ); - - if (!stat( iumname, &sb )) { - if (db_create( &db, 0, 0 )) { - fputs( "dbcreate failed\n", stderr ); - goto err2; - } - if ((db->open)( db, 0, iumname, 0, DB_HASH, 0, 0 )) { - fputs( "cannot open db\n", stderr ); - db->close( db, 0 ); - goto err2; - } - altmap++; - } else { - db = 0; - altmap--; - } - - msgs = 0; - rmsgs = 0; - nmsgs = 0; - for (i = 0; i < 2; i++) { - nfsnprintf( buf, sizeof(buf), "%s/%s/", mboxdir, subdirs[i] ); - if (!(d = opendir( buf ))) { - sys_error( "Cannot list %s", buf ); - err4: - free( msgs ); - if (db) - db->close( db, 0 ); - goto err2; - } - while ((e = readdir( d ))) { - if (*e->d_name == '.') - continue; - s = strchr( e->d_name, ':' ); - if (db) { - key.data = e->d_name; - key.size = s ? (size_t)(s - e->d_name) : strlen( e->d_name ); - if ((ret = db->get( db, 0, &key, &value, 0 ))) { - if (ret != DB_NOTFOUND) - db->err( db, ret, "Maildir error: db->get()" ); - continue; - } - uid = *(int *)value.data; - } else if ((p = strstr( e->d_name, ",U=" ))) - uid = atoi( p + 3 ); - else - continue; - if (nmsgs == rmsgs) { - rmsgs = rmsgs * 2 + 100; - msgs = nfrealloc( msgs, rmsgs * sizeof(msg_t) ); - } - msgs[nmsgs].uid = uid; - msgs[nmsgs++].flags = parse_info( s ); - } - closedir( d ); - } - - qsort( msgs, nmsgs, sizeof(msg_t), compare_uids ); - - if (!(fp = fopen( sname, "w" ))) { - sys_error( "Cannot create %s", sname ); - goto err4; - } - if (box->max_messages) { - if (!nmsgs) - i = maxuid; - else { - i = nmsgs - box->max_messages; - if (i < 0) - i = 0; - i = msgs[i].uid - 1; - } - } else - i = 0; - fprintf( fp, "%d:%d %d:%d:%d\n", uidval, maxuid, uidval, i, maxuid ); - for (i = 0; i < nmsgs; i++) { - fprintf( fp, "%d %d ", msgs[i].uid, msgs[i].uid ); - for (u = 0; u < as(Flags); u++) - if (msgs[i].flags & (1 << u)) - fputc( Flags[u], fp ); - fputc( '\n', fp ); - } - fclose( fp ); - - if (db) { - key.data = (void *)"UIDVALIDITY"; - key.size = 11; - uv[0] = uidval; - uv[1] = maxuid; - value.data = uv; - value.size = sizeof(uv); - if ((ret = db->put( db, 0, &key, &value, 0 ))) { - db->err( db, ret, "Maildir error: db->put()" ); - goto err4; - } - db->close( db, 0 ); - if (rename( iumname, diumname )) { - sys_error( "Cannot rename %s to %s", iumname, diumname ); - goto err4; - } - } else { - if (!(fp = fopen( uvname, "w" ))) { - sys_error( "Cannot create %s", uvname ); - goto err4; - } - fprintf( fp, "%d\n%d\n", uidval, maxuid ); - fclose( fp ); - } - - unlink( iuvname ); - unlink( imuname ); - - close( fd ); - unlink( ilname ); - - free( msgs ); - free( mboxdir ); - return; -} diff --git a/src/compat/isync.1 b/src/compat/isync.1 @@ -1,328 +0,0 @@ -.ig -\" isync - mbsync wrapper: IMAP4 to Maildir mailbox synchronizer -\" Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> -\" Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net> -\" -\" This program is free software; you can redistribute it and/or modify -\" it under the terms of the GNU General Public License as published by -\" the Free Software Foundation; either version 2 of the License, or -\" (at your option) any later version. -\" -\" This program is distributed in the hope that it will be useful, -\" but WITHOUT ANY WARRANTY; without even the implied warranty of -\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -\" GNU General Public License for more details. -\" -\" You should have received a copy of the GNU General Public License -\" along with this program. If not, see <http://www.gnu.org/licenses/>. -\" -.. -.TH isync 1 "2010 Feb 7" -.. -.SH NAME -isync - synchronize IMAP4 and Maildir mailboxes -.. -.SH SYNOPSIS -\fBisync\fR [\fIoptions\fR ...] {\fImailbox\fR ...|\fI-a\fR|\fI-l\fR} -.. -.SH DESCRIPTION -\fBisync\fR is a command line application which synchronizes local -Maildir mailboxes with remote IMAP4 mailboxes, suitable for use in -IMAP-disconnected mode. Multiple copies of the remote IMAP4 mailboxes can -be maintained, and all flags are synchronized. -.br -\fBisync\fR is only a wrapper binary around \fBmbsync\fR to simplify upgrades. -It will automatically migrate the UID mapping from previous versions of -\fBisync\fR (even before 0.8) to the new format, and transparently call -\fBmbsync\fR. If you were using \fBisync\fR version 0.8 or 0.9.x you might -want to use \fBmdconvert\fR to convert the mailboxes to the more efficient -\fBnative\fR UID storage scheme after migrating them. -.br -\fBisync\fR is deprecated. Please use the \fB-w\fR option to permanently -migrate the configuration and start using \fBmbsync\fR directly. -.. -.SH OPTIONS -.TP -\fB-c\fR, \fB--config\fR \fIfile\fR -Read configuration from \fIfile\fR. -By default, the configuration is read from ~/.isyncrc if it exists. -.TP -\fB-1\fR, \fB--one-to-one\fR -Instead of using the mailbox specifications in ~/.isyncrc, isync will pick up -all mailboxes from the local directory and remote folder and map them 1:1 -onto each other according to their names. -.TP -\fB-I\fR, \fB--inbox\fR \fImailbox\fR -Exception to the 1:1 mapping created by -1: the special IMAP mailbox \fIINBOX\fR -is mapped to the local \fImailbox\fR (relative to the maildir). -.TP -\fB-a\fR, \fB--all\fR -Synchronize all mailboxes (either specified in ~/.isyncrc or determined by the -1:1 mapping). -.TP -\fB-l\fR, \fB--list\fR -Don't synchronize anything, but list all mailboxes and exit. -.TP -\fB-L\fR, \fB--create-local\fR -Automatically create the local Maildir mailbox if it doesn't already -exist. -.TP -\fB-R\fR, \fB--create-remote\fR -Automatically create the remote IMAP mailbox if it doesn't already exist. -.TP -\fB-C\fR, \fB--create\fR -Automatically create any mailboxes if they don't already exist. -This is simply a combination of -L and -R. -.TP -\fB-d\fR, \fB--delete\fR -Causes \fBisync\fR to propagate message deletions. -By default, \fIdead\fR messages are \fBnot\fR deleted. -.TP -\fB-e\fR, \fB--expunge\fR -Causes \fBisync\fR to permanently remove all messages marked for deletion. -By default, \fIdeleted\fR messages are \fBnot\fR expunged. -.TP -\fB-f\fR, \fB--fast\fR -Only fetch new messages existing on the server into the local mailbox. -Message deletions and flag changes will not be propagated. -.TP -\fB-h\fR, \fB--help\fR -Displays a summary of command line options -.TP -\fB-p\fR, \fB--port\fR \fIport\fR -Specifies the port on the IMAP server to connect to (default: 143 for imap, -993 for imaps) -.TP -\fB-q\fR, \fB--quiet\fR -Suppress informational messages. -If specified twice, suppress warning messages as well. -.TP -\fB-r\fR, \fB--remote\fR \fIbox\fR -Specifies the name of the remote IMAP mailbox to synchronize with -(Default: INBOX) -.TP -\fB-s\fR, \fB--host\fR [\fBimaps:\fR]\fIhost\fR -Specifies the hostname of the IMAP server -.TP -\fB-u\fR, \fB--user\fR \fIuser\fR -Specifies the login name to access the IMAP server (default: $USER) -.TP -\fB-P\fR, \fB--pass\fR \fIpassword\fR -Specifies the password to access the IMAP server (prompted for by default) -.TP -\fB-M\fR, \fB--maildir\fR \fIdir\fR -Specifies the location for your local mailboxes. -.TP -\fB-F\fR, \fB--folder\fR \fIfolder\fR/ -Specifies the location for your remote mailboxes. -.TP -\fB-v\fR, \fB--version\fR -Displays \fBisync\fR version information. -.TP -\fB-V\fR, \fB--verbose\fR -Enables \fIverbose\fR mode, which displays the IMAP4 network traffic. -.TP -\fB-D\fR, \fB--debug\fR -Enable printing of \fIdebug\fR messages. -.TP -\fB-w\fR, \fB--write\fR -Don't run \fBmbsync\fR, but instead write a permanent config file for it. -The UID mappings of all configured mailboxes will be migrated. -Note that most command line options that would affect an actual sync operation -will be incorporated into the new config file as well; exceptions are ---fast and --create[-remote|-local]. -The name of the new config file is determined by replacing the last occurrence -of "isync" with "mbsync", or appending ".mbsync" if "isync" was not found. -.TP -\fB-W\fR, \fB--writeto\fR \fIfile\fR -Like \fB-w\fR, but use the specified name for the new config file. -.. -.SH CONFIGURATION -\fBisync\fR by default reads \fI~/.isyncrc\fR to load configuration data. -Each non-empty line of the configuration file that does not start with a -hash mark consists of a command. -The following commands are understood: -.TP -\fBMailbox\fR \fIpath\fR -Defines a local Maildir mailbox. All configuration commands following this -line, up until the next \fIMailbox\fR command, apply to this mailbox only. -.. -.TP -\fBHost\fR [\fBimaps:\fR]\fIname\fR -Defines the DNS name or IP address of the IMAP server. If the hostname is -prefixed with \fBimaps:\fR the connection is assumed to be a SSL connection -to port 993 (though you can change this by placing a \fBPort\fR command -\fBafter\fR the \fBHost\fR command). -Note that modern servers support SSL on the default port 143. -\fBisync\fR will always attempt to use SSL if available. -.. -.TP -\fBPort\fR \fIport\fR -Defines the TCP port number of the IMAP server (Default: 143 for imap, -993 for imaps) -.. -.TP -\fBBox\fR \fImailbox\fR -Defines the name of the remote IMAP mailbox associated with the local -Maildir mailbox (Default: INBOX) -.. -.TP -\fBUser\fR \fIusername\fR -Defines the login name on the IMAP server (Default: current user) -.. -.TP -\fBPass\fR \fIpassword\fR -Defines the password for \fIusername\fR on the IMAP server. -Note that this option is \fBNOT\fR required. -If no password is specified in the configuration file, \fBisync\fR -will prompt you for it. -.. -.TP -\fBAlias\fR \fIstring\fR -Defines an alias for the mailbox which can be used as a shortcut on the -command line. -.. -.TP -\fBCopyDeletedTo\fR \fImailbox\fR -Specifies the remote IMAP mailbox to copy deleted messages to prior to -expunging (Default: none). -.. -.TP -\fBDelete\fR \fIyes\fR|\fIno\fR -Specifies whether message deletions are propagated. (Default: no). -\fBNOTE:\fR The \fI-d\fR command line option overrides this setting when -set to \fIno\fR. -.. -.TP -\fBExpunge\fR \fIyes\fR|\fIno\fR -Specifies whether deleted messages are expunged. (Default: no). -\fBNOTE:\fR The \fI-e\fR command line option overrides this setting when -set to \fIno\fR. -.. -.TP -\fBMailDir\fR \fIdirectory\fR -Specifies the location of your local mailboxes if a relative path is -specified in a \fIMailbox\fR command (Default: \fI~\fR). -\fBNOTE:\fR This directive is allowed only in the \fIglobal\fR -section (see below). -.. -.TP -\fBFolder\fR \fIdirectory\fR/ -Specifies the location of your IMAP mailboxes -specified in \fIBox\fR commands (Default: \fI""\fR). -\fBNOTE:\fR You \fBmust\fR append the hierarchy delimiter (usually -a slash) to this specification. -\fBNOTE 2:\fR This directive is allowed only in the \fIglobal\fR -section (see below). -.. -.TP -\fBMaxMessages\fR \fIcount\fR -Sets the number of messages \fBisync\fR should keep in the local copy of a -mailbox. -This is useful for mailboxes where you keep a complete archive on the server, -but want to mirror only the last messages (for instance, for mailing lists). -The messages that were the first to arrive in the mailbox (independently of the -actual date of the message) will be deleted first. -Messages that are flagged (marked as important) and unread messages will not be -automatically deleted. -If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR. -(Default: 0) -.. -.TP -\fBMaxSize\fR \fIbytes\fR -Messages larger than that many bytes will not be transferred over the wire. -This is useful for weeding out messages with large attachments. -If \fIbytes\fR is 0, the maximum file size is \fBunlimited\fR. -(Default: 0) -.. -.TP -\fBTunnel\fR \fIcommand\fR -Specify a command to run to establish a connection rather than opening a TCP -socket. This allows you to run an IMAP session over an SSH tunnel, for -example. -.TP -\fBUseNamespace\fR \fIyes\fR|\fIno\fR -Selects whether the server's first "personal" NAMESPACE should be prefixed to -mailbox names. Disabling this makes sense for some broken IMAP servers. -This option is meaningless if a \fIFolder\fR was specified. -(Default: \fIyes\fR) -.. -.TP -\fBRequireCRAM\fR \fIyes\fR|\fIno\fR -If set to \fIyes\fR, \fBisync\fR will abort the connection if no CRAM-MD5 -authentication is possible. (Default: \fIno\fR) -.. -.TP -\fBRequireSSL\fR \fIyes\fR|\fIno\fR -\fBisync\fR will abort the connection if a TLS/SSL session cannot be -established with the IMAP server. (Default: \fIyes\fR) -.. -.TP -\fBCertificateFile\fR \fIpath\fR -File containing additional X.509 certificates used to verify server -identities. Directly matched peer certificates are always trusted, -regardless of validity. -.br -Note that the system's default certificate store is always used -and should not be specified here. -.. -.TP -\fBUseSSLv2\fR \fIyes\fR|\fIno\fR -Should \fBisync\fR use SSLv2 for communication with the IMAP server over SSL? -(Default: \fIno\fR) -.. -.TP -\fBUseSSLv3\fR \fIyes\fR|\fIno\fR -Should \fBisync\fR use SSLv3 for communication with the IMAP server over SSL? -(Default: \fIyes\fR if the imaps port is used, otherwise \fIno\fR) -.. -.TP -\fBUseTLSv1\fR \fIyes\fR|\fIno\fR -Should \fBisync\fR use TLSv1.x for communication with the IMAP server over SSL? -(Default: \fIyes\fR) -.. -.TP -\fBOneToOne\fR -\fBisync\fR will ignore any \fIMailbox\fR specifications and instead pick up -all mailboxes from the local \fIMailDir\fR and remote \fIFolder\fR and map -them 1:1 onto each other according to their names. -\fBNOTE:\fR This directive is allowed only in the \fIglobal\fR -section (see below). -.. -.TP -\fBInbox\fR \fImailbox\fR -Exception to the OneToOne mapping: the special IMAP mailbox \fIINBOX\fR -is mapped to the local \fImailbox\fR (relative to the \fIMailDir\fR). -\fBNOTE:\fR This directive is only meaningful in the \fIglobal\fR -section (see below). -.. -.P -Configuration commands that appear prior to the first \fBMailbox\fR -command are considered to be \fIglobal\fR -options which are used as defaults when those specific options are not -specifically set for a defined Mailbox. For example, if you use the same -login name for several IMAP servers, you can put a \fBUser\fR command before -the first \fBMailbox\fR command, and then leave out the \fBUser\fR command -in the sections for each mailbox. -\fBisync\fR will then use the global value by default. -.. -.SH FILES -.TP -.B ~/.isyncrc -Default configuration file -.. -.SH BUGS -The configuration file takes precedence over command line options. -.br -Use -c /dev/null to work around. -.P -See the \fBINHERENT PROBLEMS\fR section in the \fBmbsync\fR man page, too. -.. -.SH SEE ALSO -mbsync(1), mdconvert(1), mutt(1), maildir(5) -.P -Up to date information on \fBisync\fR can be found at http://isync.sf.net/ -.. -.SH AUTHORS -Originally written by Michael R. Elkins, -currently maintained by Oswald Buddenhagen. diff --git a/src/compat/isync.h b/src/compat/isync.h @@ -1,116 +0,0 @@ -/* - * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer - * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> - * Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <autodefs.h> - -#include <sys/types.h> -#include <stdarg.h> - -#define as(ar) (sizeof(ar)/sizeof(ar[0])) - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) -# define ATTR_UNUSED __attribute__((unused)) -# define ATTR_NORETURN __attribute__((noreturn)) -# define ATTR_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) -#else -# define ATTR_UNUSED -# define ATTR_NORETURN -# define ATTR_PRINTFLIKE(fmt,var) -#endif - -#if __GNUC__ >= 7 -# define FALLTHROUGH __attribute__((fallthrough)); -#else -# define FALLTHROUGH -#endif - -typedef struct config { - struct config *next; - - const char *server_name; - const char *old_server_name; - int servers; - int old_servers; - char *host; - int port; - char *user; - char *pass; - char *tunnel; - unsigned int require_cram:1; - unsigned int require_ssl:1; - unsigned int use_imaps:1; - unsigned int use_sslv3:1; - unsigned int use_tlsv1:1; - char *cert_file; - - const char *store_name; - int stores; - const char *local_store_name; - const char *local_store_path; - int local_stores; - char *copy_deleted_to; - unsigned int use_namespace:1; - - const char *channel_name; - int channels; - const char *alias; - const char *box; - const char *path; /* path relative to .maildir, or absolute path */ - int max_size; - unsigned int max_messages; - unsigned int expunge:1; - unsigned int delete:1; -} config_t; - -extern int Quiet, Verbose, Debug; - -extern const char *Home; -extern int HomeLen; - -extern config_t global, *boxes; - -extern const char *maildir, *xmaildir, *folder, *inbox; -extern int o2o, altmap, delete, expunge; - -/* config.c */ -void load_config( const char *, config_t *** ); -void write_config( int ); -char *expand_strdup( const char * ); -config_t *find_box( const char * ); - -/* convert.c */ -void convert( config_t * ); - -/* util.c */ -char *next_arg( char ** ); -void *nfmalloc( size_t sz ); -void *nfrealloc( void *mem, size_t sz ); -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 ); - -#ifndef HAVE_MEMRCHR -void *memrchr( const void *s, int c, size_t n ); -#endif - -int starts_with( const char *str, int strl, const char *cmp, int cmpl ); -int equals( const char *str, int strl, const char *cmp, int cmpl ); diff --git a/src/compat/isyncrc.sample b/src/compat/isyncrc.sample @@ -1,55 +0,0 @@ -# Global configuration section -# Values here are used as defaults for any following Mailbox section that -# doesn't specify it. - -# SSL server certificate file -CertificateFile ~/.isync.certs - -# by default, expunge deleted messages (same as -e on command line) -Expunge yes - -# by default delete messages in the local mailbox which no longer exist -# on the server -Delete yes - -# copy deleted messages to the IMAP "Trash" folder -CopyDeletedTo "Trash" - -# my default username, if different from the local username -User me -#Port 143 -#Box INBOX -# don't download messages larger than 200K bytes -MaxSize 200000 - -### -### work mailbox -### - -Mailbox /home/me/Mail/work -Host work.host.com -Pass xxxxxxxx -# define a shortcut so I can just use "isync work" from the command line -Alias work -# don't auto expunge messages in this box (overridden by -e on command line) -Expunge no - -### -### personal mailbox -### - -Mailbox /home/me/Mail/personal -Host host.play.com -# use a non-default port for this connection -Port 6789 -Alias personal - - -### -### Remote mailbox over a SSH tunnel -### - -Mailbox /home/me/Mail/remote -Host host.remote.com -Tunnel "ssh -q host.remote.com /usr/sbin/imapd" -Alias remote diff --git a/src/compat/main.c b/src/compat/main.c @@ -1,438 +0,0 @@ -/* - * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer - * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> - * Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "isync.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <dirent.h> - -#ifdef HAVE_GETOPT_LONG -# include <getopt.h> -struct option Opts[] = { - {"write", 0, NULL, 'w' }, - {"writeto", 0, NULL, 'W' }, - {"all", 0, NULL, 'a' }, - {"list", 0, NULL, 'l'}, - {"config", 1, NULL, 'c'}, - {"create", 0, NULL, 'C'}, - {"create-local", 0, NULL, 'L'}, - {"create-remote", 0, NULL, 'R'}, - {"delete", 0, NULL, 'd'}, - {"expunge", 0, NULL, 'e'}, - {"fast", 0, NULL, 'f'}, - {"help", 0, NULL, 'h'}, - {"remote", 1, NULL, 'r'}, - {"folder", 1, NULL, 'F'}, - {"maildir", 1, NULL, 'M'}, - {"one-to-one", 0, NULL, '1'}, - {"inbox", 1, NULL, 'I'}, - {"host", 1, NULL, 's'}, - {"port", 1, NULL, 'p'}, - {"debug", 0, NULL, 'D'}, - {"quiet", 0, NULL, 'q'}, - {"user", 1, NULL, 'u'}, - {"pass", 1, NULL, 'P'}, - {"version", 0, NULL, 'v'}, - {"verbose", 0, NULL, 'V'}, - {0, 0, 0, 0} -}; -#endif - -static void ATTR_NORETURN -version( void ) -{ - puts( PACKAGE " " VERSION ); - exit( 0 ); -} - -static void ATTR_NORETURN -usage( int code ) -{ - fputs( -PACKAGE " " VERSION " - mbsync wrapper: IMAP4 to maildir synchronizer\n" -"Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>\n" -"Copyright (C) 2002-2006,2008,2010-2012 Oswald Buddenhagen <ossi@users.sf.net>\n" -"Copyright (C) 2004 Theodore Ts'o <tytso@mit.edu>\n" -"usage:\n" -" " PACKAGE " [ flags ] mailbox [mailbox ...]\n" -" " PACKAGE " [ flags ] -a\n" -" " PACKAGE " [ flags ] -l\n" -" -a, --all synchronize all defined mailboxes\n" -" -l, --list list all defined mailboxes and exit\n" -" -L, --create-local create local maildir mailbox if nonexistent\n" -" -R, --create-remote create remote imap mailbox if nonexistent\n" -" -C, --create create both local and remote mailboxes if nonexistent\n" -" -d, --delete delete local msgs that don't exist on the server\n" -" -e, --expunge expunge deleted messages\n" -" -f, --fast only fetch new messages\n" -" -r, --remote BOX remote mailbox\n" -" -F, --folder DIR remote IMAP folder containing mailboxes\n" -" -M, --maildir DIR local directory containing mailboxes\n" -" -1, --one-to-one map every IMAP <folder>/box to <maildir>/box\n" -" -I, --inbox BOX map IMAP INBOX to <maildir>/BOX (exception to -1)\n" -" -s, --host HOST IMAP server address\n" -" -p, --port PORT server IMAP port\n" -" -u, --user USER IMAP user name\n" -" -P, --pass PASSWORD IMAP password\n" -" -c, --config CONFIG read an alternate config file (default: ~/.isyncrc)\n" -" -D, --debug print debugging messages\n" -" -V, --verbose verbose mode (display network traffic)\n" -" -q, --quiet don't display progress info\n" -" -v, --version display version\n" -" -h, --help display this help message\n\n" -"Note that this is a wrapper binary only; the \"real\" isync is named \"mbsync\".\n" -"Options to permanently transform your old isync configuration:\n" -" -w, --write write permanent mbsync configuration\n" -" -W, --writeto FILE write permanent mbsync configuration to FILE\n", - code ? stderr : stdout ); - exit( code ); -} - -static const char * -strrstr( const char *h, const char *n ) -{ - char *p = strstr( h, n ); - if (!p) - return 0; - do { - h = p; - p = strstr( h + 1, n ); - } while (p); - return h; -} - -static void -add_arg( char ***args, const char *arg ) -{ - int nu = 0; - if (*args) - for (; (*args)[nu]; nu++); - *args = nfrealloc( *args, sizeof(char *) * (nu + 2)); - (*args)[nu] = nfstrdup( arg ); - (*args)[nu + 1] = 0; -} - -#define OP_FAST (1<<2) -#define OP_CREATE_REMOTE (1<<3) -#define OP_CREATE_LOCAL (1<<4) - -int Quiet, Verbose, Debug; -config_t global, *boxes; -const char *maildir, *xmaildir, *folder, *inbox; -int o2o, altmap, delete, expunge; - -const char *Home; -int HomeLen; - -int -main( int argc, char **argv ) -{ - config_t *box, **stor; - char *config = 0, *outconfig = 0, **args; - int i, pl, fd, mod, all, list, ops, writeout; - struct stat st; - char path1[_POSIX_PATH_MAX], path2[_POSIX_PATH_MAX]; - - if (!(Home = getenv("HOME"))) { - fputs( "Fatal: $HOME not set\n", stderr ); - return 1; - } - HomeLen = strlen( Home ); - - /* defaults */ - /* XXX the precedence is borked: - it's defaults < cmdline < file instead of defaults < file < cmdline */ -#ifdef BSD - global.user = getenv( "USER" ); -#else - global.user = getenv( "LOGNAME" ); -#endif - global.port = 143; - global.box = ""; /* implicit INBOX in resulting Master/Slave entries */ - global.use_namespace = 1; - global.require_ssl = 1; - global.use_tlsv1 = 1; - folder = ""; - maildir = "~"; - xmaildir = Home; - -#define FLAGS "wW:alCLRc:defhp:qu:P:r:F:M:1I:s:vVD" - - mod = all = list = ops = writeout = Quiet = Verbose = Debug = 0; -#ifdef HAVE_GETOPT_LONG - while ((i = getopt_long( argc, argv, FLAGS, Opts, NULL )) != -1) -#else - while ((i = getopt( argc, argv, FLAGS )) != -1) -#endif - { - switch (i) { - case 'W': - outconfig = optarg; - FALLTHROUGH - case 'w': - writeout = 1; - break; - case 'l': - list = 1; - FALLTHROUGH - case 'a': - all = 1; - break; - case '1': - o2o = 1; - mod = 1; - break; - case 'C': - ops |= OP_CREATE_REMOTE|OP_CREATE_LOCAL; - break; - case 'L': - ops |= OP_CREATE_LOCAL; - break; - case 'R': - ops |= OP_CREATE_REMOTE; - break; - case 'c': - config = optarg; - break; - case 'd': - delete = 1; - break; - case 'e': - expunge = 1; - break; - case 'f': - ops |= OP_FAST; - break; - case 'p': - global.port = atoi( optarg ); - mod = 1; - break; - case 'r': - global.box = optarg; - mod = 1; - break; - case 'F': - folder = optarg; - mod = 1; - break; - case 'M': - maildir = optarg; - mod = 1; - break; - case 'I': - inbox = optarg; - mod = 1; - break; - case 's': -#ifdef HAVE_LIBSSL - if (!strncasecmp( "imaps:", optarg, 6 )) { - global.use_imaps = 1; - global.port = 993; - global.use_sslv3 = 1; - optarg += 6; - } -#endif - global.host = optarg; - mod = 1; - break; - case 'u': - global.user = optarg; - mod = 1; - break; - case 'P': - global.pass = optarg; - mod = 1; - break; - case 'D': - Debug = 1; - break; - case 'V': - Verbose++; - break; - case 'q': - Quiet++; - break; - case 'v': - version(); - case 'h': - usage( 0 ); - default: - usage( 1 ); - } - } - - if (!writeout) - fputs( "Notice: please run 'isync -w' and start using 'mbsync' directly.\n", stderr ); - - if (config) { - if (*config != '/') { - if (!getcwd( path1, sizeof(path1) )) { - fprintf( stderr, "Can't obtain working directory\n" ); - return 1; - } - pl = strlen( path1 ); - nfsnprintf( path1 + pl, sizeof(path1) - pl, "/%s", config ); - config = path1; - } - } else { - nfsnprintf( path1, sizeof(path1), "%s/.isyncrc", Home ); - config = path1; - } - stor = &boxes; - load_config( config, &stor ); - - if (!all && !o2o) - for (i = optind; argv[i]; i++) - if (!find_box( argv[i] )) { - box = nfmalloc( sizeof(config_t) ); - memcpy( box, &global, sizeof(config_t) ); - box->path = argv[i]; - *stor = box; - stor = &box->next; - mod = 1; - } - - if (writeout) { - all = 1; - if (mod) - fprintf( stderr, - "Warning: command line switches that influence the resulting config file\n" - "have been supplied.\n" ); - } else { - if (!argv[optind] && !all) { - fprintf( stderr, "No mailbox specified. Try isync -h\n" ); - return 1; - } - } - - if (all) { - if (o2o) { - DIR * dir; - struct dirent *de; - - if (!(dir = opendir( xmaildir ))) { - sys_error( "Cannot list '%s'", xmaildir ); - return 1; - } - while ((de = readdir( dir ))) { - if (*de->d_name == '.') - continue; - nfsnprintf( path2, sizeof(path2), "%s/%s/cur", xmaildir, de->d_name ); - if (stat( path2, &st ) || !S_ISDIR( st.st_mode )) - continue; - global.path = de->d_name; - global.box = (inbox && !strcmp( inbox, global.path )) ? - "INBOX" : global.path; - convert( &global ); - } - closedir( dir ); - } else - for (box = boxes; box; box = box->next) - convert( box ); - } else { - for (i = optind; argv[i]; i++) - if (o2o) { - global.path = argv[i]; - global.box = - (inbox && !strcmp( global.path, inbox )) ? - "INBOX" : global.path; - convert( &global ); - } else - convert( find_box( argv[i] ) ); - } - - if (writeout) { - if (!outconfig) { - const char *p = strrchr( config, '/' ); - if (!p) - p = config; - p = strrstr( p, "isync" ); - if (!p) - nfsnprintf( path2, sizeof(path2), "%s.mbsync", config ); - else - nfsnprintf( path2, sizeof(path2), "%.*smb%s", p - config, config, p + 1 ); - outconfig = path2; - } - if ((fd = creat( outconfig, 0666 )) < 0) { - sys_error( "Error: cannot create config file '%s'", outconfig ); - return 1; - } - } else { - strcpy( path2, "/tmp/mbsyncrcXXXXXX" ); - if ((fd = mkstemp( path2 )) < 0) { - sys_error( "Error: cannot create temporary config file" ); - return 1; - } - } - write_config( fd ); - - if (writeout) - return 0; - args = 0; - add_arg( &args, "mbsync" ); - while (--Verbose >= 0) - add_arg( &args, "-V" ); - if (Debug) - add_arg( &args, "-D" ); - for (; Quiet; Quiet--) - add_arg( &args, "-q" ); - add_arg( &args, "-cT" ); - add_arg( &args, path2 ); - if (ops & OP_FAST) - add_arg( &args, "-Ln" ); - if (ops & OP_CREATE_REMOTE) - add_arg( &args, "-Cm" ); - if (ops & OP_CREATE_LOCAL) - add_arg( &args, "-Cs" ); - if (list) - add_arg( &args, "-lC" ); - if (o2o) { - if (all) - add_arg( &args, "o2o" ); - else { - char buf[1024]; - strcpy( buf, "o2o:" ); - strcat( buf, argv[optind] ); - while (argv[++optind]) { - strcat( buf, "," ); - strcat( buf, argv[optind] ); - } - add_arg( &args, buf ); - } - } else { - if (all) - add_arg( &args, "-a" ); - else - for (; argv[optind]; optind++) - add_arg( &args, find_box( argv[optind] )->channel_name ); - } - execvp( args[0], args ); - sys_error( "Cannot execute %s", args[0] ); - return 1; -} diff --git a/src/compat/util.c b/src/compat/util.c @@ -1,208 +0,0 @@ -/* - * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer - * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org> - * Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "isync.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#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 ) -{ - char *ret; - - if (!s || !*s) - return 0; - while (isspace( (unsigned char) **s )) - (*s)++; - if (!**s) { - *s = 0; - return 0; - } - if (**s == '"') { - ++*s; - ret = *s; - *s = strchr( *s, '"' ); - } else { - ret = *s; - while (**s && !isspace( (unsigned char) **s )) - (*s)++; - } - if (*s) { - if (**s) - *(*s)++ = 0; - if (!**s) - *s = 0; - } - return ret; -} - -#ifndef HAVE_VASPRINTF -static int -vasprintf( char **strp, const char *fmt, va_list ap ) -{ - int len; - char tmp[1024]; - - if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 ))) - return -1; - if (len >= (int)sizeof(tmp)) - vsprintf( *strp, fmt, ap ); - else - memcpy( *strp, tmp, len + 1 ); - return len; -} -#endif - -#ifndef HAVE_MEMRCHR -void * -memrchr( const void *s, int c, size_t n ) -{ - u_char *b = (u_char *)s, *e = b + n; - - while (--e >= b) - if (*e == c) - return (void *)e; - return 0; -} -#endif - -#ifndef HAVE_STRNLEN -int -strnlen( const char *str, size_t maxlen ) -{ - size_t len; - - /* It's tempting to use memchr(), but it's allowed to read past the end of the actual string. */ - for (len = 0; len < maxlen && str[len]; len++) {} - return len; -} - -#endif - -int -starts_with( const char *str, int strl, const char *cmp, int cmpl ) -{ - if (strl < 0) - strl = strnlen( str, cmpl + 1 ); - return (strl >= cmpl) && !memcmp( str, cmp, cmpl ); -} - -int -equals( const char *str, int strl, const char *cmp, int cmpl ) -{ - if (strl < 0) - strl = strnlen( str, cmpl + 1 ); - return (strl == cmpl) && !memcmp( str, cmp, cmpl ); -} - -void -oob( void ) -{ - fputs( "Fatal: buffer too small. Please report a bug.\n", stderr ); - abort(); -} - -int -nfsnprintf( char *buf, int blen, const char *fmt, ... ) -{ - int ret; - va_list va; - - va_start( va, fmt ); - if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= (unsigned)blen) - oob(); - va_end( va ); - return ret; -} - -static void ATTR_NORETURN -oom( void ) -{ - fputs( "Fatal: Out of memory\n", stderr ); - abort(); -} - -void * -nfmalloc( size_t sz ) -{ - void *ret; - - if (!(ret = malloc( sz ))) - oom(); - return ret; -} - -void * -nfrealloc( void *mem, size_t sz ) -{ - char *ret; - - if (!(ret = realloc( mem, sz )) && sz) - oom(); - return ret; -} - -char * -nfstrdup( const char *str ) -{ - char *ret; - - if (!(ret = strdup( str ))) - oom(); - return ret; -} - -int -nfvasprintf( char **str, const char *fmt, va_list va ) -{ - int ret = vasprintf( str, fmt, va ); - if (ret < 0) - oom(); - return ret; -} - -int -nfasprintf( char **str, const char *fmt, ... ) -{ - int ret; - va_list va; - - va_start( va, fmt ); - ret = nfvasprintf( str, fmt, va ); - va_end( va ); - return ret; -} diff --git a/src/mbsync.1 b/src/mbsync.1 @@ -739,7 +739,7 @@ Default configuration file Directory containing synchronization state files .. .SH SEE ALSO -mdconvert(1), isync(1), mutt(1), maildir(5) +mdconvert(1), mutt(1), maildir(5) .P Up to date information on \fBmbsync\fR can be found at http://isync.sf.net/ .P