summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--guimb/collect.c30
-rw-r--r--guimb/guimb.h11
-rw-r--r--guimb/main.c68
-rw-r--r--guimb/scm/sieve-core.scm17
-rw-r--r--guimb/scm/sieve.scm.in83
-rw-r--r--include/mailutils/guile.h12
-rw-r--r--libmu_scm/Makefile.am1
-rw-r--r--libmu_scm/mu_guile.c199
-rw-r--r--libmu_scm/mu_mailbox.c32
-rw-r--r--libmu_scm/mu_message.c2
-rw-r--r--libmu_scm/mu_scm.h1
-rw-r--r--maidag/Makefile.am2
-rw-r--r--maidag/deliver.c17
-rw-r--r--maidag/guile.c43
-rw-r--r--maidag/maidag.c265
-rw-r--r--maidag/maidag.h48
-rw-r--r--maidag/script.c212
-rw-r--r--maidag/sieve.c115
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, &param);
- /*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