From 57cfc0aac9f8cc5d00fa1155367dfd055da27761 Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Sun, 27 Feb 2011 01:49:00 +0100 Subject: make backend selection at runtime --- Makefile | 40 +++++++++++++++++++--------------------- antispam-plugin.c | 29 +++++++++++++++++++++++++++-- antispam-plugin.h | 40 ++++++++++++++++++++++------------------ antispam-storage-1.0.c | 14 +++++++------- antispam-storage-1.1.c | 16 ++++++++-------- antispam-storage-1.2.c | 16 ++++++++-------- crm114-exec.c | 25 +++++++++++++++++-------- dspam-exec.c | 27 ++++++++++++++++++--------- mailtrain.c | 27 ++++++++++++++++++--------- signature-log.c | 25 +++++++++++++++++-------- spool2dir.c | 27 ++++++++++++++++++--------- 11 files changed, 179 insertions(+), 107 deletions(-) diff --git a/Makefile b/Makefile index b833a3f..f405d3d 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ INSTALLDIR ?= $(moduledir)/imap # Kill CFLAGS from dovecot-config CFLAGS := $(CFLAGSORIG) +backenddir := /usr/lib/dovecot-antispam +CFLAGS += '-DBACKENDDIR="$(backenddir)"' + # includes/flags we need for building a dovecot plugin INCS += -DHAVE_CONFIG_H INCS += -I$(DOVECOT)/ @@ -21,6 +24,7 @@ INCS += -I$(DOVECOT)/src/imap/ # output name LIBRARY_NAME ?= lib90_$(PLUGINNAME)_plugin.so +objs = antispam-storage.o antispam-plugin.o # debug rules ifeq ("$(DEBUG)", "stderr") @@ -37,32 +41,14 @@ ifeq ("$(DEBUG_VERBOSE)", "1") CFLAGS += -DCONFIG_DEBUG_VERBOSE endif -# backend error check -ifeq ("$(BACKEND)", "") -error: verify_config - @echo "Error! no backend configured" - @false -endif - -# per-backend rules -ifeq ("$(BACKEND)", "dspam-exec") -objs += signature.o -endif -ifeq ("$(BACKEND)", "signature-log") -objs += signature.o -endif -ifeq ("$(BACKEND)", "crm114-exec") -objs += signature.o -endif +BACKENDS = dspam-exec.so signature-log.so crm114-exec.so mailtrain.so spool2dir.so # main make rules CFLAGS += -fPIC -shared -Wall -Wextra -DPLUGINNAME=$(PLUGINNAME) CC ?= cc HOSTCC ?= cc -objs += antispam-plugin.o antispam-storage.o $(BACKEND).o - -all: verify_config $(LIBRARY_NAME) +all: verify_config $(LIBRARY_NAME) $(BACKENDS) antispam-storage.o: antispam-storage.c antispam-storage-*.c $(CONFIG) antispam-plugin.h dovecot-version.h $(CC) -c $(CFLAGS) $(INCS) -o $@ $< @@ -71,7 +57,7 @@ antispam-storage.o: antispam-storage.c antispam-storage-*.c $(CONFIG) antispam-p $(CC) -c $(CFLAGS) $(INCS) -o $@ $< $(LIBRARY_NAME): $(objs) - $(CC) $(CFLAGS) $(INCS) $(objs) -o $(LIBRARY_NAME) $(LDFLAGS) + $(CC) $(CFLAGS) $(INCS) $(objs) -o $(LIBRARY_NAME) $(LDFLAGS) -ldl dovecot-version: dovecot-version.c $(CONFIG) $(HOSTCC) $(INCS) -o dovecot-version dovecot-version.c @@ -82,11 +68,23 @@ dovecot-version.h: dovecot-version antispam-version.h: version.sh ./version.sh > antispam-version.h +dspam-exec.so: dspam-exec.o signature.o +signature-log.so: signature-log.o signature.o +crm114-exec.so: crm114-exec.o signature.o +mailtrain.so: mailtrain.o +spool2dir.so: spool2dir.o + +$(BACKENDS): + $(CC) $(CFLAGS) $(INCS) $(LDFLAGS) -shared -o $@ $^ + + clean: rm -f *.so *.o *~ dovecot-version dovecot-version.h antispam-version.h install: all install -o $(USER) -g $(GROUP) -m 0755 $(LIBRARY_NAME) $(DESTDIR)$(INSTALLDIR)/ + mkdir -p $(DESTDIR)$(backenddir) + install -o $(USER) -g $(GROUP) -m 0755 $(BACKENDS) $(DESTDIR)$(backenddir)/ verify_config: @if [ ! -r $(CONFIG) ]; then \ diff --git a/antispam-plugin.c b/antispam-plugin.c index 455668d..8a6fb65 100644 --- a/antispam-plugin.c +++ b/antispam-plugin.c @@ -27,6 +27,7 @@ #include #include +#include /* dovecot headers we need */ #include "lib.h" @@ -73,12 +74,15 @@ static char **trash_folders[] = { NULL, NULL, NULL }; static char **spam_folders[] = { default_spam_folders,NULL, NULL }; static char **unsure_folders[] = { NULL, NULL, NULL }; +void (*antispam_next_hook_mail_storage_created)(struct mail_storage *storage); bool antispam_can_append_to_spam = FALSE; static char **spam_keywords = NULL; bool need_keyword_hook; bool need_folder_hook; +struct backend *backend = NULL; + /* lower-case string, but keep modified UTF7 unchanged */ void lowercase_string(const char *in, char *out) { @@ -323,11 +327,32 @@ void PLUGIN_FUNCTION(init)(void) } } + tmp = get_setting("BACKEND"); + if (tmp) { + void *lib; + if (*tmp != '/') + tmp = t_strconcat(BACKENDDIR, tmp, ".so", NULL); + lib = dlopen(tmp, RTLD_NOW | RTLD_LOCAL); + if (!lib) { + debug("backend failed to load: %s\n", strerror(errno)); + exit(3); + } + backend = dlsym(lib, "antispam_backend"); + if (!backend) { + debug("invalid backend!\n"); + exit(5); + } + } + else { + debug("no backend selected!\n"); + exit(2); + } + /* set spam_folders to empty to only allow keywords */ need_folder_hook = spam_folder_count > 0; need_keyword_hook = !!spam_keywords; - backend_init(global_pool); + backend->init(global_pool); antispam_next_hook_mail_storage_created = hook_mail_storage_created; hook_mail_storage_created = antispam_mail_storage_created; @@ -336,7 +361,7 @@ void PLUGIN_FUNCTION(init)(void) void PLUGIN_FUNCTION(deinit)(void) { hook_mail_storage_created = antispam_next_hook_mail_storage_created; - backend_exit(); + backend->exit(); mempool_unref(&global_pool); } diff --git a/antispam-plugin.h b/antispam-plugin.h index fd8783a..4b95f63 100644 --- a/antispam-plugin.h +++ b/antispam-plugin.h @@ -29,22 +29,26 @@ enum classification { CLASS_SPAM, }; -void backend_init(pool_t pool); -void backend_exit(void); -/* - * Handle mail; parameters are - * - t: transaction context - * - ast: transaction context from backend_start() - * - mail: the message - * - wanted: the wanted classification determined by the user - */ -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification wanted); -struct antispam_transaction_context *backend_start(struct mailbox *box); -void backend_rollback(struct antispam_transaction_context *ast); -int backend_commit(struct mailbox_transaction_context *ctx, - struct antispam_transaction_context *ast); +struct backend { + void (*init)(pool_t pool); + void (*exit)(void); + /* + * Handle mail; parameters are + * - t: transaction context + * - ast: transaction context from backend_start() + * - mail: the message + * - wanted: the wanted classification determined by the user + */ + int (*handle_mail)(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification wanted); + struct antispam_transaction_context *(*start)(struct mailbox *box); + void (*rollback)(struct antispam_transaction_context *ast); + int (*commit)(struct mailbox_transaction_context *ctx, + struct antispam_transaction_context *ast); +}; + +extern struct backend *backend; #ifdef CONFIG_DEBUG void debug(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); @@ -70,12 +74,12 @@ static inline void debug_verbose(const char *fmt __attribute__((unused)), ...) #endif void antispam_mail_storage_created(struct mail_storage *storage); -void (*antispam_next_hook_mail_storage_created)(struct mail_storage *storage); +extern void (*antispam_next_hook_mail_storage_created)(struct mail_storage *storage); bool mailbox_is_spam(struct mailbox *box); bool mailbox_is_trash(struct mailbox *box); bool mailbox_is_unsure(struct mailbox *box); const char *get_setting(const char *name); -bool antispam_can_append_to_spam; +extern bool antispam_can_append_to_spam; bool keyword_is_spam(const char *keyword); extern bool need_keyword_hook; diff --git a/antispam-storage-1.0.c b/antispam-storage-1.0.c index 1651281..3112a22 100644 --- a/antispam-storage-1.0.c +++ b/antispam-storage-1.0.c @@ -119,8 +119,8 @@ antispam_copy(struct mailbox_transaction_context *t, struct mail *mail, if (asbox->save_hack || asbox->movetype == MMT_UNINTERESTING) ret = 0; else - ret = backend_handle_mail(t, ast, copy_dest_mail, - move_to_class(asbox->movetype)); + ret = backend->handle_mail(t, ast, copy_dest_mail, + move_to_class(asbox->movetype)); /* * Both save_hack and movetype are only valid within a copy operation, @@ -231,8 +231,8 @@ static int antispam_save_finish(struct mail_save_context *ctx, } /* fall through */ default: - ret = backend_handle_mail(ctx->transaction, ast, save_dest_mail, - move_to_class(asbox->movetype)); + ret = backend->handle_mail(ctx->transaction, ast, save_dest_mail, + move_to_class(asbox->movetype)); } if (save_dest_mail != dest_mail) @@ -245,7 +245,7 @@ antispam_transaction_begin(struct mailbox *box) { struct antispam_transaction_context *ast; - ast = backend_start(box); + ast = backend->start(box); i_assert(ast != NULL); return ast; @@ -256,7 +256,7 @@ antispam_transaction_rollback(struct antispam_transaction_context **_ast) { struct antispam_transaction_context *ast = *_ast; - backend_rollback(ast); + backend->rollback(ast); *_ast = NULL; } @@ -267,7 +267,7 @@ antispam_transaction_commit(struct mailbox_transaction_context *ctx, struct antispam_transaction_context *ast = *_ast; int ret; - ret = backend_commit(ctx, ast); + ret = backend->commit(ctx, ast); *_ast = NULL; return ret; } diff --git a/antispam-storage-1.1.c b/antispam-storage-1.1.c index 80c80e3..e21ac82 100644 --- a/antispam-storage-1.1.c +++ b/antispam-storage-1.1.c @@ -127,8 +127,8 @@ antispam_copy(struct mailbox_transaction_context *t, struct mail *mail, if (asbox->save_hack || asbox->movetype == MMT_UNINTERESTING) ret = 0; else - ret = backend_handle_mail(t, ast->backendctx, dest_mail, - move_to_class(asbox->movetype)); + ret = backend->handle_mail(t, ast->backendctx, dest_mail, + move_to_class(asbox->movetype)); /* * Both save_hack and movetype are only valid within a copy operation, @@ -247,9 +247,9 @@ static int antispam_save_finish(struct mail_save_context *ctx) } /* fall through */ default: - ret = backend_handle_mail(ctx->transaction, ast->backendctx, - dest_mail, - move_to_class(asbox->movetype)); + ret = backend->handle_mail(ctx->transaction, ast->backendctx, + dest_mail, + move_to_class(asbox->movetype)); } return ret; @@ -260,7 +260,7 @@ antispam_transaction_begin(struct mailbox *box) { struct antispam_transaction_context *ast; - ast = backend_start(box); + ast = backend->start(box); i_assert(ast != NULL); return ast; @@ -271,7 +271,7 @@ antispam_transaction_rollback(struct antispam_transaction_context **_ast) { struct antispam_transaction_context *ast = *_ast; - backend_rollback(ast); + backend->rollback(ast); *_ast = NULL; } @@ -282,7 +282,7 @@ antispam_transaction_commit(struct mailbox_transaction_context *ctx, struct antispam_transaction_context *ast = *_ast; int ret; - ret = backend_commit(ctx, ast); + ret = backend->commit(ctx, ast); *_ast = NULL; return ret; } diff --git a/antispam-storage-1.2.c b/antispam-storage-1.2.c index 54b8f7b..2c11ce7 100644 --- a/antispam-storage-1.2.c +++ b/antispam-storage-1.2.c @@ -126,8 +126,8 @@ antispam_copy(struct mail_save_context *ctx, struct mail *mail) if (asbox->save_hack || asbox->movetype == MMT_UNINTERESTING) ret = 0; else - ret = backend_handle_mail(t, ast->backendctx, ctx->dest_mail, - move_to_class(asbox->movetype)); + ret = backend->handle_mail(t, ast->backendctx, ctx->dest_mail, + move_to_class(asbox->movetype)); /* * Both save_hack and movetype are only valid within a copy operation, @@ -237,9 +237,9 @@ static int antispam_save_finish(struct mail_save_context *ctx) } /* fall through */ default: - ret = backend_handle_mail(ctx->transaction, ast->backendctx, - dest_mail, - move_to_class(asbox->movetype)); + ret = backend->handle_mail(ctx->transaction, ast->backendctx, + dest_mail, + move_to_class(asbox->movetype)); } return ret; @@ -250,7 +250,7 @@ antispam_transaction_begin(struct mailbox *box) { struct antispam_transaction_context *ast; - ast = backend_start(box); + ast = backend->start(box); i_assert(ast != NULL); return ast; @@ -261,7 +261,7 @@ antispam_transaction_rollback(struct antispam_transaction_context **_ast) { struct antispam_transaction_context *ast = *_ast; - backend_rollback(ast); + backend->rollback(ast); *_ast = NULL; } @@ -272,7 +272,7 @@ antispam_transaction_commit(struct mailbox_transaction_context *ctx, struct antispam_transaction_context *ast = *_ast; int ret; - ret = backend_commit(ctx, ast); + ret = backend->commit(ctx, ast); *_ast = NULL; return ret; } diff --git a/crm114-exec.c b/crm114-exec.c index 7727409..f4245dd 100644 --- a/crm114-exec.c +++ b/crm114-exec.c @@ -129,7 +129,7 @@ struct antispam_transaction_context { struct siglist *siglist; }; -struct antispam_transaction_context * +static struct antispam_transaction_context * backend_start(struct mailbox *box __attr_unused__) { struct antispam_transaction_context *ast; @@ -139,13 +139,13 @@ backend_start(struct mailbox *box __attr_unused__) return ast; } -void backend_rollback(struct antispam_transaction_context *ast) +static void backend_rollback(struct antispam_transaction_context *ast) { signature_list_free(&ast->siglist); i_free(ast); } -int backend_commit(struct mailbox_transaction_context *ctx, +static int backend_commit(struct mailbox_transaction_context *ctx, struct antispam_transaction_context *ast) { struct siglist *item = ast->siglist; @@ -167,14 +167,14 @@ int backend_commit(struct mailbox_transaction_context *ctx, return ret; } -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification want) +static int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification want) { return signature_extract_to_list(t, mail, &ast->siglist, want); } -void backend_init(pool_t pool) +static void backend_init(pool_t pool) { const char *tmp; int i; @@ -198,6 +198,15 @@ void backend_init(pool_t pool) signature_init(); } -void backend_exit(void) +static void backend_exit(void) { } + +struct backend antispam_backend = { + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, +}; diff --git a/dspam-exec.c b/dspam-exec.c index ecfb9f1..ed706d7 100644 --- a/dspam-exec.c +++ b/dspam-exec.c @@ -163,7 +163,7 @@ struct antispam_transaction_context { struct siglist *siglist; }; -struct antispam_transaction_context * +static struct antispam_transaction_context * backend_start(struct mailbox *box __attr_unused__) { struct antispam_transaction_context *ast; @@ -173,14 +173,14 @@ backend_start(struct mailbox *box __attr_unused__) return ast; } -void backend_rollback(struct antispam_transaction_context *ast) +static void backend_rollback(struct antispam_transaction_context *ast) { signature_list_free(&ast->siglist); i_free(ast); } -int backend_commit(struct mailbox_transaction_context *ctx, - struct antispam_transaction_context *ast) +static int backend_commit(struct mailbox_transaction_context *ctx, + struct antispam_transaction_context *ast) { struct siglist *item = ast->siglist; int ret = 0; @@ -201,9 +201,9 @@ int backend_commit(struct mailbox_transaction_context *ctx, return ret; } -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification want) +static int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification want) { const char *const *result = NULL; int i; @@ -224,7 +224,7 @@ int backend_handle_mail(struct mailbox_transaction_context *t, return signature_extract_to_list(t, mail, &ast->siglist, want); } -void backend_init(pool_t pool) +static void backend_init(pool_t pool) { const char *tmp; int i; @@ -263,6 +263,15 @@ void backend_init(pool_t pool) signature_init(); } -void backend_exit(void) +static void backend_exit(void) { } + +struct backend antispam_backend = { + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, +}; diff --git a/mailtrain.c b/mailtrain.c index 5529f03..276eb4a 100644 --- a/mailtrain.c +++ b/mailtrain.c @@ -101,7 +101,7 @@ struct antispam_transaction_context { int tmplen; }; -struct antispam_transaction_context * +static struct antispam_transaction_context * backend_start(struct mailbox *box __attr_unused__) { struct antispam_transaction_context *ast; @@ -178,7 +178,7 @@ static void clear_tmpdir(struct antispam_transaction_context *ast) t_pop(); } -void backend_rollback(struct antispam_transaction_context *ast) +static void backend_rollback(struct antispam_transaction_context *ast) { if (ast->tmpdir) { /* clear it! */ @@ -189,8 +189,8 @@ void backend_rollback(struct antispam_transaction_context *ast) i_free(ast); } -int backend_commit(struct mailbox_transaction_context *ctx, - struct antispam_transaction_context *ast) +static int backend_commit(struct mailbox_transaction_context *ctx, + struct antispam_transaction_context *ast) { int ret; @@ -209,9 +209,9 @@ int backend_commit(struct mailbox_transaction_context *ctx, return ret; } -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification wanted) +static int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification wanted) { struct istream *mailstream; struct ostream *outstream; @@ -310,7 +310,7 @@ int backend_handle_mail(struct mailbox_transaction_context *t, return ret; } -void backend_init(pool_t pool __attr_unused__) +static void backend_init(pool_t pool __attr_unused__) { const char *tmp; int i; @@ -349,6 +349,15 @@ void backend_init(pool_t pool __attr_unused__) debug("mail backend tmpdir %s\n", tmpdir); } -void backend_exit(void) +static void backend_exit(void) { } + +struct backend antispam_backend = { + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, +}; diff --git a/signature-log.c b/signature-log.c index 85617f1..1cfc956 100644 --- a/signature-log.c +++ b/signature-log.c @@ -44,7 +44,7 @@ struct antispam_transaction_context { struct dict_transaction_context *dict_ctx; }; -struct antispam_transaction_context * +static struct antispam_transaction_context * backend_start(struct mailbox *box __attr_unused__) { struct antispam_transaction_context *ast; @@ -59,7 +59,7 @@ backend_start(struct mailbox *box __attr_unused__) return ast; } -void backend_rollback(struct antispam_transaction_context *ast) +static void backend_rollback(struct antispam_transaction_context *ast) { if (ast->dict) { // dict_transaction_rollback(ast->dict_ctx); @@ -69,7 +69,7 @@ void backend_rollback(struct antispam_transaction_context *ast) i_free(ast); } -int backend_commit(struct mailbox_transaction_context *ctx __attr_unused__, +static int backend_commit(struct mailbox_transaction_context *ctx __attr_unused__, struct antispam_transaction_context *ast) { int ret = 0; @@ -84,9 +84,9 @@ int backend_commit(struct mailbox_transaction_context *ctx __attr_unused__, return ret; } -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification wanted) +static int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification wanted) { const char *signature; int ret; @@ -137,7 +137,7 @@ int backend_handle_mail(struct mailbox_transaction_context *t, return ret; } -void backend_init(pool_t pool __attr_unused__) +static void backend_init(pool_t pool __attr_unused__) { const char *tmp; @@ -156,6 +156,15 @@ void backend_init(pool_t pool __attr_unused__) signature_init(); } -void backend_exit(void) +static void backend_exit(void) { } + +struct backend antispam_backend = { + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, +}; diff --git a/spool2dir.c b/spool2dir.c index aa53e71..2c4b547 100644 --- a/spool2dir.c +++ b/spool2dir.c @@ -112,22 +112,22 @@ struct antispam_transaction_context { }; -void backend_rollback(struct antispam_transaction_context *ast) +static void backend_rollback(struct antispam_transaction_context *ast) { i_free(ast); } -int backend_commit(struct mailbox_transaction_context *ctx __attr_unused__, - struct antispam_transaction_context *ast) +static int backend_commit(struct mailbox_transaction_context *ctx __attr_unused__, + struct antispam_transaction_context *ast) { i_free(ast); return 0; } -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification wanted) +static int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification wanted) { struct istream *mailstream; struct ostream *outstream; @@ -232,7 +232,7 @@ int backend_handle_mail(struct mailbox_transaction_context *t, return ret; } -void backend_init(pool_t pool __attr_unused__) +static void backend_init(pool_t pool __attr_unused__) { if((spamspool = get_setting("SPOOL2DIR_SPAM"))) debug("spool2dir spamspool %s\n", spamspool); @@ -241,7 +241,7 @@ void backend_init(pool_t pool __attr_unused__) debug("spool2dir hamspool %s\n", hamspool); } -struct antispam_transaction_context * +static struct antispam_transaction_context * backend_start(struct mailbox *box __attr_unused__) { struct antispam_transaction_context *ast; @@ -254,6 +254,15 @@ struct antispam_transaction_context * } -void backend_exit(void) +static void backend_exit(void) { } + +struct backend antispam_backend = { + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, +}; -- cgit v1.2.3