diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-12-04 11:23:43 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-12-04 11:45:37 +0200 |
commit | e2bd3a059eb8268d156baf59e41909cae1e28297 (patch) | |
tree | 2bb388b447716624c6afb7b157cfa1faddc2f497 /libmu_sieve | |
parent | fdf02db320d6bd88920cdcd15db3c45f71d2fb74 (diff) | |
download | mailutils-e2bd3a059eb8268d156baf59e41909cae1e28297.tar.gz mailutils-e2bd3a059eb8268d156baf59e41909cae1e28297.tar.bz2 |
sieve: redo symbol registry support.
The purpose is to simplify the machine structure and to ensure its
clones are completely independent of the master instance.
* include/mailutils/sieve.h (mu_sieve_command): New struct.
(mu_sieve_record): New enum
(mu_sieve_registry_t): Generalize for storing various types of objects.
(mu_sieve_test_lookup,mu_sieve_action_lookup)
(mu_sieve_require_action,mu_sieve_require_test)
(mu_sieve_require_comparator): Remove.
(mu_sieve_register_test_ext,mu_sieve_register_test)
(mu_sieve_register_action_ext,mu_sieve_register_action)
(mu_sieve_register_comparator)
(mu_sieve_load_ext): Change return type.
(mu_sieve_registry_require,mu_sieve_unload_ext): New functions.
(mu_sieve_machine_inherit): Rename to mu_sieve_machine_clone.
* libmu_sieve/sieve-priv.h (mu_sieve_machine): Remove source_list,
test_list, action_list, and comp_list. Add a single registry list
instead.
Add space for file and command (action and test) names: idspace,
idcount, idmax.
Remove unused field "stack";
(mu_i_sv_lex_finish): Change prototype.
(_mu_i_sv_instr_push,_mu_i_sv_instr_pop): Remove protos.
(mu_i_sv_id_canon,mu_i_sv_id_num)
(mu_i_sv_id_str,mu_i_sv_free_idspace): New protos.
* libmu_sieve/register.c: Rename to registry.c
* libmu_sieve/registry.c (mu_sieve_test_lookup)
(mu_sieve_action_lookup): Remove.
(mu_sieve_require_test,mu_sieve_require_action): Remove.
(mu_sieve_registry_require): New function.
(mu_sieve_registry_add,mu_sieve_registry_lookup): New functions.
* libmu_sieve/Makefile.am: Update.
* libmu_sieve/comparator.c: Rewrite using new registry functions.
* libmu_sieve/load.c (mu_sieve_load_ext): Return module handle.
(mu_sieve_unload_ext): New function.
* libmu_sieve/mem.c (mu_sieve_free): Gracefully handle NULL argument.
(mu_i_sv_id_canon,mu_i_sv_id_num,mu_i_sv_id_str): New functions.
* libmu_sieve/prog.c (mu_i_sv_locus): Store index of the file name in
the id space, instead of pointer to the name itself.
* libmu_sieve/require.c (mu_sieve_require): Rewrite.
* libmu_sieve/runtime.c (_mu_i_sv_instr_source): Expect ID index
as argument.
(_mu_i_sv_instr_push)
(_mu_i_sv_instr_pop): Remove unused instructions.
* libmu_sieve/sieve.l (file_names): Remove. Use mu_sieve_machine
idspace instead.
* libmu_sieve/sieve.y (mu_sieve_machine_clone)
(mu_sieve_machine_dup): Rewrite.
(mu_sieve_machine_destroy): Free idspace and registry
* examples/numaddr.c: Reflect changes.
* libmu_sieve/extensions/editheader.c: Likewise.
* libmu_sieve/extensions/list.c: Likewise.
* libmu_sieve/extensions/moderator.c: Likewise.
* libmu_sieve/extensions/pipe.c: Likewise.
* libmu_sieve/extensions/spamd.c: Likewise.
* libmu_sieve/extensions/timestamp.c: Likewise.
* libmu_sieve/extensions/vacation.c: Likewise.
Diffstat (limited to 'libmu_sieve')
-rw-r--r-- | libmu_sieve/Makefile.am | 2 | ||||
-rw-r--r-- | libmu_sieve/comparator.c | 80 | ||||
-rw-r--r-- | libmu_sieve/extensions/editheader.c | 25 | ||||
-rw-r--r-- | libmu_sieve/extensions/list.c | 5 | ||||
-rw-r--r-- | libmu_sieve/extensions/moderator.c | 11 | ||||
-rw-r--r-- | libmu_sieve/extensions/pipe.c | 12 | ||||
-rw-r--r-- | libmu_sieve/extensions/spamd.c | 5 | ||||
-rw-r--r-- | libmu_sieve/extensions/timestamp.c | 5 | ||||
-rw-r--r-- | libmu_sieve/extensions/vacation.c | 5 | ||||
-rw-r--r-- | libmu_sieve/load.c | 38 | ||||
-rw-r--r-- | libmu_sieve/mem.c | 65 | ||||
-rw-r--r-- | libmu_sieve/prog.c | 22 | ||||
-rw-r--r-- | libmu_sieve/register.c | 171 | ||||
-rw-r--r-- | libmu_sieve/registry.c | 177 | ||||
-rw-r--r-- | libmu_sieve/require.c | 44 | ||||
-rw-r--r-- | libmu_sieve/runtime.c | 36 | ||||
-rw-r--r-- | libmu_sieve/sieve-priv.h | 22 | ||||
-rw-r--r-- | libmu_sieve/sieve.l | 32 | ||||
-rw-r--r-- | libmu_sieve/sieve.y | 190 | ||||
-rw-r--r-- | libmu_sieve/tests.c | 10 |
20 files changed, 487 insertions, 470 deletions
diff --git a/libmu_sieve/Makefile.am b/libmu_sieve/Makefile.am index b9f3a0ada..d0a77a967 100644 --- a/libmu_sieve/Makefile.am +++ b/libmu_sieve/Makefile.am @@ -34,7 +34,7 @@ libmu_sieve_la_SOURCES = \ load.c\ mem.c\ prog.c\ - register.c\ + registry.c\ relational.c\ require.c\ runtime.c\ diff --git a/libmu_sieve/comparator.c b/libmu_sieve/comparator.c index 44dd05bbf..591b4d4a8 100644 --- a/libmu_sieve/comparator.c +++ b/libmu_sieve/comparator.c @@ -30,13 +30,7 @@ #include <mailutils/cctype.h> #include <mailutils/cstr.h> -typedef struct { - const char *name; - int required; - mu_sieve_comparator_t comp[MU_SIEVE_MATCH_LAST]; -} sieve_comparator_record_t; - -int +void mu_sieve_register_comparator (mu_sieve_machine_t mach, const char *name, int required, @@ -46,70 +40,26 @@ mu_sieve_register_comparator (mu_sieve_machine_t mach, mu_sieve_comparator_t regex, mu_sieve_comparator_t eq) { - sieve_comparator_record_t *rp; - - if (!mach->comp_list) - { - int rc = mu_list_create (&mach->comp_list); - if (rc) - return rc; - } - - rp = mu_sieve_malloc (mach, sizeof (*rp)); - rp->required = required; - rp->name = name; - rp->comp[MU_SIEVE_MATCH_IS] = is; - rp->comp[MU_SIEVE_MATCH_CONTAINS] = contains; - rp->comp[MU_SIEVE_MATCH_MATCHES] = matches; - rp->comp[MU_SIEVE_MATCH_REGEX] = regex; - rp->comp[MU_SIEVE_MATCH_EQ] = eq; - - return mu_list_append (mach->comp_list, rp); -} - -sieve_comparator_record_t * -_lookup (mu_list_t list, const char *name) -{ - mu_iterator_t itr; - sieve_comparator_record_t *reg; - - if (!list || mu_list_get_iterator (list, &itr)) - return NULL; - - for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) - { - mu_iterator_current (itr, (void **)®); - if (strcmp (reg->name, name) == 0) - break; - else - reg = NULL; - } - mu_iterator_destroy (&itr); - return reg; -} - -int -mu_sieve_require_comparator (mu_sieve_machine_t mach, const char *name) -{ - sieve_comparator_record_t *reg = _lookup (mach->comp_list, name); - if (!reg) - { - if (!(mu_sieve_load_ext (mach, name) == 0 - && (reg = _lookup (mach->comp_list, name)) != NULL)) - return 1; - } - - reg->required = 1; - return 0; + mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name); + + reg->type = mu_sieve_record_comparator; + reg->required = required; + reg->name = name; + reg->v.comp[MU_SIEVE_MATCH_IS] = is; + reg->v.comp[MU_SIEVE_MATCH_CONTAINS] = contains; + reg->v.comp[MU_SIEVE_MATCH_MATCHES] = matches; + reg->v.comp[MU_SIEVE_MATCH_REGEX] = regex; + reg->v.comp[MU_SIEVE_MATCH_EQ] = eq; } mu_sieve_comparator_t mu_sieve_comparator_lookup (mu_sieve_machine_t mach, const char *name, int matchtype) { - sieve_comparator_record_t *reg = _lookup (mach->comp_list, name); - if (reg && reg->comp[matchtype]) - return reg->comp[matchtype]; + mu_sieve_registry_t *reg = + mu_sieve_registry_lookup (mach, name, mu_sieve_record_comparator); + if (reg && reg->v.comp[matchtype]) + return reg->v.comp[matchtype]; return NULL; } diff --git a/libmu_sieve/extensions/editheader.c b/libmu_sieve/extensions/editheader.c index 3ef017f0d..dfb51acfc 100644 --- a/libmu_sieve/extensions/editheader.c +++ b/libmu_sieve/extensions/editheader.c @@ -272,22 +272,13 @@ static mu_sieve_data_type deleteheader_args[] = { int SIEVE_EXPORT (editheader, init) (mu_sieve_machine_t mach) { - int rc; - /* This dummy record is required by libmu_sieve */ - rc = mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1); - if (rc) - return rc; - rc = mu_sieve_register_action (mach, "addheader", sieve_addheader, - addheader_args, addheader_tag_groups, 1); - if (rc) - return rc; - rc = mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader, - deleteheader_args, deleteheader_args, - deleteheader_tag_groups, - 1); - if (rc) - return rc; - - return rc; + mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1); + mu_sieve_register_action (mach, "addheader", sieve_addheader, + addheader_args, addheader_tag_groups, 1); + mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader, + deleteheader_args, deleteheader_args, + deleteheader_tag_groups, + 1); + return 0; } diff --git a/libmu_sieve/extensions/list.c b/libmu_sieve/extensions/list.c index 3a64e0a69..e31e76358 100644 --- a/libmu_sieve/extensions/list.c +++ b/libmu_sieve/extensions/list.c @@ -203,8 +203,9 @@ static mu_sieve_tag_group_t list_tag_groups[] = { int SIEVE_EXPORT(list,init) (mu_sieve_machine_t mach) { - return mu_sieve_register_test (mach, "list", list_test, - list_req_args, list_tag_groups, 1); + mu_sieve_register_test (mach, "list", list_test, + list_req_args, list_tag_groups, 1); + return 0; } /* End of list.c */ diff --git a/libmu_sieve/extensions/moderator.c b/libmu_sieve/extensions/moderator.c index 249611cad..f2ccd8284 100644 --- a/libmu_sieve/extensions/moderator.c +++ b/libmu_sieve/extensions/moderator.c @@ -84,7 +84,7 @@ moderator_filter_message (mu_sieve_machine_t mach, if (mu_sieve_get_tag (mach, "source", SVT_STRING, &arg)) { - rc = mu_sieve_machine_inherit (mach, &newmach); + rc = mu_sieve_machine_clone (mach, &newmach); if (rc) { mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), @@ -105,7 +105,7 @@ moderator_filter_message (mu_sieve_machine_t mach, { struct mu_locus locus; - rc = mu_sieve_machine_inherit (mach, &newmach); + rc = mu_sieve_machine_clone (mach, &newmach); if (rc) { mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), @@ -363,8 +363,9 @@ static mu_sieve_tag_group_t moderator_tag_groups[] = { int SIEVE_EXPORT(moderator,init) (mu_sieve_machine_t mach) { - return mu_sieve_register_action (mach, "moderator", moderator_action, - moderator_req_args, - moderator_tag_groups, 1); + mu_sieve_register_action (mach, "moderator", moderator_action, + moderator_req_args, + moderator_tag_groups, 1); + return 0; } diff --git a/libmu_sieve/extensions/pipe.c b/libmu_sieve/extensions/pipe.c index 3aedf16ac..5ba6c134b 100644 --- a/libmu_sieve/extensions/pipe.c +++ b/libmu_sieve/extensions/pipe.c @@ -275,11 +275,9 @@ static mu_sieve_data_type pipe_args[] = { int SIEVE_EXPORT (pipe, init) (mu_sieve_machine_t mach) { - int rc; - rc = mu_sieve_register_action (mach, "pipe", sieve_action_pipe, - pipe_args, pipe_action_tag_groups, 1); - if (rc) - return rc; - return mu_sieve_register_test (mach, "pipe", sieve_test_pipe, - pipe_args, pipe_test_tag_groups, 1); + mu_sieve_register_action (mach, "pipe", sieve_action_pipe, + pipe_args, pipe_action_tag_groups, 1); + mu_sieve_register_test (mach, "pipe", sieve_test_pipe, + pipe_args, pipe_test_tag_groups, 1); + return 0; } diff --git a/libmu_sieve/extensions/spamd.c b/libmu_sieve/extensions/spamd.c index 692f49ae2..2ea2efd35 100644 --- a/libmu_sieve/extensions/spamd.c +++ b/libmu_sieve/extensions/spamd.c @@ -544,7 +544,8 @@ static mu_sieve_tag_group_t spamd_tag_groups[] = { int SIEVE_EXPORT(spamd,init) (mu_sieve_machine_t mach) { - return mu_sieve_register_test (mach, "spamd", spamd_test, - spamd_req_args, spamd_tag_groups, 1); + mu_sieve_register_test (mach, "spamd", spamd_test, + spamd_req_args, spamd_tag_groups, 1); + return 0; } diff --git a/libmu_sieve/extensions/timestamp.c b/libmu_sieve/extensions/timestamp.c index e96f4ddcf..5adf4decc 100644 --- a/libmu_sieve/extensions/timestamp.c +++ b/libmu_sieve/extensions/timestamp.c @@ -123,6 +123,7 @@ static mu_sieve_tag_group_t timestamp_tag_groups[] = { int SIEVE_EXPORT(timestamp,init) (mu_sieve_machine_t mach) { - return mu_sieve_register_test (mach, "timestamp", timestamp_test, - timestamp_req_args, timestamp_tag_groups, 1); + mu_sieve_register_test (mach, "timestamp", timestamp_test, + timestamp_req_args, timestamp_tag_groups, 1); + return 0; } diff --git a/libmu_sieve/extensions/vacation.c b/libmu_sieve/extensions/vacation.c index fa19c8785..ecff9386b 100644 --- a/libmu_sieve/extensions/vacation.c +++ b/libmu_sieve/extensions/vacation.c @@ -868,6 +868,7 @@ static mu_sieve_data_type vacation_args[] = { int SIEVE_EXPORT (vacation, init) (mu_sieve_machine_t mach) { - return mu_sieve_register_action (mach, "vacation", sieve_action_vacation, - vacation_args, vacation_tag_groups, 1); + mu_sieve_register_action (mach, "vacation", sieve_action_vacation, + vacation_args, vacation_tag_groups, 1); + return 0; } diff --git a/libmu_sieve/load.c b/libmu_sieve/load.c index c164c2741..deddcd2d8 100644 --- a/libmu_sieve/load.c +++ b/libmu_sieve/load.c @@ -31,16 +31,6 @@ typedef int (*sieve_module_init_t) (mu_sieve_machine_t mach); -#if 0 -/* FIXME: See comment below */ -static void -_free_loaded_module (void *data) -{ - lt_dlclose ((lt_dlhandle)data); - lt_dlexit (); -} -#endif - static int _add_load_dir (void *, void *); static int @@ -61,8 +51,7 @@ sieve_init_load_path () } return 0; } - - + static lt_dlhandle load_module (mu_sieve_machine_t mach, const char *name) { @@ -74,18 +63,12 @@ load_module (mu_sieve_machine_t mach, const char *name) handle = lt_dlopenext (name); if (handle) { - sieve_module_init_t init = (sieve_module_init_t) - lt_dlsym (handle, "init"); + sieve_module_init_t init; + + init = (sieve_module_init_t) lt_dlsym (handle, "init"); if (init) { init (mach); - /* FIXME: We used to have this: - mu_sieve_machine_add_destructor (mach, _free_loaded_module, - handle); - However, unloading modules can lead to random segfaults in - case they allocated any global-access data (e.g. mach->msg). - In particular, this was the case with extensions/pipe.c. - */ return handle; } else @@ -114,7 +97,7 @@ fix_module_name (char *name) } } -int +void * mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name) { lt_dlhandle handle; @@ -122,11 +105,18 @@ mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name) modname = strdup (name); if (!modname) - return 1; + return NULL; fix_module_name (modname); handle = load_module (mach, modname); free (modname); - return handle == NULL; + return handle; +} + +void +mu_sieve_unload_ext (void *data) +{ + if (data) + lt_dlclose ((lt_dlhandle)data); } static int diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c index 3c39a3d10..565ba3228 100644 --- a/libmu_sieve/mem.c +++ b/libmu_sieve/mem.c @@ -83,6 +83,9 @@ mu_sieve_free (mu_sieve_machine_t mach, void *ptr) int rc; struct memory_cell mcell; + if (!ptr) + return; + mcell.ptr = ptr; rc = mu_list_remove (mach->memory_pool, &mcell); if (rc) @@ -228,3 +231,65 @@ mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb, *pptr = ptr; *pnmemb = nmemb; } + +char * +mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name) +{ + size_t i; + char *p; + + if (!name) + return NULL; + + for (i = 0; i < mach->idcount; i++) + { + if (strcmp (mach->idspace[i], name) == 0) + return mach->idspace[i]; + } + + if (mach->idcount == mach->idmax) + { + mu_i_sv_2nrealloc (mach, + (void **) &mach->idspace, + &mach->idmax, + sizeof mach->idspace[0]); + } + + p = mu_sieve_strdup (mach, name); + mach->idspace[mach->idcount++] = p; + + return p; +} + +size_t +mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name) +{ + size_t i; + + for (i = 0; i < mach->idcount; i++) + { + if (mach->idspace[i] == name || strcmp (mach->idspace[i], name) == 0) + return i; + } + abort (); +} + +char * +mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n) +{ + if (n >= mach->idcount) + abort (); + return mach->idspace[n]; +} + +void +mu_i_sv_free_idspace (mu_sieve_machine_t mach) +{ + size_t i; + + for (i = 0; i < mach->idcount; i++) + mu_sieve_free (mach, mach->idspace[i]); + mach->idcount = 0; +} + + diff --git a/libmu_sieve/prog.c b/libmu_sieve/prog.c index 17b65870f..6ab96091e 100644 --- a/libmu_sieve/prog.c +++ b/libmu_sieve/prog.c @@ -52,7 +52,7 @@ mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr) if (!file_eq (mach->locus.mu_file, lr->beg.mu_file)) { mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_source); - mu_i_sv_code (mach, (sieve_op_t) lr->beg.mu_file); + mu_i_sv_code (mach, (sieve_op_t) mu_i_sv_id_num (mach, lr->beg.mu_file)); } if (mach->locus.mu_line != lr->beg.mu_line) { @@ -133,8 +133,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, struct mu_sieve_node *node) { size_t i; - mu_sieve_register_t *reg = node->v.command.reg; - + mu_sieve_registry_t *reg = node->v.command.reg; + mu_sieve_value_t *start = mach->valspace + node->v.command.argstart; mu_list_t chk_list = NULL; @@ -142,8 +142,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, int opt_args = 0; int rc, err = 0; static mu_sieve_data_type empty[] = { SVT_VOID }; + + if (!reg) + return; - exp_arg = reg->req_args ? reg->req_args : empty; + exp_arg = reg->v.command.req_args ? reg->v.command.req_args : empty; /* Pass 1: consolidation */ for (i = 0; i < node->v.command.argcount; i++) @@ -153,7 +156,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, if (val->type == SVT_TAG) { mu_sieve_tag_checker_t cf; - mu_sieve_tag_def_t *tag = find_tag (reg->tags, val->v.string, &cf); + mu_sieve_tag_def_t *tag = find_tag (reg->v.command.tags, + val->v.string, &cf); if (!tag) { @@ -228,9 +232,9 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, { if (*exp_arg == SVT_VOID) { - if (reg->opt_args) + if (reg->v.command.opt_args) { - exp_arg = reg->opt_args; + exp_arg = reg->v.command.opt_args; opt_args = 1; } else @@ -252,7 +256,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, { mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, _("type mismatch in argument %lu to `%s'"), - (unsigned long) (exp_arg - reg->req_args + 1), + (unsigned long) (exp_arg - reg->v.command.req_args + 1), reg->name); mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, _("expected %s but passed %s"), @@ -316,7 +320,7 @@ static void sv_code_command (struct mu_sieve_machine *mach, struct mu_sieve_node *node) { - mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->handler); + mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->v.command.handler); mu_i_sv_code (mach, (sieve_op_t) node->v.command.argstart); mu_i_sv_code (mach, (sieve_op_t) node->v.command.argcount); mu_i_sv_code (mach, (sieve_op_t) node->v.command.tagcount); diff --git a/libmu_sieve/register.c b/libmu_sieve/register.c deleted file mode 100644 index acd387645..000000000 --- a/libmu_sieve/register.c +++ /dev/null @@ -1,171 +0,0 @@ -/* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999-2002, 2004-2005, 2007-2008, 2010-2012, 2014-2016 - 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, see - <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sieve-priv.h> - -static mu_sieve_register_t * -reg_lookup (mu_list_t list, const char *name) -{ - mu_iterator_t itr; - mu_sieve_register_t *reg; - - if (!list || mu_list_get_iterator (list, &itr)) - return NULL; - - for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) - { - mu_iterator_current (itr, (void **)®); - if (strcmp (reg->name, name) == 0) - break; - else - reg = NULL; - } - mu_iterator_destroy (&itr); - return reg; -} - -mu_sieve_register_t * -mu_sieve_test_lookup (mu_sieve_machine_t mach, const char *name) -{ - mu_sieve_register_t *reg = reg_lookup (mach->test_list, name); - return (reg && reg->handler) ? reg : NULL; -} - -mu_sieve_register_t * -mu_sieve_action_lookup (mu_sieve_machine_t mach, const char *name) -{ - mu_sieve_register_t *reg = reg_lookup (mach->action_list, name); - return (reg && reg->handler) ? reg : NULL; -} - -static int -reg_require (mu_sieve_machine_t mach, mu_list_t list, const char *name) -{ - mu_sieve_register_t *reg = reg_lookup (list, name); - if (!reg) - { - if (!(mu_sieve_load_ext (mach, name) == 0 - && (reg = reg_lookup (list, name)) != NULL)) - return 1; - } - reg->required = 1; - return 0; -} - -int -mu_sieve_require_action (mu_sieve_machine_t mach, const char *name) -{ - return reg_require (mach, mach->action_list, name); -} - -int -mu_sieve_require_test (mu_sieve_machine_t mach, const char *name) -{ - return reg_require (mach, mach->test_list, name); -} - - -static int -sieve_register (mu_sieve_machine_t mach, - mu_list_t *list, - const char *name, mu_sieve_handler_t handler, - mu_sieve_data_type *req_arg_types, - mu_sieve_data_type *opt_arg_types, - mu_sieve_tag_group_t *tags, int required) -{ - mu_sieve_register_t *reg = mu_sieve_malloc (mach, sizeof (*reg)); - - if (!reg) - return ENOMEM; - reg->name = name; - reg->handler = handler; - - reg->req_args = req_arg_types; - reg->opt_args = opt_arg_types; - reg->tags = tags; - reg->required = required; - - if (!*list) - { - int rc = mu_list_create (list); - if (rc) - { - free (reg); - return rc; - } - } - - return mu_list_append (*list, reg); -} - - -int -mu_sieve_register_test_ext (mu_sieve_machine_t mach, - const char *name, mu_sieve_handler_t handler, - mu_sieve_data_type *req_args, - mu_sieve_data_type *opt_args, - mu_sieve_tag_group_t *tags, int required) -{ - return sieve_register (mach, - &mach->test_list, name, handler, - req_args, opt_args, tags, required); -} - -int -mu_sieve_register_test (mu_sieve_machine_t mach, - const char *name, mu_sieve_handler_t handler, - mu_sieve_data_type *arg_types, - mu_sieve_tag_group_t *tags, int required) -{ - return mu_sieve_register_test_ext (mach, name, handler, - arg_types, NULL, - tags, - required); -} - -int -mu_sieve_register_action_ext (mu_sieve_machine_t mach, - const char *name, mu_sieve_handler_t handler, - mu_sieve_data_type *req_args, - mu_sieve_data_type *opt_args, - mu_sieve_tag_group_t *tags, int required) -{ - return sieve_register (mach, - &mach->action_list, name, handler, - req_args, opt_args, tags, required); -} - -int -mu_sieve_register_action (mu_sieve_machine_t mach, - const char *name, mu_sieve_handler_t handler, - mu_sieve_data_type *arg_types, - mu_sieve_tag_group_t *tags, int required) -{ - return mu_sieve_register_action_ext (mach, name, handler, - arg_types, NULL, - tags, - required); -} diff --git a/libmu_sieve/registry.c b/libmu_sieve/registry.c new file mode 100644 index 000000000..a5cbdfca9 --- /dev/null +++ b/libmu_sieve/registry.c @@ -0,0 +1,177 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999-2002, 2004-2005, 2007-2008, 2010-2012, 2014-2016 + 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, see + <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sieve-priv.h> + +int +mu_sieve_registry_require (mu_sieve_machine_t mach, const char *name, + enum mu_sieve_record type) +{ + mu_sieve_registry_t *reg; + + reg = mu_sieve_registry_lookup (mach, name, type); + if (!reg) + { + void *handle = mu_sieve_load_ext (mach, name); + if (!handle) + return 1; + reg = mu_sieve_registry_lookup (mach, name, type); + if (!reg) + return 1; + reg->handle = handle; + } + + reg->required = 1; + return 0; +} + + +static void +regunload (void *data) +{ + mu_sieve_registry_t *reg = data; + mu_sieve_unload_ext (reg->handle); +} + +static int +regcmp (void const *a, void const *b) +{ + mu_sieve_registry_t const *rega = a; + mu_sieve_registry_t const *regb = b; + if (rega->type != regb->type) + return rega->type - regb->type; + return strcmp (rega->name, regb->name); +} + +mu_sieve_registry_t * +mu_sieve_registry_add (mu_sieve_machine_t mach, const char *name) +{ + mu_sieve_registry_t *reg; + int rc; + + if (!mach->registry) + { + rc = mu_list_create (&mach->registry); + if (rc) + { + mu_sieve_error (mach, "mu_list_create: %s", mu_strerror (rc)); + mu_sieve_abort (mach); + } + mu_list_set_destroy_item (mach->registry, regunload); + mu_list_set_comparator (mach->registry, regcmp); + } + reg = mu_sieve_malloc (mach, sizeof (*reg)); + reg->name = name; + reg->handle = NULL; + reg->required = 0; + memset (®->v, 0, sizeof reg->v); + rc = mu_list_append (mach->registry, reg); + if (rc) + { + mu_sieve_error (mach, "mu_list_append: %s", mu_strerror (rc)); + mu_sieve_abort (mach); + } + return reg; +} + +mu_sieve_registry_t * +mu_sieve_registry_lookup (mu_sieve_machine_t mach, const char *name, + enum mu_sieve_record type) +{ + mu_sieve_registry_t key, *reg; + int rc; + + key.name = name; + key.type = type; + + rc = mu_list_locate (mach->registry, &key, (void**) ®); + if (rc == MU_ERR_NOENT) + return NULL; + else if (rc) + { + mu_sieve_error (mach, _("registry lookup failed: %s"), mu_strerror (rc)); + mu_sieve_abort (mach); + } + return reg; +} + +void +mu_sieve_register_test_ext (mu_sieve_machine_t mach, + const char *name, mu_sieve_handler_t handler, + mu_sieve_data_type *req_args, + mu_sieve_data_type *opt_args, + mu_sieve_tag_group_t *tags, int required) +{ + mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name); + + reg->type = mu_sieve_record_test; + reg->required = required; + reg->v.command.handler = handler; + reg->v.command.req_args = req_args; + reg->v.command.opt_args = opt_args; + reg->v.command.tags = tags; +} + +void +mu_sieve_register_test (mu_sieve_machine_t mach, + const char *name, mu_sieve_handler_t handler, + mu_sieve_data_type *arg_types, + mu_sieve_tag_group_t *tags, int required) +{ + return mu_sieve_register_test_ext (mach, name, handler, + arg_types, NULL, + tags, + required); +} + +void +mu_sieve_register_action_ext (mu_sieve_machine_t mach, + const char *name, mu_sieve_handler_t handler, + mu_sieve_data_type *req_args, + mu_sieve_data_type *opt_args, + mu_sieve_tag_group_t *tags, int required) +{ + mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name); + + reg->type = mu_sieve_record_action; + reg->required = required; + reg->v.command.handler = handler; + reg->v.command.req_args = req_args; + reg->v.command.opt_args = opt_args; + reg->v.command.tags = tags; +} + +void +mu_sieve_register_action (mu_sieve_machine_t mach, + const char *name, mu_sieve_handler_t handler, + mu_sieve_data_type *arg_types, + mu_sieve_tag_group_t *tags, int required) +{ + return mu_sieve_register_action_ext (mach, name, handler, + arg_types, NULL, + |