From 2f81b111843005d12e1c7a50d4cfe5b22498c710 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 23 May 2017 17:23:14 +0200 Subject: [PATCH] Make the moduledir configurable at the runtime --- daemon/engine.c | 85 +++++++++++++++++++++++++++++++++++++++---------- daemon/engine.h | 5 +++ daemon/main.c | 28 ++++++++++------ lib/module.c | 8 ++--- 4 files changed, 94 insertions(+), 32 deletions(-) diff --git a/daemon/engine.c b/daemon/engine.c index 520cd3cd3..f6a6513a2 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "daemon/engine.h" @@ -43,6 +44,13 @@ KR_NORETURN int lua_error (lua_State *L); /* Cleanup engine state every 5 minutes */ const size_t CLEANUP_TIMER = 5*60*1000; +/* Execute byte code */ +#define l_dobytecode(L, arr, len, name) \ + (luaL_loadbuffer((L), (arr), (len), (name)) || lua_pcall((L), 0, LUA_MULTRET, 0)) +/** Load file in a sandbox environment. */ +#define l_dosandboxfile(L, filename) \ + (luaL_loadfile((L), (filename)) || engine_pcall((L), 0)) + /* * Global bindings. */ @@ -201,6 +209,63 @@ static int l_hostname(lua_State *L) return 1; } +char *engine_get_moduledir(struct engine *engine) { + return engine->moduledir; +} + +int engine_set_moduledir(struct engine *engine, const char *moduledir) { + if (!engine || !moduledir) { + return kr_error(EINVAL); + } + + char *new_moduledir = strdup(moduledir); + if (!new_moduledir) { + return kr_error(ENOMEM); + } + if (engine->moduledir) { + free(engine->moduledir); + } + engine->moduledir = new_moduledir; + + /* Use module path for including Lua scripts */ + char l_paths[MAXPATHLEN] = { 0 }; + /* Save original package.path to package._path */ + snprintf(l_paths, MAXPATHLEN - 1, + "if package._path == nil then package._path = package.path end\n" + "package.path = '%s/?.lua;%s/?/init.lua;'..package._path\n", + new_moduledir, + new_moduledir); + + int ret = l_dobytecode(engine->L, l_paths, strlen(l_paths), ""); + if (ret != 0) { + lua_pop(engine->L, 1); + return ret; + } + return 0; +} + +/** Return hostname. */ +static int l_moduledir(lua_State *L) +{ + struct engine *engine = engine_luaget(L); + if (lua_gettop(L) == 0) { + lua_pushstring(L, engine_get_moduledir(engine)); + return 1; + } + if ((lua_gettop(L) != 1) || !lua_isstring(L, 1)) { + lua_pushstring(L, "moduledir takes at most one parameter: (\"directory\")"); + lua_error(L); + } + + if (engine_set_moduledir(engine, lua_tostring(L, 1)) != 0) { + lua_pushstring(L, "setting moduledir failed"); + lua_error(L); + } + + lua_pushstring(L, engine_get_moduledir(engine)); + return 1; +} + /** Get/set context option. */ static int l_option(lua_State *L) { @@ -532,6 +597,8 @@ static int init_state(struct engine *engine) lua_setglobal(engine->L, "quit"); lua_pushcfunction(engine->L, l_hostname); lua_setglobal(engine->L, "hostname"); + lua_pushcfunction(engine->L, l_moduledir); + lua_setglobal(engine->L, "moduledir"); lua_pushcfunction(engine->L, l_verbose); lua_setglobal(engine->L, "verbose"); lua_pushcfunction(engine->L, l_option); @@ -548,8 +615,6 @@ static int init_state(struct engine *engine) lua_setglobal(engine->L, "tojson"); lua_pushcfunction(engine->L, l_map); lua_setglobal(engine->L, "map"); - lua_pushliteral(engine->L, MODULEDIR); - lua_setglobal(engine->L, "moduledir"); lua_pushlightuserdata(engine->L, engine); lua_setglobal(engine->L, "__engine"); return kr_ok(); @@ -685,21 +750,9 @@ int engine_ipc(struct engine *engine, const char *expr) } } -/* Execute byte code */ -#define l_dobytecode(L, arr, len, name) \ - (luaL_loadbuffer((L), (arr), (len), (name)) || lua_pcall((L), 0, LUA_MULTRET, 0)) -/** Load file in a sandbox environment. */ -#define l_dosandboxfile(L, filename) \ - (luaL_loadfile((L), (filename)) || engine_pcall((L), 0)) - static int engine_loadconf(struct engine *engine, const char *config_path) { - /* Use module path for including Lua scripts */ - static const char l_paths[] = "package.path = '" MODULEDIR "/?.lua;'..package.path"; - int ret = l_dobytecode(engine->L, l_paths, sizeof(l_paths) - 1, ""); - if (ret != 0) { - lua_pop(engine->L, 1); - } + int ret = 0; /* Init environment */ static const char sandbox_bytecode[] = { #include "daemon/lua/sandbox.inc" @@ -836,7 +889,7 @@ int engine_register(struct engine *engine, const char *name, const char *precede return kr_error(ENOMEM); } module->data = engine; - int ret = kr_module_load(module, name, NULL); + int ret = kr_module_load(module, name, engine->moduledir); /* Load Lua module if not a binary */ if (ret == kr_error(ENOENT)) { ret = ffimodule_register_lua(engine, module, name); diff --git a/daemon/engine.h b/daemon/engine.h index 409e40982..a4f6ab5f4 100644 --- a/daemon/engine.h +++ b/daemon/engine.h @@ -61,6 +61,7 @@ struct engine { uv_timer_t *updater; char *hostname; struct lua_State *L; + char *moduledir; }; int engine_init(struct engine *engine, knot_mm_t *pool); @@ -89,3 +90,7 @@ struct engine *engine_luaget(struct lua_State *L); /** Set/get the per engine hostname */ char *engine_get_hostname(struct engine *engine); int engine_set_hostname(struct engine *engine, const char *hostname); + +/** Set/get the per engine moduledir */ +char *engine_get_moduledir(struct engine *engine); +int engine_set_moduledir(struct engine *engine, const char *moduledir); diff --git a/daemon/main.c b/daemon/main.c index 2ebbf6ad4..6de5e5cd3 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -341,15 +341,16 @@ static void help(int argc, char *argv[]) { printf("Usage: %s [parameters] [rundir]\n", argv[0]); printf("\nParameters:\n" - " -a, --addr=[addr] Server address (default: localhost@53).\n" - " -t, --tls=[addr] Server address for TLS (default: off).\n" - " -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n" - " -T, --tlsfd=[fd] Listen using TLS on given fd (handed out by supervisor).\n" - " -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n" - " -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n" - " -f, --forks=N Start N forks sharing the configuration.\n" - " -q, --quiet Quiet output, no prompt in interactive mode.\n" - " -v, --verbose Run in verbose mode." + " -a, --addr=[addr] Server address (default: localhost@53).\n" + " -t, --tls=[addr] Server address for TLS (default: off).\n" + " -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n" + " -T, --tlsfd=[fd] Listen using TLS on given fd (handed out by supervisor).\n" + " -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n" + " -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n" + " -m, --moduledir=[path] Override the default module path (" MODULEDIR ").\n" + " -f, --forks=N Start N forks sharing the configuration.\n" + " -q, --quiet Quiet output, no prompt in interactive mode.\n" + " -v, --verbose Run in verbose mode." #ifdef NOVERBOSELOG " (Recompile without -DNOVERBOSELOG to activate.)" #endif @@ -433,6 +434,7 @@ int main(int argc, char **argv) array_t(int) tls_fd_set; array_init(tls_fd_set); char *keyfile = NULL; + char *moduledir = MODULEDIR; const char *config = NULL; int control_fd = -1; @@ -446,13 +448,14 @@ int main(int argc, char **argv) {"config", required_argument, 0, 'c'}, {"keyfile",required_argument, 0, 'k'}, {"forks",required_argument, 0, 'f'}, + {"moduledir", required_argument, 0, 'm'}, {"verbose", no_argument, 0, 'v'}, {"quiet", no_argument, 0, 'q'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; - while ((c = getopt_long(argc, argv, "a:t:S:T:c:f:k:vqVh", opts, &li)) != -1) { + while ((c = getopt_long(argc, argv, "a:t:S:T:c:f:m:k:vqVh", opts, &li)) != -1) { switch (c) { case 'a': @@ -482,6 +485,9 @@ int main(int argc, char **argv) case 'k': keyfile = optarg; break; + case 'm': + moduledir = optarg; + break; case 'v': kr_verbose_set(true); #ifdef NOVERBOSELOG @@ -636,6 +642,8 @@ int main(int argc, char **argv) goto cleanup; } + engine_set_moduledir(&engine, moduledir); + /* Block signals. */ uv_loop_t *loop = uv_default_loop(); uv_signal_t sigint, sigterm; diff --git a/lib/module.c b/lib/module.c index 6cd462365..cea899fe8 100644 --- a/lib/module.c +++ b/lib/module.c @@ -132,12 +132,8 @@ int kr_module_load(struct kr_module *module, const char *name, const char *path) /* Search for module library, use current namespace if not found. */ if (load_library(module, name, path) != 0) { - /* Expand HOME env variable, as the linker may not expand it. */ - auto_free char *local_path = kr_strcatdup(2, getenv("HOME"), "/.local/lib/kdns_modules"); - if (load_library(module, name, local_path) != 0) { - if (load_library(module, name, MODULEDIR) != 0) { - module->lib = RTLD_DEFAULT; - } + if (load_library(module, name, MODULEDIR) != 0) { + module->lib = RTLD_DEFAULT; } } -- 2.47.2