summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2010-11-18 21:51:44 +0000
committerChristian Pointner <equinox@spreadspace.org>2010-11-18 21:51:44 +0000
commit5d6eb48f9560d352962b56d8f629157d6cacdea3 (patch)
treec141584458bb8a143685979fd583c5c57f01cd30
parentrawio: fixed return value at read (diff)
added util module with own select
core doesn't depend on lua sockets anymore cleaned up at rawio git-svn-id: https://svn.spreadspace.org/gcsd/trunk@39 ac14a137-c7f1-4531-abe0-07747231d213
-rw-r--r--src/Makefile1
-rw-r--r--src/gcsd.c2
-rw-r--r--src/l_rawio.c10
-rw-r--r--src/l_util.c164
-rw-r--r--src/l_util.h41
-rw-r--r--src/main_loop.lua13
-rw-r--r--src/module_list.lua2
7 files changed, 223 insertions, 10 deletions
diff --git a/src/Makefile b/src/Makefile
index 0bb1ff4..603b3d2 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -45,6 +45,7 @@ C_OBJS := log.o \
sig_handler.o \
l_sig_handler.o \
l_rawio.o \
+ l_util.o \
gcsd.o
C_SRCS := $(C_OBJS:%.o=%.c)
diff --git a/src/gcsd.c b/src/gcsd.c
index c6d3e7c..d25c13a 100644
--- a/src/gcsd.c
+++ b/src/gcsd.c
@@ -43,6 +43,7 @@
#include "string_list.h"
#include "log.h"
#include "l_rawio.h"
+#include "l_util.h"
#include "l_log.h"
#include "l_sig_handler.h"
@@ -62,6 +63,7 @@ static const luaL_Reg gcsd_lualibs[] = {
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_RAWIOLIBNAME, luaopen_rawio},
+ {LUA_UTILLIBNAME, luaopen_util},
{LUA_LOGLIBNAME, luaopen_log},
{LUA_SIGNALLIBNAME, luaopen_signal},
{NULL, NULL}
diff --git a/src/l_rawio.c b/src/l_rawio.c
index 889aeb7..779d6ae 100644
--- a/src/l_rawio.c
+++ b/src/l_rawio.c
@@ -62,7 +62,7 @@ static int l_rawio_open(lua_State *L)
static int l_rawio_setnonblock(lua_State *L)
{
- int fd = luaL_checkinteger(L,1);
+ int fd = luaL_checkint(L,1);
int ret = fcntl(fd, F_SETFL, O_NONBLOCK);
if(ret == -1) {
@@ -77,7 +77,7 @@ static int l_rawio_setnonblock(lua_State *L)
static int l_rawio_write(lua_State *L)
{
- int fd = luaL_checkinteger(L,1);
+ int fd = luaL_checkint(L,1);
size_t len = 0;
const char* data = luaL_checklstring(L, 2, &len);
@@ -95,8 +95,8 @@ static int l_rawio_write(lua_State *L)
static int l_rawio_read(lua_State *L)
{
- int fd = luaL_checkinteger(L,1);
- size_t len = luaL_checkinteger(L,2);
+ int fd = luaL_checkint(L,1);
+ size_t len = luaL_checkint(L,2);
char* data = malloc(len);
if(!data) {
lua_pushnil(L);
@@ -120,7 +120,7 @@ static int l_rawio_read(lua_State *L)
static int l_rawio_close(lua_State *L)
{
- close(luaL_checkinteger(L,1));
+ close(luaL_checkint(L,1));
return 0;
}
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;
+}
diff --git a/src/l_util.h b/src/l_util.h
new file mode 100644
index 0000000..c0b558a
--- /dev/null
+++ b/src/l_util.h
@@ -0,0 +1,41 @@
+/*
+ * 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/>.
+ */
+
+#ifndef GCSD_l_util_h_INCLUDED
+#define GCSD_l_util_h_INCLUDED
+
+#include <lua.h>
+
+#define LUA_UTILLIBNAME "util"
+LUALIB_API int luaopen_util(lua_State *L);
+
+#endif
diff --git a/src/main_loop.lua b/src/main_loop.lua
index ec68b70..c310cdb 100644
--- a/src/main_loop.lua
+++ b/src/main_loop.lua
@@ -30,7 +30,6 @@
-- along with gcsd. If not, see <http://www.gnu.org/licenses/>.
--
-local socket = require("socket")
local defines = require("defines")
function get_readables()
@@ -83,10 +82,16 @@ function main_loop(opt)
end
while return_value == 0 do
- local readable, writeable, err = socket.select({ sig, unpack(get_readables()) }, get_writeables())
+ local readable, writeable, err = util.select({ sig, unpack(get_readables()) }, get_writeables(), 10)
if(err) then
- log.printf(log.ERROR, "select returned with error: %s", err)
- return_value = -1
+ if(err == "timeout") then
+ -- TODO: handle timeouts
+ elseif(err == "signal") then
+ -- ignore this
+ else
+ log.printf(log.ERROR, "select returned with error: %s", err)
+ return_value = -1
+ end
else
for _, reader in ipairs(readable) do
if(reader == sig) then
diff --git a/src/module_list.lua b/src/module_list.lua
index 89d4920..5b35fe9 100644
--- a/src/module_list.lua
+++ b/src/module_list.lua
@@ -43,7 +43,7 @@ function mt.__index(table, key)
log.printf(log.DEBUG, "load module class: %s", key)
local old_path = package.path
- package.path = "./modules/?.lua"
+ package.path = package.path .. ";./modules/?.lua"
value = require(key)
package.path = old_path