diff options
Diffstat (limited to 'client/lua-client.c')
-rw-r--r-- | client/lua-client.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/client/lua-client.c b/client/lua-client.c new file mode 100644 index 0000000..ca4365a --- /dev/null +++ b/client/lua-client.c @@ -0,0 +1,112 @@ + +#include <sys/socket.h> +#include <sys/un.h> + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#define LIBNAME "client" + +#ifndef VERSION +#define VERSION "(unknown)" +#endif + +#ifndef DEFAULT_SOCKET_PATH +#define DEFAULT_SOCKET_PATH "/var/run/privsep/root.sock" +#endif + +#define BUFSIZE 32768 + +static int pusherror(lua_State *L, const char *info) +{ + lua_pushnil(L); + if (info == NULL) + lua_pushstring(L, strerror(errno)); + else + lua_pushfstring(L, "%s: %s", info, strerror(errno)); + lua_pushinteger(L, errno); + return 3; +} + +static int Pconnect(lua_State *L) +{ + const char *socket_path = luaL_optstring(L, 1, DEFAULT_SOCKET_PATH); + struct sockaddr_un sun; + int fd, ret; + + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + strncpy(sun.sun_path, socket_path, sizeof(sun.sun_path)); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return pusherror(L, "socket"); + + if (connect(fd, (struct sockaddr *) &sun, sizeof(sun)) < 0) { + ret = pusherror(L, socket_path); + goto close_err; + } + + lua_pushinteger(L, fd); + return 1; + +close_err: + close(fd); + return ret; +} + +static int push_err_or_int(lua_State *L, ssize_t n) +{ + if (n < 0) + return pusherror(L, NULL); + lua_pushinteger(L, n); + return 1; +} + +static int Pwrite(lua_State *L) +{ + int fd = luaL_checkinteger(L, 1); + size_t len = 0; + const char *msg = luaL_checklstring(L, 2, &len); + return push_err_or_int(L, write(fd, msg, len)); +} + +static int Precv(lua_State *L) +{ + int fd = luaL_checkinteger(L, 1); + static char buf[BUFSIZE]; + ssize_t n = recv(fd, buf, sizeof(buf), 0); + if (n < 0) + return pusherror(L, NULL); + lua_pushlstring(L, buf, n); + return 1; +} + +static int Pclose(lua_State *L) +{ + int fd = luaL_checkinteger(L, 1); + return push_err_or_int(L, close(fd)); +} + +static const luaL_reg reg_client_methods[] = { + {"connect", Pconnect}, + {"write", Pwrite}, + {"recv", Precv}, + {"close", Pclose}, + {NULL, NULL}, +}; + + +LUALIB_API int luaopen_client(lua_State *L) +{ + luaL_register(L, LIBNAME, reg_client_methods); + lua_pushliteral(L, "version"); + lua_pushliteral(L, VERSION); + lua_settable(L, -3); + return 1; +} |