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