]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
Make the moduledir configurable at the runtime
authorOndřej Surý <ondrej@sury.org>
Tue, 23 May 2017 15:23:14 +0000 (17:23 +0200)
committerOndřej Surý <ondrej@sury.org>
Fri, 26 May 2017 11:37:31 +0000 (13:37 +0200)
daemon/engine.c
daemon/engine.h
daemon/main.c
lib/module.c

index 520cd3cd32a9ff038b75e9f8b8ebefa1b2e7904f..f6a6513a28e189b00e0a6a38294bb8339f412856 100644 (file)
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <grp.h>
 #include <pwd.h>
+#include <sys/param.h>
 #include <zscanner/scanner.h>
 
 #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);
index 409e40982329f283ebeb9053c38d0dcaf4a5560d..a4f6ab5f45d8f5f55f037c66e07b56e5561f02e9 100644 (file)
@@ -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);
index 2ebbf6ad427104cda25383a6eef2b9804bcdd6ba..6de5e5cd3a32628326213b31c113af2343ccc08d 100644 (file)
@@ -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;
index 6cd46236580688aff7f319d81c7c1437d876bc09..cea899fe87a81dedbac6d12a193f174c1aa13ce3 100644 (file)
@@ -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;
                }
        }