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;
 }