diff options
Diffstat (limited to 'rhnop-server/l_pipe.c')
-rw-r--r-- | rhnop-server/l_pipe.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/rhnop-server/l_pipe.c b/rhnop-server/l_pipe.c new file mode 100644 index 0000000..6b769a5 --- /dev/null +++ b/rhnop-server/l_pipe.c @@ -0,0 +1,137 @@ +/* + * rhnop + * + * Copyright (C) 2011 Christian Pointner <equinox@helsinki.at> + * + * This file is part of rhnop. + * + * rhnop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * rhnop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rhnop. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lua.h> +#include <lauxlib.h> + +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include "l_pipe.h" + +static int pipefds_[2]; + +int pipe_init() +{ + return pipe(pipefds_); +} + +void pipe_close() +{ + close(pipefds_[0]); + close(pipefds_[1]); +} + +static int l_pipe_signal(lua_State *L) +{ + size_t len = 0, written = 0; + const char* data = luaL_checklstring(L, 1, &len); + len++; // also send trailing zero + + int ret = 0; + for(;;) { + ret = write(pipefds_[1], &(data[written]), len - written); + if(!ret) continue; + if(ret == -1 && (errno == EAGAIN || errno == EINTR)) continue; + + written += ret; + if(written == len) break; + + break; + } + + lua_pushinteger(L, ret); + return 1; +} + +static int l_pipe_getfd(lua_State *L) +{ + if(!lua_istable(L, -1)) + luaL_error(L, "can't retreive pipe fd"); + + lua_pushliteral(L, "fd"); + lua_gettable(L, -2); + return 1; +} + +static int l_pipe_dirty(lua_State *L) +{ + lua_pushboolean(L, 0); + return 1; +} + +static int l_pipe_getreadfd(lua_State *L) +{ + lua_newtable(L); + lua_pushliteral(L, "fd"); + lua_pushinteger(L, pipefds_[0]); + lua_settable(L, -3); + lua_pushliteral(L, "getfd"); + lua_pushcfunction(L, l_pipe_getfd); + lua_settable(L, -3); + lua_pushliteral(L, "dirty"); + lua_pushcfunction(L, l_pipe_dirty); + lua_settable(L, -3); + return 1; +} + +static int l_pipe_consume(lua_State *L) +{ + char data[17]; // 17 should be sufficient + size_t len = 0; + + int ret = 0; + for(;;) { + ret = read(pipefds_[0], &(data[len]), 1); + if(ret == 0) break; + if(ret == -1 && (errno == EAGAIN || errno == EINTR)) continue; + + if(data[len] == 0) + break; + + len += ret; + if(len >= sizeof(data)) { + ret = 0; + break; + } + } + + if(ret) + lua_pushstring(L, data); + else + lua_pushnil(L); + + return 1; +} + +static const struct luaL_reg pipe_funcs [] = { + { "signal", l_pipe_signal }, + { "getreadfd", l_pipe_getreadfd }, + { "consume", l_pipe_consume }, + { NULL, NULL } +}; + +LUALIB_API int luaopen_pipe(lua_State *L) +{ + luaL_register(L, LUA_PIPELIBNAME, pipe_funcs); + return 1; +} |