#include <unistd.h>
#include <grp.h>
#include <pwd.h>
+#include <sys/param.h>
#include <zscanner/scanner.h>
#include "daemon/engine.h"
/* 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.
*/
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)
{
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);
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();
}
}
-/* 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"
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);
{
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
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;
{"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':
case 'k':
keyfile = optarg;
break;
+ case 'm':
+ moduledir = optarg;
+ break;
case 'v':
kr_verbose_set(true);
#ifdef NOVERBOSELOG
goto cleanup;
}
+ engine_set_moduledir(&engine, moduledir);
+
/* Block signals. */
uv_loop_t *loop = uv_default_loop();
uv_signal_t sigint, sigterm;