diff options
Diffstat (limited to 'src/l_util.c')
-rw-r--r-- | src/l_util.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/l_util.c b/src/l_util.c new file mode 100644 index 0000000..778c5b7 --- /dev/null +++ b/src/l_util.c @@ -0,0 +1,164 @@ +/* + * gcsd + * + * gcsd the generic command sequencer daemon can be used to serialize + * commands sent over various paralell communication channels to a + * single command output. It can be seen as a multiplexer for any + * kind of communication between a single resource and various clients + * which want to submit commands to it or query information from it. + * gcsd is written in C and Lua. The goal is to provide an easy to + * understand high level API based on Lua which can be used to + * implement the business logic of the so formed multiplexer daemon. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@spreadspace.org> + * Christian Pointner <equinox@spreadspace.org> + * + * This file is part of gcsd. + * + * gcsd 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. + * + * gcsd 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 gcsd. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lua.h> +#include <lauxlib.h> + +#include <sys/select.h> +#include <errno.h> +#include <string.h> + +#include "l_util.h" + +static int get_fd(lua_State *L) +{ + if(!lua_istable(L, -1)) + return -1; + + lua_pushstring(L, "getfd"); + lua_gettable(L, -2); + if(lua_isnil(L, -1)) { + lua_pop(L,1); + return -1; + } + lua_pushvalue(L, -2); // self + lua_call(L, 1, 1); + int fd = luaL_checkint(L, -1); + lua_pop(L, 1); + return fd; +} + +static int collect_fds(lua_State *L, int table_idx, fd_set* fds, int max_fd) +{ + FD_ZERO(fds); + int i; + for(i = 1;;i++) { + int fd; + lua_pushinteger(L, i); + lua_gettable(L, table_idx); + if(lua_isnil(L,-1)) { + lua_pop(L, 1); + break; + } + fd = get_fd(L); + if(fd >= 0) { + FD_SET(fd, fds); + max_fd = fd > max_fd ? fd : max_fd; + } + lua_pop(L,1); + } + return max_fd; +} + +static void return_fds(lua_State *L, int table_idx, fd_set* fds) +{ + lua_newtable(L); + int i, j = 1; + for(i = 1;;i++) { + int fd; + lua_pushinteger(L, i); + lua_gettable(L, table_idx); + if(lua_isnil(L,-1)) { + lua_pop(L, 1); + break; + } + fd = get_fd(L); + if(fd >= 0 && FD_ISSET(fd, fds)) { + lua_pushinteger(L, j++); + lua_insert(L, -2); + lua_settable(L, -3); + } + else + lua_pop(L,1); + } +} + +static int l_util_select(lua_State *L) +{ + if(!lua_istable(L, 1)) + luaL_error(L, "table expected as first argument"); + if(!lua_istable(L, 2)) + luaL_error(L, "table expected as second argument"); + int ms = luaL_optint(L, 3, -1); + + fd_set readables, writeables; + int max_fd = collect_fds(L, 1, &readables, 0); + max_fd = collect_fds(L, 2, &writeables, max_fd); + + struct timeval tv; + struct timeval* timeout = NULL; + if(timeout > 0) { + tv.tv_sec = 0; + tv.tv_usec = ms * 1000; + timeout = &tv; + } + int ret = select(max_fd+1, &readables, &writeables, NULL, timeout); + if(ret <= 0) { + lua_pushnil(L); + lua_pushnil(L); + if(!ret) + lua_pushstring(L, "timeout"); + else if(errno == EINTR) + lua_pushstring(L, "signal"); + else + lua_pushstring(L, strerror(errno)); // FIXXXXXME: strerror is not threadsafe!!! + return 3; + } + return_fds(L, 1, &readables); + return_fds(L, 2, &writeables); + return 2; +} + +static int l_util_exec(lua_State *L) +{ + //TODO: implement fork/exec + return 0; +} + +static int l_util_waitpid(lua_State *L) +{ + //TODO: implement waitpid + return 0; +} + +static const struct luaL_reg util_funcs [] = { + { "select", l_util_select }, + { "exec", l_util_exec }, + { "waitpid", l_util_waitpid }, + { NULL, NULL } +}; + +LUALIB_API int luaopen_util(lua_State *L) +{ + luaL_register(L, LUA_UTILLIBNAME, util_funcs); + return 1; +} |