summaryrefslogtreecommitdiff
path: root/src/l_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/l_util.c')
-rw-r--r--src/l_util.c164
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;
+}