isync/src/isync.h

448 lines
14 KiB
C
Raw Normal View History

/*
* mbsync - mailbox synchronizer
* Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
2006-03-20 20:16:22 +00:00
* Copyright (C) 2002-2006 Oswald Buddenhagen <ossi@users.sf.net>
2000-12-20 21:41:21 +00:00
*
* 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, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* As a special exception, mbsync may be linked with the OpenSSL library,
* despite that library's more restrictive license.
2000-12-20 21:41:21 +00:00
*/
#define _GNU_SOURCE
#include <config.h>
#include <sys/types.h>
2004-09-20 11:28:33 +00:00
#include <stdarg.h>
#include <stdio.h>
#define as(ar) (sizeof(ar)/sizeof(ar[0]))
#define __stringify(x) #x
#define stringify(x) __stringify(x)
#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)
2000-12-21 06:27:05 +00:00
#endif
2000-12-20 21:41:21 +00:00
#ifdef __GNUC__
# define INLINE __inline__
#else
# define INLINE
#endif
#define EXE "mbsync"
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
typedef struct x509_store_st X509_STORE;
typedef struct server_conf {
char *tunnel;
char *host;
int port;
#ifdef HAVE_LIBSSL
char *cert_file;
unsigned use_imaps:1;
unsigned use_sslv2:1;
unsigned use_sslv3:1;
unsigned use_tlsv1:1;
/* these are actually variables and are leaked at the end */
SSL_CTX *SSLContext;
X509_STORE *cert_store;
#endif
} server_conf_t;
typedef struct {
int fd;
#ifdef HAVE_LIBSSL
SSL *ssl;
#endif
void (*bad_callback)( void *aux ); /* async fail while sending or listening */
void *callback_aux;
int offset; /* start of filled bytes in buffer */
int bytes; /* number of filled bytes in buffer */
int scanoff; /* offset to continue scanning for newline at, relative to 'offset' */
char buf[1024];
} conn_t;
typedef struct {
const char *file;
FILE *fp;
char *buf;
int bufl;
int line;
char *cmd, *val, *rest;
} conffile_t;
#define OP_NEW (1<<0)
#define OP_RENEW (1<<1)
#define OP_DELETE (1<<2)
#define OP_FLAGS (1<<3)
#define OP_MASK_TYPE (OP_NEW|OP_RENEW|OP_DELETE|OP_FLAGS) /* asserted in the target ops */
#define OP_EXPUNGE (1<<4)
#define OP_CREATE (1<<5)
#define XOP_PUSH (1<<6)
#define XOP_PULL (1<<7)
#define XOP_MASK_DIR (XOP_PUSH|XOP_PULL)
#define XOP_HAVE_TYPE (1<<8)
#define XOP_HAVE_EXPUNGE (1<<9)
#define XOP_HAVE_CREATE (1<<10)
typedef struct driver driver_t;
typedef struct store_conf {
struct store_conf *next;
char *name;
driver_t *driver;
const char *path; /* should this be here? its interpretation is driver-specific */
const char *map_inbox;
const char *trash;
unsigned max_size; /* off_t is overkill */
unsigned trash_remote_new:1, trash_only_new:1;
} store_conf_t;
typedef struct string_list {
struct string_list *next;
char string[1];
} string_list_t;
#define M 0 /* master */
#define S 1 /* slave */
typedef struct channel_conf {
struct channel_conf *next;
const char *name;
store_conf_t *stores[2];
const char *boxes[2];
char *sync_state;
string_list_t *patterns;
int ops[2];
unsigned max_messages; /* for slave only */
} channel_conf_t;
typedef struct group_conf {
struct group_conf *next;
const char *name;
string_list_t *channels;
} group_conf_t;
/* For message->flags */
/* Keep the mailbox driver flag definitions in sync! */
/* The order is according to alphabetical maildir flag sort */
#define F_DRAFT (1<<0) /* Draft */
#define F_FLAGGED (1<<1) /* Flagged */
#define F_ANSWERED (1<<2) /* Replied */
#define F_SEEN (1<<3) /* Seen */
#define F_DELETED (1<<4) /* Trashed */
#define NUM_FLAGS 5
/* For message->status */
#define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */
#define M_DEAD (1<<1) /* expunged */
#define M_FLAGS (1<<2) /* flags fetched */
typedef struct message {
struct message *next;
struct sync_rec *srec;
/* string_list_t *keywords; */
size_t size; /* zero implies "not fetched" */
int uid;
unsigned char flags, status;
} message_t;
/* For opts, both in store and driver_t->select() */
#define OPEN_OLD (1<<0)
#define OPEN_NEW (1<<1)
#define OPEN_FLAGS (1<<2)
#define OPEN_SIZE (1<<3)
#define OPEN_EXPUNGE (1<<5)
#define OPEN_SETFLAGS (1<<6)
#define OPEN_APPEND (1<<7)
#define OPEN_FIND (1<<8)
typedef struct store {
struct store *next;
store_conf_t *conf; /* foreign */
string_list_t *boxes; /* _list results - own */
unsigned listed:1; /* was _list already run? */
void (*bad_callback)( void *aux );
void *bad_callback_aux;
/* currently open mailbox */
const char *name; /* foreign! maybe preset? */
char *path; /* own */
message_t *msgs; /* own */
int uidvalidity;
unsigned opts; /* maybe preset? */
/* note that the following do _not_ reflect stats from msgs, but mailbox totals */
int count; /* # of messages */
int recent; /* # of recent messages - don't trust this beyond the initial read */
} store_t;
/* When the callback is invoked (at most once per store), the store is fubar;
* call the driver's cancel_store() to dispose of it. */
static INLINE void
set_bad_callback( store_t *ctx, void (*cb)( void *aux ), void *aux )
{
ctx->bad_callback = cb;
ctx->bad_callback_aux = aux;
}
typedef struct {
char *data;
int len;
unsigned char flags;
} msg_data_t;
#define DRV_OK 0
/* Message went missing, or mailbox is full, etc. */
#define DRV_MSG_BAD 1
/* Something is wrong with the current mailbox - probably it is somehow inaccessible. */
#define DRV_BOX_BAD 2
/* The command has been cancel()ed or cancel_store()d. */
#define DRV_CANCELED 3
/* All memory belongs to the driver's user, unless stated otherwise. */
/*
This flag says that the driver CAN store messages with CRLFs,
not that it must. The lack of it OTOH implies that it CANNOT,
and as CRLF is the canonical format, we convert.
*/
#define DRV_CRLF 1
#define TUIDL 12
struct driver {
int flags;
/* Parse configuration. */
int (*parse_store)( conffile_t *cfg, store_conf_t **storep, int *err );
/* Close remaining server connections. All stores must be disowned first. */
void (*cleanup)( void );
/* Open a store with the given configuration. This may recycle existing
* server connections. Upon failure, a null store is passed to the callback. */
void (*open_store)( store_conf_t *conf,
void (*cb)( store_t *ctx, void *aux ), void *aux );
/* Mark the store as available for recycling. Server connection may be kept alive. */
void (*disown_store)( store_t *ctx );
/* Try to recycle a store with the given configuration. */
store_t *(*own_store)( store_conf_t *conf );
/* Discard the store after a bad_callback. The server connections will be closed.
* Pending commands will have their callbacks synchronously invoked with DRV_CANCELED. */
void (*cancel_store)( store_t *ctx );
/* List the mailboxes in this store. */
void (*list)( store_t *ctx,
void (*cb)( int sts, void *aux ), void *aux );
/* Invoked before select(), this informs the driver which operations (OP_*)
* will be performed on the mailbox. The driver may extend the set by implicitly
* needed or available operations. */
void (*prepare_opts)( store_t *ctx, int opts );
/* Open the mailbox ctx->name. Optionally create missing boxes.
* As a side effect, this should resolve ctx->path if applicable. */
void (*select)( store_t *ctx, int create,
void (*cb)( int sts, void *aux ), void *aux );
/* Load the message attributes needed to perform the requested operations.
* Consider only messages with UIDs between minuid and maxuid (inclusive)
* and those named in the excs array (smaller than minuid).
* The driver takes ownership of the excs array. */
void (*load)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs,
void (*cb)( int sts, void *aux ), void *aux );
/* Fetch the contents and flags of the given message from the current mailbox. */
void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
void (*cb)( int sts, void *aux ), void *aux );
/* Store the given message to either the current mailbox or the trash folder.
* If the new copy's UID can be immediately determined, return it, otherwise -1. */
void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash,
void (*cb)( int sts, int uid, void *aux ), void *aux );
/* Find a message by its temporary UID header to determine its real UID. */
void (*find_msg)( store_t *ctx, const char *tuid,
void (*cb)( int sts, int uid, void *aux ), void *aux );
/* Add/remove the named flags to/from the given message. The message may be either
* a pre-fetched one (in which case the in-memory representation is updated),
* or it may be identifed by UID only. The operation may be delayed until commit()
* is called. */
void (*set_flags)( store_t *ctx, message_t *msg, int uid, int add, int del, /* msg can be null, therefore uid as a fallback */
void (*cb)( int sts, void *aux ), void *aux );
/* Move the given message from the current mailbox to the trash folder.
* This may expunge the original message immediately, but it needn't to. */
void (*trash_msg)( store_t *ctx, message_t *msg, /* This may expunge the original message immediately, but it needn't to */
void (*cb)( int sts, void *aux ), void *aux );
/* Expunge deleted messages from the current mailbox and close it.
* There is no need to explicitly close a mailbox if no expunge is needed. */
void (*close)( store_t *ctx, /* IMAP-style: expunge inclusive */
void (*cb)( int sts, void *aux ), void *aux );
/* Cancel queued commands which are not in flight yet; they will have their
* callbacks invoked with DRV_CANCELED. Afterwards, wait for the completion of
* the in-flight commands. If the store is canceled before this command completes,
* the callback will *not* be invoked. */
void (*cancel)( store_t *ctx,
void (*cb)( void *aux ), void *aux );
/* Commit any pending set_flags() commands. */
void (*commit)( store_t *ctx );
2000-12-20 21:41:21 +00:00
};
/* main.c */
2000-12-20 21:41:21 +00:00
extern int Pid;
extern char Hostname[256];
extern const char *Home;
/* socket.c */
/* call this before doing anything with the socket */
static INLINE void socket_init( conn_t *conn,
void (*bad_callback)( void *aux ),
void *aux )
{
conn->bad_callback = bad_callback;
conn->callback_aux = aux;
conn->fd = -1;
}
int socket_connect( const server_conf_t *conf, conn_t *sock );
int socket_start_tls( const server_conf_t *conf, conn_t *sock );
void socket_close( conn_t *sock );
int socket_fill( conn_t *sock );
int socket_read( conn_t *sock, char *buf, int len ); /* never waits */
char *socket_read_line( conn_t *sock ); /* don't free return value; never waits */
typedef enum { KeepOwn = 0, GiveOwn } ownership_t;
int socket_write( conn_t *sock, char *buf, int len, ownership_t takeOwn );
int socket_pending( conn_t *sock );
void cram( const char *challenge, const char *user, const char *pass,
char **_final, int *_finallen );
/* util.c */
#define DEBUG 1
#define VERBOSE 2
#define XVERBOSE 4
#define QUIET 8
#define VERYQUIET 16
#define KEEPJOURNAL 32
extern int DFlags, Ontty;
void debug( const char *, ... );
void debugn( const char *, ... );
void info( const char *, ... );
void infon( const char *, ... );
void warn( const char *, ... );
void error( const char *, ... );
2000-12-20 21:41:21 +00:00
char *next_arg( char ** );
void add_string_list( string_list_t **list, const char *str );
void free_string_list( string_list_t *list );
void free_generic_messages( message_t * );
void *nfmalloc( size_t sz );
void *nfcalloc( 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 ATTR_NORETURN oob( void );
2000-12-20 21:41:21 +00:00
char *expand_strdup( const char *s );
void sort_ints( int *arr, int len );
void arc4_init( void );
unsigned char arc4_getbyte( void );
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#else
# define POLLIN 1
# define POLLOUT 4
# define POLLERR 8
#endif
void add_fd( int fd, void (*cb)( int events, void *aux ), void *aux );
void conf_fd( int fd, int and_events, int or_events );
void fake_fd( int fd, int events );
void del_fd( int fd );
void main_loop( void );
/* sync.c */
2006-03-21 10:30:45 +00:00
extern const char *str_ms[2], *str_hl[2];
#define SYNC_OK 0 /* assumed to be 0 */
#define SYNC_FAIL 1
#define SYNC_BAD(ms) (2<<(ms))
#define SYNC_NOGOOD 8 /* internal */
#define SYNC_CANCELED 16 /* internal */
/* All passed pointers must stay alive until cb is called. */
void sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
void (*cb)( int sts, void *aux ), void *aux );
/* config.c */
#define N_DRIVERS 2
extern driver_t *drivers[N_DRIVERS];
extern channel_conf_t *channels;
extern group_conf_t *groups;
extern int global_ops[2];
extern char *global_sync_state;
int parse_bool( conffile_t *cfile );
int parse_int( conffile_t *cfile );
int parse_size( conffile_t *cfile );
int getcline( conffile_t *cfile );
int merge_ops( int cops, int ops[] );
int load_config( const char *filename, int pseudo );
void parse_generic_store( store_conf_t *store, conffile_t *cfg, int *err );
2000-12-21 06:27:05 +00:00
/* drv_*.c */
extern driver_t maildir_driver, imap_driver;