diff --git a/daemon/engine.c b/daemon/engine.c index f8c065731e53bfadc1099cef5e816fd034ea4de6..8b174a8096a37f398c0b20602493b0ad2515e89a 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -41,15 +41,10 @@ static int l_help(lua_State *L) static const char *help_str = "help()\n show this help\n" "quit()\n quit\n" - "modules.list()\n list modules\n" - "modules.load()\n load module\n" - "modules.unload()\n unload module\n" - "cache.open(path, max_size)\n open cache\n" - "cache.close()\n close cache\n" + "hostname()\n hostname\n" ; - puts(help_str); - /* No results */ - return 0; + lua_pushstring(L, help_str); + return 1; } /** Quit current executable. */ @@ -61,6 +56,15 @@ static int l_quit(lua_State *L) return 0; } +/** Return hostname. */ +static int l_hostname(lua_State *L) +{ + char host_str[KNOT_DNAME_MAXLEN]; + gethostname(host_str, sizeof(host_str)); + lua_pushstring(L, host_str); + return 1; +} + /** Trampoline function for module properties. */ static int l_trampoline(lua_State *L) { @@ -115,6 +119,8 @@ static int init_state(struct engine *engine) lua_setglobal(engine->L, "help"); lua_pushcfunction(engine->L, l_quit); lua_setglobal(engine->L, "quit"); + lua_pushcfunction(engine->L, l_hostname); + lua_setglobal(engine->L, "hostname"); lua_pushlightuserdata(engine->L, engine); lua_setglobal(engine->L, "__engine"); return kr_ok(); @@ -171,7 +177,7 @@ static int l_sandboxcall(lua_State *L, int argc) { #if LUA_VERSION_NUM >= 502 lua_getglobal(L, "_SANDBOX"); - lua_setupvalue(L, -2, 1); + lua_setupvalue(L, -(2 + argc), 1); #endif return lua_pcall(L, argc, LUA_MULTRET, 0); } @@ -188,6 +194,8 @@ int engine_cmd(struct engine *engine, const char *str) /* Check result. */ if (l_sandboxcall(engine->L, 1) != 0) { + fprintf(stderr, "%s\n", lua_tostring(engine->L, -1)); + lua_pop(engine->L, 1); return kr_error(EINVAL); } @@ -227,7 +235,7 @@ static int engine_loadconf(struct engine *engine) /* Evaluate */ if (ret != 0) { - fprintf(stderr, "[system] error %s\n", lua_tostring(engine->L, -1)); + fprintf(stderr, "%s\n", lua_tostring(engine->L, -1)); lua_pop(engine->L, 1); return kr_error(EINVAL); } @@ -243,7 +251,7 @@ int engine_start(struct engine *engine) return ret; } - return uv_run(uv_default_loop(), UV_RUN_DEFAULT); + return kr_ok(); } void engine_stop(struct engine *engine) diff --git a/daemon/lua/sandbox.lua b/daemon/lua/sandbox.lua index 09beab95586ff5eae6453ef41715974e116197d3..d64dd19344728d2e5c7990c396cfe43d538f69af 100644 --- a/daemon/lua/sandbox.lua +++ b/daemon/lua/sandbox.lua @@ -13,7 +13,7 @@ setmetatable(modules, { }) -- Make sandboxed environment -function make_sandbox(defined) +local function make_sandbox(defined) local __protected = { modules = true, cache = true, net = true } return setmetatable({}, { __index = defined, @@ -29,6 +29,7 @@ function make_sandbox(defined) }) end +-- Compatibility sandbox if setfenv then -- Lua 5.1 and less _G = make_sandbox(getfenv(0)) setfenv(0, _G) @@ -36,6 +37,29 @@ else -- Lua 5.2+ _SANDBOX = make_sandbox(_ENV) end +-- Interactive command evaluation +function eval_cmd(line) + -- Compatibility sandbox code loading + local function load_code(code) + if getfenv then -- Lua 5.1 + return loadstring(code) + else -- Lua 5.2+ + return load(code, nil, 't', _ENV) + end + end + local status, err, chunk + chunk, err = load_code('table_print('..line..')') + if err then + chunk, err = load_code(line) + end + if not err then + chunk() + end + if err then + print(err) + end +end + -- Pretty printing function table_print (tt, indent, done) done = done or {} @@ -57,18 +81,4 @@ function table_print (tt, indent, done) else io.write(tostring(tt) .. "\n") end -end - --- Interactive command evaluation -function eval_cmd(line) - local chunk, err = loadstring('table_print('..line..')') - if err then - chunk, err = loadstring(line) - end - if not err then - status, err = pcall(chunk) - end - if err then - print(err) - end end \ No newline at end of file diff --git a/daemon/main.c b/daemon/main.c index ef5bc3790ad5eb8c63371a1cad78bc60b7cd6fc3..1f9906f0baf642916329d645d8464b72cf7dcb8f 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -76,7 +76,7 @@ static const char *set_addr(char *addr, int *port) int main(int argc, char **argv) { - const char *addr = "127.0.0.1"; + const char *addr = NULL; int port = 53; /* Long options. */ @@ -108,12 +108,16 @@ int main(int argc, char **argv) /* Switch to rundir. */ if (optind < argc) { - ret = chdir(argv[optind]); + const char *rundir = argv[optind]; + if (access(rundir, W_OK) != 0) { + fprintf(stderr, "[system] rundir '%s': not writeable\n", rundir); + return EXIT_FAILURE; + } + ret = chdir(rundir); if (ret != 0) { - fprintf(stderr, "[system] rundir '%s': %s\n", argv[optind], strerror(errno)); + fprintf(stderr, "[system] rundir '%s': %s\n", rundir, strerror(errno)); return EXIT_FAILURE; } - printf("[system] rundir '%s'\n", argv[optind]); } /* Block signals. */ @@ -146,31 +150,39 @@ int main(int argc, char **argv) loop->data = &worker; /* Bind to sockets. */ - ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP); - if (ret != 0) { - fprintf(stderr, "[system] bind to '%s#%d' %s\n", addr, port, knot_strerror(ret)); - ret = EXIT_FAILURE; - } else { - /* Allocate TTY */ - uv_pipe_t pipe; - uv_pipe_init(loop, &pipe, 0); - uv_pipe_open(&pipe, 0); - pipe.data = &engine; + if (addr != NULL) { + ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP); + if (ret != 0) { + fprintf(stderr, "[system] bind to '%s#%d' %s\n", addr, port, knot_strerror(ret)); + ret = EXIT_FAILURE; + } + } + if (ret == 0) { /* Interactive stdin */ + uv_pipe_t pipe; if (!feof(stdin)) { - printf("[system] listening on '%s#%d'\n", addr, port); printf("[system] started in interactive mode, type 'help()'\n"); + uv_pipe_init(loop, &pipe, 0); + uv_pipe_open(&pipe, 0); + pipe.data = &engine; tty_read(NULL, 0, NULL); uv_read_start((uv_stream_t*) &pipe, tty_alloc, tty_read); } + /* Run the event loop. */ ret = engine_start(&engine); + if (ret == 0) { + ret = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + } } /* Cleanup. */ fprintf(stderr, "\n[system] quitting\n"); engine_deinit(&engine); + if (ret != 0) { + ret = EXIT_FAILURE; + } return ret; }