diff options
-rw-r--r-- | guimb/collect.c | 30 | ||||
-rw-r--r-- | guimb/guimb.h | 11 | ||||
-rw-r--r-- | guimb/main.c | 68 | ||||
-rw-r--r-- | guimb/scm/sieve-core.scm | 17 | ||||
-rw-r--r-- | guimb/scm/sieve.scm.in | 83 | ||||
-rw-r--r-- | include/mailutils/guile.h | 12 | ||||
-rw-r--r-- | libmu_scm/Makefile.am | 1 | ||||
-rw-r--r-- | libmu_scm/mu_guile.c | 199 | ||||
-rw-r--r-- | libmu_scm/mu_mailbox.c | 32 | ||||
-rw-r--r-- | libmu_scm/mu_message.c | 2 | ||||
-rw-r--r-- | libmu_scm/mu_scm.h | 1 | ||||
-rw-r--r-- | maidag/Makefile.am | 2 | ||||
-rw-r--r-- | maidag/deliver.c | 17 | ||||
-rw-r--r-- | maidag/guile.c | 43 | ||||
-rw-r--r-- | maidag/maidag.c | 265 | ||||
-rw-r--r-- | maidag/maidag.h | 48 | ||||
-rw-r--r-- | maidag/script.c | 212 | ||||
-rw-r--r-- | maidag/sieve.c | 115 |
18 files changed, 759 insertions, 399 deletions
diff --git a/guimb/collect.c b/guimb/collect.c index d4f78f988..8839d98a3 100644 --- a/guimb/collect.c +++ b/guimb/collect.c @@ -1,6 +1,6 @@ /* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999, 2000, 2001, 2002, 2005, - 2007 Free Software Foundation, Inc. + 2007, 2009 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -191,31 +191,3 @@ collect_drop_mailbox () } } -SCM -guimb_catch_body (void *data, mu_mailbox_t unused) -{ - struct guimb_data *gd = data; - if (gd->program_file) - scm_primitive_load (scm_makfrom0str (gd->program_file)); - - if (gd->program_expr) - scm_c_eval_string (gd->program_expr); - - return SCM_BOOL_F; -} - -SCM -guimb_catch_handler (void *unused, SCM tag, SCM throw_args) -{ - collect_drop_mailbox (); - return scm_handle_by_message ("guimb", tag, throw_args); -} - -int -guimb_exit (void *unused1, mu_mailbox_t unused2) -{ - int rc = collect_output (); - collect_drop_mailbox (); - return rc; -} - diff --git a/guimb/guimb.h b/guimb/guimb.h index 95df1417d..166f86cdc 100644 --- a/guimb/guimb.h +++ b/guimb/guimb.h @@ -1,6 +1,6 @@ /* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999, 2000, 2001, 2002, 2005, - 2007 Free Software Foundation, Inc. + 2007, 2009 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -67,12 +67,3 @@ int collect_output (void); void util_error (const char *fmt, ...) MU_PRINTFLIKE(1, 2); int util_tempfile (char **namep); -struct guimb_data -{ - char *program_file; - char *program_expr; -}; - -SCM guimb_catch_body (void *data, mu_mailbox_t unused); -SCM guimb_catch_handler (void *unused, SCM tag, SCM throw_args); -int guimb_exit (void *unused1, mu_mailbox_t unused2); diff --git a/guimb/main.c b/guimb/main.c index 64c548b1a..6a294720c 100644 --- a/guimb/main.c +++ b/guimb/main.c @@ -145,19 +145,21 @@ static const char *guimb_argp_capa[] = { "license", NULL }; - + +const char *main_sym = "mailutils-main"; + int main (int argc, char *argv[]) { + int rc; int c = argc; int index; - mu_guimb_param_t param; - struct guimb_data gd; /* Native Language Support */ MU_APP_INIT_NLS (); - append_arg (""); + /* Register the desired formats. */ + mu_register_all_formats (); mu_argp_init (program_version, NULL); if (mu_app_init (&argp, guimb_argp_capa, NULL, argc, argv, 0, &index, &c)) @@ -169,17 +171,12 @@ main (int argc, char *argv[]) if (!user_name) user_name = who_am_i (); - if (program_file) - g_argv[0] = program_file; - else if (!program_expr) + if (!program_file && !program_expr) { mu_error (_("At least one of -fecs must be used. Try guimb --help for more info.")); - exit (0); + exit (1); } - /* Register the desired formats. */ - mu_register_all_formats (); - if (!argv[index]) { if (default_mailbox) @@ -202,27 +199,42 @@ main (int argc, char *argv[]) collect_append_file ("-"); } - append_arg (NULL); - g_argc--; - /* Finish creating input mailbox */ collect_create_mailbox (); - gd.program_file = program_file; - gd.program_expr = program_expr; + mu_guile_init (debug_guile); + if (program_file) + mu_guile_load (program_file, g_argc, g_argv); + if (program_expr) + mu_guile_eval (program_expr); + + rc = mu_guile_mailbox_apply (mbox, main_sym); + switch (rc) + { + case 0: + collect_output (); + break; + + case MU_ERR_NOENT: + mu_error (_("%s not defined"), main_sym); + break; + + case EINVAL: + mu_error (_("%s is not a procedure object"), main_sym); + break; + + case MU_ERR_FAILURE: + mu_error (_("execution of %s failed"), main_sym); + break; + + default: + mu_error (_("unrecognized error")); + break; + } + + collect_drop_mailbox (); - param.debug_guile = debug_guile; - param.mbox = mbox; - param.user_name = user_name; - param.init = NULL; - param.catch_body = guimb_catch_body; - param.catch_handler = guimb_catch_handler; - param.next = NULL; - param.exit = guimb_exit; - param.data = &gd; - mu_process_mailbox (g_argc, g_argv, ¶m); - /*NOTREACHED*/ - return 0; + return !!rc; } char * diff --git a/guimb/scm/sieve-core.scm b/guimb/scm/sieve-core.scm index 89a0872d6..c75cf3484 100644 --- a/guimb/scm/sieve-core.scm +++ b/guimb/scm/sieve-core.scm @@ -457,8 +457,15 @@ (lambda args #f))) ;;; Sieve-main -(define sieve-mailbox #f) -(define sieve-current-message #f) +(define-public sieve-mailbox #f) +(define-public sieve-current-message #f) + +(define-public (sieve-run-current-message thunk) + (and (catch 'sieve-stop + thunk + (lambda args + #f)) + (sieve-verbose-print "IMPLICIT KEEP"))) (define (sieve-run thunk) (if (not sieve-my-email) @@ -470,11 +477,7 @@ ((> n count) #f) (set! sieve-current-message (mu-mailbox-get-message sieve-mailbox n)) - (and (catch 'sieve-stop - thunk - (lambda args - #f)) - (sieve-verbose-print "IMPLICIT KEEP"))) + (sieve-run-current-message thunk)) (sieve-close-mailboxes))) (define (sieve-command-line) diff --git a/guimb/scm/sieve.scm.in b/guimb/scm/sieve.scm.in index 4a8672f3f..293dcf747 100644 --- a/guimb/scm/sieve.scm.in +++ b/guimb/scm/sieve.scm.in @@ -1,8 +1,9 @@ #! %GUILE_BINDIR%/guile -s -# Emacs, its -*- scheme -*- +# Emacs, it's -*- scheme -*- !# ;;;; GNU Mailutils -- a suite of utilities for electronic mail -;;;; Copyright (C) 1999, 2000, 2001, 2006, 2007 Free Software Foundation, Inc. +;;;; Copyright (C) 1999, 2000, 2001, 2006, 2007, +;;;; 2009 Free Software Foundation, Inc. ;;;; ;;;; GNU Mailutils is free software; you can redistribute it and/or modify ;;;; it under the terms of the GNU General Public License as published by @@ -931,39 +932,53 @@ outfile (lambda () (display "#! ") - (if guimb-header - (display "/home/gray/alpha/bin/guimb -s\n") - (display "/usr/bin/guile -s\n")) - (display (string-append - "# Guile mailbox parser made from " filename)) - (newline) - (display "# by sieve.scm, GNU %PACKAGE% %VERSION%\n!#") - (newline) - - (display - "(if (not (member \"%GUILE_SITE%\" %load-path))\n + (cond + (guimb-header + (display "/home/gray/alpha/bin/guimb -s\n")) + (else + (display "/bin/sh\n\ +# aside from this initial boilerplate, this is actually -*- scheme -*- code\n\ +exec ${GUILE-guile} -l $0 -c '(mailutils-main)'\n"))) + (display (string-append + "# This Guile mailbox parser was made from " filename)) + (newline) + (display "# by sieve.scm, GNU %PACKAGE% %VERSION%\n!#") + (newline) + + (display + "(if (not (member \"%GUILE_SITE%\" %load-path))\n (set! %load-path (cons \"%GUILE_SITE%\" %load-path)))\n") - - (display "(use-modules (mailutils sieve-core))\n") - (display (string-append - "(set! sieve-source \"" filename "\")")) - (newline) - - (for-each - (lambda (file) - (display (string-append - "(load \"" file "\")")) - (newline)) - sieve-load-files) - (newline) - (if request-verbose - (display "(set! sieve-verbose #t)\n")) - (display "(sieve-main ") - - (sieve-code-print-list - (append '(lambda ()) - sieve-code-list)) - (display ")")))) + + (display "(use-modules (mailutils sieve-core))\n") + (display (string-append + "(set! sieve-source \"" filename "\")")) + (newline) + + (for-each + (lambda (file) + (display (string-append + "(load \"" file "\")")) + (newline)) + sieve-load-files) + (newline) + (if request-verbose + (display "(set! sieve-verbose #t)\n")) + (display "(define (sieve-filter-thunk) ") + + (sieve-code-print-list (car sieve-code-list)) + (display ")\n\n") + + (display "(define (mailutils-main . rest)\n") + (display " (sieve-main sieve-filter-thunk))\n\n") + + (display "(define (mailutils-check-message msg)\n\ + (set! sieve-current-message msg)\n\ + (sieve-run-current-message sieve-filter-thunk))\n") + + (display "\n\ +;;;; Local Variables:\n\ +;;;; buffer-read-only: t\n\ +;;;; End:\n")))) ;;;; diff --git a/include/mailutils/guile.h b/include/mailutils/guile.h index ad03dcffe..cdc9c0912 100644 --- a/include/mailutils/guile.h +++ b/include/mailutils/guile.h @@ -69,10 +69,20 @@ extern SCM mu_port_make_from_stream (SCM msg, mu_stream_t stream, long mode); extern void mu_scm_mime_init (void); extern void mu_scm_message_add_owner (SCM MESG, SCM owner); +extern void mu_scm_mutil_init (void); + extern void mu_process_mailbox (int argc, char *argv[], mu_guimb_param_t *param); -extern void mu_scm_mutil_init (void); +extern void mu_guile_init (int debug); +extern int mu_guile_load (char *filename, int argc, char **argv); +extern int mu_guile_eval (const char *string); +extern int mu_guile_mailbox_apply (mu_mailbox_t mbx, char *funcname); +extern int mu_guile_message_apply (mu_message_t msg, char *funcname); +extern int mu_guile_safe_exec (SCM (*handler) (void *data), void *data, + SCM *result); +extern int mu_guile_safe_proc_call (SCM proc, SCM arglist, SCM *presult); + #ifdef __cplusplus } #endif diff --git a/libmu_scm/Makefile.am b/libmu_scm/Makefile.am index 4a4ecb205..282d2621e 100644 --- a/libmu_scm/Makefile.am +++ b/libmu_scm/Makefile.am @@ -26,6 +26,7 @@ EXTRA_LTLIBRARIES=libmu_scm.la C_SRCS=\ mu_address.c\ mu_body.c\ + mu_guile.c\ mu_guimb.c\ mu_mailbox.c\ mu_message.c\ diff --git a/libmu_scm/mu_guile.c b/libmu_scm/mu_guile.c new file mode 100644 index 000000000..f6b6caafc --- /dev/null +++ b/libmu_scm/mu_guile.c @@ -0,0 +1,199 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2009 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA */ + +#include "mu_scm.h" + +static SCM +eval_catch_body (void *list) +{ + return scm_primitive_eval ((SCM)list); +} + +static SCM +eval_catch_handler (void *data, SCM tag, SCM throw_args) +{ + scm_handle_by_message_noexit ("mailutils", tag, throw_args); + longjmp (*(jmp_buf*)data, 1); +} + +struct scheme_exec_data +{ + SCM (*handler) (void *data); + void *data; + SCM result; +}; + +static SCM +scheme_safe_exec_body (void *data) +{ + struct scheme_exec_data *ed = data; + ed->result = ed->handler (ed->data); + return SCM_BOOL_F; +} + +int +mu_guile_safe_exec (SCM (*handler) (void *data), void *data, SCM *result) +{ + jmp_buf jmp_env; + struct scheme_exec_data ed; + + if (setjmp (jmp_env)) + return 1; + ed.handler = handler; + ed.data = data; + scm_internal_lazy_catch (SCM_BOOL_T, + scheme_safe_exec_body, (void*)&ed, + eval_catch_handler, &jmp_env); + if (result) + *result = ed.result; + return 0; +} + + + +SCM +lookup_handler (void *data) +{ + const char *symbol = (const char *)data; + return MU_SCM_SYMBOL_VALUE (symbol); +} + +int +mu_guile_sym_lookup (const char *symbol, SCM *result) +{ + return mu_guile_safe_exec (lookup_handler, (void*) symbol, result); +} + + +int +mu_guile_safe_proc_call (SCM proc, SCM arglist, SCM *presult) +{ + jmp_buf jmp_env; + SCM cell, result; + + if (setjmp (jmp_env)) + return 1; + + cell = scm_cons (proc, arglist); + result = scm_internal_lazy_catch (SCM_BOOL_T, + eval_catch_body, cell, + eval_catch_handler, &jmp_env); + if (presult) + *presult = result; + return 0; +} + + + +void +mu_guile_init (int debug) +{ + scm_init_guile (); + scm_load_goops (); + + if (debug) + { + SCM_DEVAL_P = 1; + SCM_BACKTRACE_P = 1; + SCM_RECORD_POSITIONS_P = 1; + SCM_RESET_DEBUG_MODE; + } + mu_scm_init (); +} + + +struct load_closure +{ + char *filename; + int argc; + char **argv; +}; + +static SCM +load_path_handler (void *data) +{ + struct load_closure *lp = data; + + scm_set_program_arguments (lp->argc, lp->argv, lp->filename); + scm_primitive_load (scm_makfrom0str (lp->filename)); + return SCM_UNDEFINED; +} + +int +mu_guile_load (char *filename, int argc, char **argv) +{ + struct load_closure lc; + lc.filename = filename; + lc.argc = argc; + lc.argv = argv; + return mu_guile_safe_exec (load_path_handler, &lc, NULL); +} + +static SCM +eval_handler (void *data) +{ + const char *string = data; + scm_c_eval_string (string); + return SCM_UNDEFINED; +} + +int +mu_guile_eval (const char *string) +{ + return mu_guile_safe_exec (eval_handler, (void*) string, NULL); +} + + +/* See comment on this function in mu_mailbox.c */ +extern SCM mu_scm_mailbox_create0 (mu_mailbox_t mbox, int noclose); + +int +mu_guile_mailbox_apply (mu_mailbox_t mbx, char *funcname) +{ + SCM proc; + + if (mu_guile_sym_lookup (funcname, &proc)) + return MU_ERR_NOENT; + if (scm_procedure_p (proc) != SCM_BOOL_T) + return EINVAL; + + if (mu_guile_safe_proc_call (proc, + scm_list_1 (mu_scm_mailbox_create0 (mbx, 1)), + NULL)) + return MU_ERR_FAILURE; + + return 0; +} + +int +mu_guile_message_apply (mu_message_t msg, char *funcname) +{ + SCM proc; + + if (mu_guile_sym_lookup (funcname, &proc)) + return MU_ERR_NOENT; + if (scm_procedure_p (proc) != SCM_BOOL_T) + return EINVAL; + + if (mu_guile_safe_proc_call (proc, + scm_list_1 (mu_scm_message_create (SCM_BOOL_F, msg)), + NULL)) + return MU_ERR_FAILURE; + + return 0; +} diff --git a/libmu_scm/mu_mailbox.c b/libmu_scm/mu_mailbox.c index 6fb611ae6..e0a3e4720 100644 --- a/libmu_scm/mu_mailbox.c +++ b/libmu_scm/mu_mailbox.c @@ -25,6 +25,7 @@ long mailbox_tag; struct mu_mailbox { mu_mailbox_t mbox; /* Mailbox */ + int noclose; }; /* SMOB functions: */ @@ -38,8 +39,11 @@ static scm_sizet mu_scm_mailbox_free (SCM mailbox_smob) { struct mu_mailbox *mum = (struct mu_mailbox *) SCM_CDR (mailbox_smob); - mu_mailbox_close (mum->mbox); - mu_mailbox_destroy (&mum->mbox); + if (!mum->noclose) + { + mu_mailbox_close (mum->mbox); + mu_mailbox_destroy (&mum->mbox); + } free (mum); /* NOTE: Currently there is no way for this function to return the amount of memory *actually freed* by mu_mailbox_destroy */ @@ -85,16 +89,38 @@ mu_scm_mailbox_print (SCM mailbox_smob, SCM port, scm_print_state * pstate) /* Internal functions */ +/* There are two C interfaces for creating mailboxes in Scheme. + The first one, mu_scm_mailbox_create0, allows to set `noclose' + bit, which disables closing and releasing the underlying mu_mailbox_t + after the hosting SCM object is freed. Use this, if this mailbox + is referenced elsewhere. + + Another one, mu_scm_mailbox_create, always create an object that + will cause closing the mu_mailbox_t object and releasing its memory + after the hosting SCM object is swept away by GC. This is the only + official one. + + The mu_scm_mailbox_create0 function is a kludge, needed because + mu_mailbox_t objects don't have reference counters. When it is fixed in + the library, the interface will be removed. */ + SCM -mu_scm_mailbox_create (mu_mailbox_t mbox) +mu_scm_mailbox_create0 (mu_mailbox_t mbox, int noclose) { struct mu_mailbox *mum; mum = scm_gc_malloc (sizeof (struct mu_mailbox), "mailbox"); mum->mbox = mbox; + mum->noclose = noclose; SCM_RETURN_NEWSMOB (mailbox_tag, mum); } +SCM +mu_scm_mailbox_create (mu_mailbox_t mbox) +{ + return mu_scm_mailbox_create0 (mbox, 0); +} + int mu_scm_is_mailbox (SCM scm) { diff --git a/libmu_scm/mu_message.c b/libmu_scm/mu_message.c index 47f950ee8..5c73e429e 100644 --- a/libmu_scm/mu_message.c +++ b/libmu_scm/mu_message.c @@ -103,7 +103,7 @@ mu_scm_message_print (SCM message_smob, SCM port, scm_print_state * pstate) else scm_puts ("UNKNOWN", port); - if (mu_envelope_sget_date (env, &buffer) == 0 + if (mu_envelope_sget_date (env, &p) == 0 && mu_parse_ctime_date_time (&p, &tm, &tz) == 0) { strftime (datebuf, sizeof (datebuf), "%a %b %e %H:%M", &tm); diff --git a/libmu_scm/mu_scm.h b/libmu_scm/mu_scm.h index 92b7b1abd..8f04bf58b 100644 --- a/libmu_scm/mu_scm.h +++ b/libmu_scm/mu_scm.h @@ -49,4 +49,3 @@ #include <mailutils/guile.h> - diff --git a/maidag/Makefile.am b/maidag/Makefile.am index 7b5eca22c..c19ffc436 100644 --- a/maidag/Makefile.am +++ b/maidag/Makefile.am @@ -21,11 +21,13 @@ sbin_PROGRAMS=maidag maidag_SOURCES=\ deliver.c\ forward.c\ + guile.c\ lmtp.c\ maidag.c\ maidag.h\ mailtmp.c\ mailquota.c\ + sieve.c\ script.c\ util.c diff --git a/maidag/deliver.c b/maidag/deliver.c index 1c6ae797f..e8a5b0769 100644 --- a/maidag/deliver.c +++ b/maidag/deliver.c @@ -72,19 +72,6 @@ maidag_stdio_delivery (int argc, char **argv) if (multiple_delivery) multiple_delivery = argc > 1; -#ifdef WITH_GUILE - if (progfile_pattern) - { - struct mda_data mda_data; - - memset (&mda_data, 0, sizeof mda_data); - mda_data.mbox = mbox; - mda_data.argv = argv; - mda_data.progfile_pattern = progfile_pattern; - return prog_mda (&mda_data); - } -#endif - for (; *argv; argv++) mda (mbox, *argv); return exit_code; @@ -322,8 +309,8 @@ deliver_url (mu_url_t url, mu_message_t msg, const char *name, char **errp) if (current_uid) auth->change_uid = 0; - - if (!sieve_test (auth, msg)) + + if (script_apply (msg, auth)) { exit_code = EX_OK; mu_auth_data_free (auth); diff --git a/maidag/guile.c b/maidag/guile.c new file mode 100644 index 000000000..9e2b19335 --- /dev/null +++ b/maidag/guile.c @@ -0,0 +1,43 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2000, 2001, 2002, 2005, + 2007, 2009 Free Software Foundation, Inc. + + GNU Mailutils 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 3, or (at your option) + any later version. + + GNU Mailutils 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 GNU Mailutils; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA */ + +#include "maidag.h" + +#ifdef WITH_GUILE +#include <mailutils/guile.h> + +int debug_guile; +static int initialized; + +int +scheme_check_msg (mu_message_t msg, struct mu_auth_data *auth, + const char *prog) +{ + if (!initialized) + { + mu_guile_init (debug_guile); + initialized = 1; + } + mu_guile_load (prog, 0, NULL); + mu_guile_message_apply (msg, "mailutils-check-message"); + return 0; +} + +#endif + diff --git a/maidag/maidag.c b/maidag/maidag.c index 88bc9abe7..94aaa03e4 100644 --- a/maidag/maidag.c +++ b/maidag/maidag.c @@ -30,8 +30,10 @@ char *quotadbname = NULL; /* Name of mailbox quota database */ char *quota_query = NULL; /* SQL query to retrieve mailbox quota */ char *sender_address = NULL; -char *progfile_pattern = NULL; -char *sieve_pattern = NULL; + +maidag_script_fun script_handler; + +mu_list_t script_list; char *forward_file = NULL; int forward_file_checks = FWD_ALL; @@ -73,28 +75,40 @@ static char args_doc[] = N_("[recipient...]"); static struct argp_option options[] = { - { "foreground", FOREGROUND_OPTION, 0, 0, N_("Remain in foreground."), 0 }, - { "inetd", 'i', 0, 0, N_("Run in inetd mode"), 0 }, +#define GRID 0 + { NULL, 0, NULL, 0, + N_("General options"), GRID }, + + { "foreground", FOREGROUND_OPTION, 0, 0, N_("Remain in foreground."), + GRID + 1 }, + { "inetd", 'i', 0, 0, N_("Run in inetd mode"), GRID + 1 }, { "daemon", 'd', N_("NUMBER"), OPTION_ARG_OPTIONAL, - N_("Runs in daemon mode with a maximum of NUMBER children"), 0 }, - { "url", URL_OPTION, 0, 0, N_("Deliver to given URLs"), 0 }, + N_("Runs in daemon mode with a maximum of NUMBER children"), GRID + 1 }, + { "url", URL_OPTION, 0, 0, N_("Deliver to given URLs"), GRID + 1 }, { "from", 'f', N_("EMAIL"), 0, - N_("Specify the sender's name") }, + N_("Specify the sender's name"), GRID + 1 }, { NULL, 'r', NULL, OPTION_ALIAS, NULL }, - { "sieve", 'S', N_("PATTERN"), 0, - N_("Set name pattern for user-defined Sieve mail filters"), 0 }, - { "message-id-header", MESSAGE_ID_HEADER_OPTION, N_("STRING"), 0, - N_("Identify messages by the value of this header when logging Sieve actions"), 0 }, -#ifdef WITH_GUILE - { "source", 's', N_("PATTERN"), 0, - N_("Set name pattern for user-defined Scheme mail filters"), 0 }, -#endif { "lmtp", LMTP_OPTION, N_("URL"), OPTION_ARG_OPTIONAL, - N_("Operate in LMTP mode"), 0 }, + N_("Operate in LMTP mode"), GRID + 1 }, { "debug", 'x', N_("FLAGS"), 0, - N_("Enable debugging"), 0 }, + N_("Enable debugging"), GRID + 1 }, { "stderr", STDERR_OPTION, NULL, 0, - N_("Log to standard error"), 0 }, + N_("Log to standard error"), GRID + 1 }, +#undef GRID + +#define GRID 2 + { NULL, 0, NULL, 0, + N_("Scripting options"), GRID }, + + { "language", 'l', N_("STRING"), 0, + N_("Define scripting language for the next --script option"), + GRID + 1 }, + { "script", 's', N_("PATTERN"), 0, + N_("Set name pattern for user-defined mail filter"), GRID + 1 }, + { "message-id-header", MESSAGE_ID_HEADER_OPTION, N_("STRING"), 0, + N_("Use this header to identify messages when logging Sieve actions"), + GRID + 1 }, +#undef GRID { NULL, 0, NULL, 0, NULL, 0 } }; @@ -201,21 +215,30 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'r': case 'f': if (sender_address != NULL) - { - argp_error (state, _("Multiple --from options")); - return EX_USAGE; - } + argp_error (state, _("Multiple --from options")); sender_address = arg; break; -#ifdef WITH_GUILE - case 's': - mu_argp_node_list_new (&lst, "guile-filter", arg); + case 'l': + script_handler = script_lang_handler (arg); + if (!script_handler) + argp_error (state, _("Unknown or unsupported language: %s"), + arg); break; -#endif + + case 's': + switch (script_register (arg)) + { + case 0: + break; - case 'S': - mu_argp_node_list_new (&lst, "sieve-filter", arg); + case EINVAL: + argp_error (state, _("%s has unknown file suffix"), arg); + break; + + default: + argp_error (state, _("error registering script")); + } break; case 'x': @@ -329,6 +352,54 @@ cb_forward_file_checks (mu_debug_t debug, void *data, mu_config_value_t *arg) return mu_cfg_string_value_cb (debug, arg, cb2_forward_file_checks, data); } +static int +cb_script_language (mu_debug_t debug, void *data, mu_config_value_t *val) +{ + if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug)) + return 1; + script_handler = script_lang_handler (val->v.string); + if (!script_handler) + { + mu_cfg_format_error (debug, MU_DEBUG_ERROR, + _("Unsupported language: %s"), + val->v.string); + return 1; + } + return 0; +} + +static int +cb_script_pattern (mu_debug_t debug, void *data, mu_config_value_t *val) +{ + if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug)) + return 1; + + switch (script_register (val->v.string)) + { + case 0: + break; + + case EINVAL: + mu_cfg_format_error (debug, MU_DEBUG_ERROR, + _("%s has unknown file suffix"), + val->v.string); + break; + + default: + mu_cfg_format_error (debug, MU_DEBUG_ERROR, + _("error registering script")); + } + return 0; +} + +struct mu_cfg_param filter_cfg_param[] = { + { "language", mu_cfg_callback, NULL, 0, cb_script_language, + N_("Set script language.") }, + { "pattern", mu_cfg_callback, NULL, 0, cb_script_pattern, + N_("Set script pattern.") }, + { NULL } +}; + struct mu_cfg_param maidag_cfg_param[] = { { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL, N_("In case of multiple delivery, exit with code 0 if at least one " @@ -347,18 +418,10 @@ struct mu_cfg_param maidag_cfg_param[] = { "sql { ... } instead."), N_("query") }, #endif - { "sieve-filter", mu_cfg_string, &sieve_pattern, 0, NULL, - N_("File name or name pattern for Sieve filter file."), - N_("file-or-pattern") }, { "message-id-header", mu_cfg_string, &message_id_header, 0, NULL, N_("When logging Sieve actions, identify messages by the value of " "this header."), N_("name") }, -#ifdef WITH_GUILE - { "guile-filter", mu_cfg_string, &progfile_pattern, 0, NULL, - N_("File name or name pattern for Guile filter file."), - N_("file-or-pattern") }, -#endif { "debug", mu_cfg_callback, NULL, 0, cb_debug, N_("Set maidag debug level. Debug level consists of one or more " "of the following letters:\n" @@ -388,138 +451,23 @@ struct mu_cfg_param maidag_cfg_param[] = { N_("url") }, { "reuse-address", mu_cfg_bool, &reuse_lmtp_address, 0, NULL, N_("Reuse existing address (LMTP mode). Default is \"yes\".") }, + { "filter", mu_cfg_section, NULL, 0, NULL, + N_("Add a message filter") }, { ".server", mu_cfg_section, NULL, 0, NULL, N_("LMTP server configuration.") }, TCP_WRAPPERS_CONFIG { NULL } }; - -/* Logging */ - -static int -_sieve_debug_printer (void *unused, const char *fmt, va_list ap) -{ - mu_diag_vprintf (MU_DIAG_DEBUG, fmt, ap); - return 0; -} - static void -_sieve_action_log (void *user_name, - const mu_sieve_locus_t *locus, size_t msgno, - mu_message_t msg, - const char *action, const char *fmt, va_list ap) -{ - int pfx = 0; - mu_debug_t debug; - - mu_diag_get_debug (&debug); - mu_debug_set_locus (debug, locus->source_file, locus->source_line); - - mu_diag_printf (MU_DIAG_NOTICE, _("(user %s) "), (char*) user_name); - if (message_id_header) - { - mu_header_t hdr = NULL; - char *val = NULL; - mu_message_get_header (msg, &hdr); - if (mu_header_aget_value (hdr, message_id_header, &val) == 0 - || mu_header_aget_value (hdr, MU_HEADER_MESSAGE_ID, &val) == 0) - { - pfx = 1; - mu_diag_printf (MU_DIAG_NOTICE, _("%s on msg %s"), action, val); - free (val); - } - } - - if (!pfx) - { - size_t uid = 0; - mu_message_get_uid (msg, &uid); - mu_diag_printf (MU_DIAG_NOTICE, _("%s on msg uid %d"), action, uid); - } - - if (fmt && strlen (fmt)) - { - mu_diag_printf (MU_DIAG_NOTICE, "; "); - mu_diag_vprintf (MU_DIAG_NOTICE, fmt, ap); - } - mu_diag_printf (MU_DIAG_NOTICE, "\n"); - mu_debug_set_locus (debug, NULL, 0); -} - -static int -_sieve_parse_error (void *user_name, const char *filename, int lineno, - const char *fmt, va_list ap) -{ - mu_debug_t debug; - - mu_diag_get_debug (&debug); - if (filename) - mu_debug_set_locus (debug, filename, li |