diff options
Diffstat (limited to 'server/lua-privsep.c')
-rw-r--r-- | server/lua-privsep.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/server/lua-privsep.c b/server/lua-privsep.c new file mode 100644 index 0000000..65dc39e --- /dev/null +++ b/server/lua-privsep.c @@ -0,0 +1,96 @@ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + + +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> + +#include "conn.h" +#include "lua-privsep.h" + +#ifndef PRIVSEP_PATH +#define PRIVSEP_PATH "./" +#endif + +static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + fprintf(stderr, "traceback\n"); + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + fprintf(stderr, "traceback: debug\n"); + lua_pop(L, 1); + return 1; + } + + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + fprintf(stderr, "traceback: traceback\n"); + lua_pop(L, 2); + return 1; + } + + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; +} + +static void lerror(lua_State *L, const char *fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + lua_close(L); + exit(EXIT_FAILURE); +} + +int call_lua(struct conn *c, const char *msg, size_t msglen) +{ + const char *retbuf; + size_t retsize; + lua_State *L = c->L; + + lua_getglobal(L, "handler"); + lua_pushlstring(L, msg, msglen); + + + if (lua_pcall(L, 1, 1, 0)) + return luaL_error(L, lua_tostring(L, -1)); + + if (!lua_isstring(L, -1)) + lerror(L, "handler function must return string\n"); + + retbuf = lua_tolstring(L, -1, &retsize); + return write(c->io.fd, retbuf, retsize); +} + +int init_lua(struct conn *c) +{ + const char *luamain = PRIVSEP_PATH "handler.lua"; + int traceback_index; + const char *retbuf; + size_t retsize; + + c->L = luaL_newstate(); + if (c == NULL) + return -1; + luaL_openlibs(c->L); + + if (luaL_loadfile(c->L, luamain) || lua_pcall(c->L, 0, 0, 0)) { + lerror(c->L, "%s: %s", luamain, lua_tostring(c->L, -1)); + lua_close(c->L); + c->L = NULL; + return -1; + } + return 0; +} + +void close_lua(struct conn *c) +{ + lua_close(c->L); + c->L = NULL; +} |