delete the compat wrapper
it was deprecated in 1.2. until 1.4 gets released, enough time will have passed for sure.
This commit is contained in:
parent
094bc883e8
commit
cbac8aa75c
4
NEWS
4
NEWS
|
@ -1,3 +1,7 @@
|
||||||
|
[1.4.0]
|
||||||
|
|
||||||
|
The 'isync' compatibility wrapper was removed.
|
||||||
|
|
||||||
[1.3.0]
|
[1.3.0]
|
||||||
|
|
||||||
Network timeout handling has been added.
|
Network timeout handling has been added.
|
||||||
|
|
3
README
3
README
|
@ -23,8 +23,7 @@ Mailboxes can be safely modified while ``mbsync'' operates.
|
||||||
Multiple replicas of each mailbox can be maintained.
|
Multiple replicas of each mailbox can be maintained.
|
||||||
|
|
||||||
isync is the project name, while mbsync is the current executable name; this
|
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
|
change was necessary because of massive changes in the user interface.
|
||||||
isync executable still exists; it is a compatibility wrapper around mbsync.
|
|
||||||
|
|
||||||
* Features
|
* Features
|
||||||
|
|
||||||
|
|
|
@ -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_compat, test "x$ob_cv_enable_compat" != xno -a "x$ac_cv_berkdb4" = xyes)
|
||||||
AM_CONDITIONAL(with_mdconvert, test "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_OUTPUT
|
||||||
|
|
||||||
AC_MSG_RESULT()
|
AC_MSG_RESULT()
|
||||||
|
|
13
debian/README.Debian
vendored
13
debian/README.Debian
vendored
|
@ -3,10 +3,11 @@ A note from isync's web site:
|
||||||
isync can be integrated into Mutt fairly easily with a few hooks:
|
isync can be integrated into Mutt fairly easily with a few hooks:
|
||||||
|
|
||||||
folder-hook ~A bind index $ <sync-mailbox>
|
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
|
where the_channel is the Channel used to sync this mailbox, and maildir is the
|
||||||
so long as you are not modifying the IMAP mailbox outside of Mutt. However, if
|
name of the local mailbox itself. This works well so long as you are not
|
||||||
you are using another mail program simultaneously Mutt will have the wrong idea
|
modifying the IMAP mailbox outside of Mutt. However, if you are using another
|
||||||
of the local mailbox flags and messages will start disappearing from its index
|
mail program simultaneously, Mutt will have the wrong idea of the local mailbox
|
||||||
display (don't worry, they are still on disk).
|
flags and messages will start disappearing from its index display (don't worry,
|
||||||
|
they are still on disk).
|
||||||
|
|
5
debian/control
vendored
5
debian/control
vendored
|
@ -26,11 +26,6 @@ Description: IMAP and MailDir mailbox synchronizer
|
||||||
deletions and flag changes can be propagated both ways. isync is suitable
|
deletions and flag changes can be propagated both ways. isync is suitable
|
||||||
for use in IMAP-disconnected mode.
|
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:
|
Features:
|
||||||
* Fine-grained selection of synchronization operations to perform
|
* Fine-grained selection of synchronization operations to perform
|
||||||
* Synchronizes single mailboxes or entire mailbox collections
|
* Synchronizes single mailboxes or entire mailbox collections
|
||||||
|
|
|
@ -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_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)
|
mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS)
|
||||||
noinst_HEADERS = common.h config.h driver.h sync.h socket.h
|
noinst_HEADERS = common.h config.h driver.h sync.h socket.h
|
||||||
|
|
1
src/compat/.gitignore
vendored
1
src/compat/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/isync
|
|
|
@ -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)
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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.
|
|
|
@ -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 );
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -739,7 +739,7 @@ Default configuration file
|
||||||
Directory containing synchronization state files
|
Directory containing synchronization state files
|
||||||
..
|
..
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
mdconvert(1), isync(1), mutt(1), maildir(5)
|
mdconvert(1), mutt(1), maildir(5)
|
||||||
.P
|
.P
|
||||||
Up to date information on \fBmbsync\fR can be found at http://isync.sf.net/
|
Up to date information on \fBmbsync\fR can be found at http://isync.sf.net/
|
||||||
.P
|
.P
|
||||||
|
|
Loading…
Reference in New Issue
Block a user