diff options
Diffstat (limited to 'src/l_cmd.c')
-rw-r--r-- | src/l_cmd.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/l_cmd.c b/src/l_cmd.c new file mode 100644 index 0000000..86bc872 --- /dev/null +++ b/src/l_cmd.c @@ -0,0 +1,152 @@ +/* + * rhctl + * + * Copyright (C) 2009-2014 Christian Pointner <equinox@helsinki.at> + * + * This file is part of rhctl. + * + * rhctl 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. + * + * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lua.h> +#include <lauxlib.h> + +#include <unistd.h> +#include <sys/socket.h> +#include <errno.h> + +#include "datatypes.h" + +#include "l_cmd.h" + +#include "options.h" +#include "command_queue.h" +#include "client_list.h" +#include "log.h" +#include "utils.h" + +int cmd_fd; +read_buffer_t cmd_buffer; + +static int l_cmd_getfd(lua_State *L) +{ + if(!lua_istable(L, -1)) + luaL_error(L, "can't retreive signal fd"); + + lua_pushliteral(L, "fd"); + lua_gettable(L, -2); + return 1; +} + +static int l_cmd_dirty(lua_State *L) +{ + lua_pushboolean(L, 0); + return 1; +} + +static int l_cmd_init(lua_State *L) +{ + lua_newtable(L); + lua_pushliteral(L, "fd"); + lua_pushinteger(L, cmd_fd); + lua_settable(L, -3); + lua_pushliteral(L, "getfd"); + lua_pushcfunction(L, l_cmd_getfd); + lua_settable(L, -3); + lua_pushliteral(L, "dirty"); + lua_pushcfunction(L, l_cmd_dirty); + lua_settable(L, -3); + return 1; +} + +// gets called by nonblock_recvline for every complete message +static int cmd_recv_data(lua_State* L) +{ + int ret = 0; + for(;;) { + ret = recv(cmd_fd, &cmd_buffer.buf[cmd_buffer.offset], 1, 0); + if(!ret) + return 2; + if(ret == -1 && errno == EAGAIN) + return 0; + else if(ret < 0) + break; + + if(cmd_buffer.buf[cmd_buffer.offset] == '\n') { + cmd_buffer.buf[cmd_buffer.offset] = 0; + + lua_pushstring(L, (char *)(cmd_buffer.buf)); + + ret = lua_pcall(L, 1, 1, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: log_printf(ERROR, "lua_pcall(cmd_callback) runtime error: %s", err_str); break; + case LUA_ERRMEM: log_printf(ERROR, "lua_pcall(cmd_callback) malloc error: %s", err_str); break; + case LUA_ERRERR: log_printf(ERROR, "lua_pcall(cmd_callback) error at error handler function: %s", err_str); break; + } + return -1; + } + + ret = lua_tointeger(L, 1); + cmd_buffer.offset = 0; + break; + } + + cmd_buffer.offset++; + if(cmd_buffer.offset >= sizeof(cmd_buffer.buf)) { + log_printf(DEBUG, "string too long cmd_fd"); + cmd_buffer.offset = 0; + return 0; + } + } + + return ret; +} + +static int l_cmd_recv_data(lua_State* L) +{ + int ret = cmd_recv_data(L); + lua_pushinteger(L, ret); + return 1; +} + +static int l_cmd_send_string(lua_State* L) +{ + int ret = send_string(cmd_fd, luaL_checkstring(L,1)); + if (ret > 0) + do { + ret = write(cmd_fd, "\n", 1); + } while(!ret || (ret == -1 && errno == EINTR)); + + if(ret > 0) + ret = 0; + + lua_pushinteger(L, ret); + return 1; +} + +static const struct luaL_reg cmd_funcs [] = { + { "init", l_cmd_init }, + { "recv_data", l_cmd_recv_data }, + { "send_string", l_cmd_send_string }, + { NULL, NULL } +}; + + +LUALIB_API int luaopen_cmd(lua_State *L) +{ + luaL_register(L, LUA_CMDLIBNAME, cmd_funcs); + return 1; +} |