diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2010-04-05 21:09:40 +0400 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2010-04-05 21:09:40 +0400 |
commit | 42baae32bc212e9287e11afa685e2de77cdf48e4 (patch) | |
tree | 1bf9ad6eeb94a0bf40e8d60ed1a0777aa23aa69d /src/lua | |
parent | 6be82def714f297d54302953286223b4afb07208 (diff) | |
download | rspamd-42baae32bc212e9287e11afa685e2de77cdf48e4.tar.gz rspamd-42baae32bc212e9287e11afa685e2de77cdf48e4.zip |
* Add initial version of lua configuration system
Diffstat (limited to 'src/lua')
-rw-r--r-- | src/lua/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/lua/lua_cfg_file.c | 196 | ||||
-rw-r--r-- | src/lua/lua_common.c | 5 | ||||
-rw-r--r-- | src/lua/lua_common.h | 9 |
4 files changed, 210 insertions, 3 deletions
diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index d0ac4f826..c17936862 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -3,7 +3,8 @@ SET(LUASRC lua_common.c lua_task.c lua_message.c lua_config.c - lua_classifier.c) + lua_classifier.c + lua_cfg_file.c) ADD_LIBRARY(rspamd_lua STATIC ${LUASRC}) TARGET_LINK_LIBRARIES(rspamd_lua ${LUALIB}) diff --git a/src/lua/lua_cfg_file.c b/src/lua/lua_cfg_file.c new file mode 100644 index 000000000..1ac334299 --- /dev/null +++ b/src/lua/lua_cfg_file.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2009, Rambler media + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY Rambler media ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Rambler BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lua_common.h" + +/* + * This is implementation of lua routines to handle config file params + */ + + +/* Check element with specified name in list, and append it to list if no element with such name was found */ +static void +lua_check_element (memory_pool_t *pool, const gchar *name, GList *options, struct module_opt **opt) +{ + struct module_opt *cur; + GList *cur_opt; + gboolean found = FALSE; + + cur_opt = options; + + while (cur_opt) { + cur = cur_opt->data; + + if (g_ascii_strcasecmp (cur->param, name) == 0) { + found = TRUE; + break; + } + cur_opt = g_list_next (cur_opt); + } + + if (found) { + *opt = cur; + cur->is_lua = TRUE; + } + else { + /* New option */ + *opt = memory_pool_alloc0 (pool, sizeof (struct module_opt)); + (*opt)->is_lua = TRUE; + (void)g_list_append (options, *opt); + } +} + +/* Process a single item in 'config' table */ +static void +lua_process_module (lua_State *L, const gchar *param, struct config_file *cfg) +{ + GList *cur_opt; + struct module_opt *cur; + const char *name; + gboolean new_module = FALSE; + + /* Get module opt structure */ + if ((cur_opt = g_hash_table_lookup (cfg->modules_opts, param)) == NULL) { + new_module = TRUE; + } + + /* Now iterate throught module table */ + lua_gettable (L, -1); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + /* key - -2, value - -1 */ + name = luaL_checkstring (L, -2); + if (name != NULL) { + lua_check_element (cfg->cfg_pool, name, cur_opt, &cur); + lua_process_element (cfg, name, cur, -1); + } + } + + if (new_module && cur_opt != NULL) { + /* Insert new list into a hash */ + g_hash_table_insert (cfg->modules_opts, memory_pool_strdup (cfg->cfg_pool, param), cur_opt); + } +} + +/* Process single element */ +void +lua_process_element (struct config_file *cfg, const char *name, struct module_opt *opt, int idx) +{ + lua_State *L = cfg->lua_state; + int t; + double *num; + gboolean *flag; + + t = lua_type (L, idx); + /* Handle type */ + switch (t) { + case LUA_TNUMBER: + opt->actual_data = memory_pool_alloc (cfg->cfg_pool, sizeof (double)); + num = (double *)opt->actual_data; + *num = lua_tonumber (L, idx); + opt->lua_type = LUA_VAR_NUM; + break; + case LUA_TBOOLEAN: + opt->actual_data = memory_pool_alloc (cfg->cfg_pool, sizeof (gboolean)); + flag = (gboolean *)opt->actual_data; + *flag = lua_toboolean (L, idx); + opt->lua_type = LUA_VAR_BOOLEAN; + break; + case LUA_TSTRING: + opt->actual_data = memory_pool_strdup (cfg->cfg_pool, lua_tostring (L, idx)); + opt->lua_type = LUA_VAR_STRING; + break; + case LUA_TFUNCTION: + opt->actual_data = (gpointer)lua_topointer (L, idx); + opt->lua_type = LUA_VAR_FUNCTION; + break; + case LUA_TNIL: + case LUA_TTABLE: + case LUA_TUSERDATA: + case LUA_TTHREAD: + case LUA_TLIGHTUSERDATA: + msg_warn ("cannot handle variables of type %s as there is nothing to do with them", lua_typename (L, t)); + opt->lua_type = LUA_VAR_UNKNOWN; + break; + } +} + + +static void +lua_module_callback (gpointer key, gpointer value, gpointer ud) +{ + struct config_file *cfg = ud; + lua_State *L = cfg->lua_state; + GList *cur; + struct module_opt *opt; + + cur = value; + while (cur) { + opt = cur->data; + if (opt->is_lua && opt->actual_data == NULL) { + /* Try to extract variable name from config table first */ + lua_getglobal (L, "config"); + if (lua_istable (L, -1)) { + lua_pushstring (L, opt->param); + lua_gettable (L, -2); + if (lua_isnil (L, -1)) { + /* Try to get global variable */ + lua_getglobal (L, opt->param); + } + } + else { + /* Try to get global variable */ + lua_getglobal (L, opt->param); + } + lua_process_element (cfg, opt->param, opt, -1); + } + cur = g_list_next (cur); + } + +} + +/* Do post load initialization based on lua */ +void +lua_post_load_config (struct config_file *cfg) +{ + lua_State *L = cfg->lua_state; + const gchar *name; + + /* First check all module options that may be overriden in 'config' global */ + lua_getglobal (L, "config"); + + if (lua_istable (L, -1)) { + /* Iterate */ + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + /* 'key' is at index -2 and 'value' is at index -1 */ + /* Key must be a string and value must be a table */ + name = luaL_checkstring (L, -2); + if (name != NULL && lua_istable (L, -1)) { + lua_process_module (L, name, cfg); + } + } + } + + /* Now parse all lua params */ + g_hash_table_foreach (cfg->modules_opts, lua_module_callback, cfg); +} diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c index 1f39975d0..3d4e29b28 100644 --- a/src/lua/lua_common.c +++ b/src/lua/lua_common.c @@ -180,7 +180,7 @@ luaopen_logger (lua_State * L) return 1; } -static void +void init_lua () { if (L == NULL) { @@ -211,7 +211,6 @@ init_lua_filters (struct config_file *cfg) struct script_module *module; struct statfile *st; - init_lua (); cur = g_list_first (cfg->script_modules); while (cur) { module = cur->data; @@ -251,6 +250,8 @@ init_lua_filters (struct config_file *cfg) } cur = g_list_next (cur); } + /* Assign state */ + cfg->lua_state = L; } /* Callback functions */ diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h index a1820d064..5de7bdc71 100644 --- a/src/lua/lua_common.h +++ b/src/lua/lua_common.h @@ -16,6 +16,7 @@ extern const luaL_reg null_reg[]; +/* Common utility functions */ void lua_newclass (lua_State *L, const char *classname, const struct luaL_reg *func); void lua_setclass (lua_State *L, const char *classname, int objidx); void lua_set_table_index (lua_State *L, const char *index, const char *value); @@ -29,17 +30,25 @@ int luaopen_hash_table (lua_State *L); int luaopen_textpart (lua_State *L); int luaopen_classifier (lua_State *L); int luaopen_statfile (lua_State * L); +void init_lua (); void init_lua_filters (struct config_file *cfg); +/* Filters functions */ int lua_call_filter (const char *function, struct worker_task *task); int lua_call_chain_filter (const char *function, struct worker_task *task, int *marks, unsigned int number); double lua_consolidation_func (struct worker_task *task, const char *metric_name, const char *function_name); void add_luabuf (const char *line); +/* Classify functions */ GList *call_classifier_pre_callbacks (struct classifier_config *ccf, struct worker_task *task); double call_classifier_post_callbacks (struct classifier_config *ccf, struct worker_task *task, double in); double lua_normalizer_func (double score, void *params); +/* Config file functions */ +void lua_post_load_config (struct config_file *cfg); +void lua_process_element (struct config_file *cfg, const char *name, struct module_opt *opt, int idx); + + #endif /* WITH_LUA */ #endif /* RSPAMD_LUA_H */ |