/* * rhnop * * Copyright (C) 2011-2016 Christian Pointner * * 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 . */ #include #include #include #include #include #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) { #if LUA_VERSION_NUM > 501 lua_newtable(L); luaL_setfuncs(L, pipe_funcs, 0); lua_pushvalue(L, -1); lua_setglobal(L, LUA_PIPELIBNAME); #else luaL_register(L, LUA_PIPELIBNAME, pipe_funcs); #endif return 1; }