Commit 2f81b111 authored by Ondřej Surý's avatar Ondřej Surý

Make the moduledir configurable at the runtime

parent 15db5051
......@@ -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);
......
......@@ -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);
......@@ -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;
......
......@@ -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;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment