diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | l_cmd.c | 140 | ||||
-rw-r--r-- | l_cmd.h | 32 | ||||
-rw-r--r-- | luaclient.c | 13 | ||||
-rw-r--r-- | mode-leds.lua | 23 | ||||
-rw-r--r-- | switchctl.c | 29 | ||||
-rw-r--r-- | utils.c | 30 | ||||
-rw-r--r-- | utils.h | 1 |
8 files changed, 231 insertions, 42 deletions
@@ -33,7 +33,7 @@ COMMONOBJ := log.o \ sig_handler.o \ string_list.o \ key_value_storage.o \ - utils.o \ + utils.o SWITCHCTLOBJ := command_queue.o \ client_list.o \ @@ -47,11 +47,12 @@ STDIOCLIENTOBJ := opt-stdioclient.o \ stdioclient.o HEARTBEATCLIENTOBJ := opt-heartbeatclient.o \ - heartbeatclient.o + heartbeatclient.o LUACLIENTOBJ := opt-luaclient.o \ l_log.o \ l_sig_handler.o \ + l_cmd.o \ luaclient.o @@ -0,0 +1,140 @@ +/* + * rhctl + * + * Copyright (C) 2009 Christian Pointner <equinox@spreadspace.org> + * + * 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 <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" + +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, 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) +{ + return 0; +} + +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; +} @@ -0,0 +1,32 @@ +/* + * rhctl + * + * Copyright (C) 2009 Christian Pointner <equinox@spreadspace.org> + * + * 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/>. + */ + +#ifndef RHCTL_l_cmd_h_INCLUDED +#define RHCTL_l_cmd_h_INCLUDED + +#include <lua.h> + +extern int cmd_fd; + +#define LUA_CMDLIBNAME "cmd" +LUALIB_API int luaopen_cmd(lua_State *L); + +#endif diff --git a/luaclient.c b/luaclient.c index f77dbe0..58aaa7e 100644 --- a/luaclient.c +++ b/luaclient.c @@ -32,6 +32,7 @@ #include "l_log.h" #include "l_sig_handler.h" +#include "l_cmd.h" #include "log.h" #include "options.h" @@ -39,10 +40,6 @@ #include "daemon.h" #include "utils.h" -int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - return 0; -} #define LUA_MAIN_LOOP_FUNC "main_loop" @@ -52,8 +49,9 @@ static const luaL_Reg anylike_lualibs[] = { {LUA_TABLIBNAME, luaopen_table}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, - {LUA_SIGNALLIBNAME, luaopen_signal}, {LUA_LOGLIBNAME, luaopen_log}, + {LUA_SIGNALLIBNAME, luaopen_signal}, + {LUA_CMDLIBNAME, luaopen_cmd}, {NULL, NULL} }; @@ -96,7 +94,7 @@ int call_main_loop(lua_State* L, int cmd_fd, options_t* opt) { lua_getglobal(L, LUA_MAIN_LOOP_FUNC); if(!lua_isfunction(L, -1)) { - log_printf(ERROR, "there is no function '%s' inside the load file", LUA_MAIN_LOOP_FUNC); + log_printf(ERROR, "there is no function '%s' inside the loaded file", LUA_MAIN_LOOP_FUNC); return -1; }; @@ -231,7 +229,8 @@ int main(int argc, char* argv[]) fclose(pid_file); } - int cmd_fd = connect_command_socket(opt.command_sock_); + // extern global variable defined in l_cmd.c + cmd_fd = connect_command_socket(opt.command_sock_); if(cmd_fd < 0) { options_clear(&opt); log_close(); diff --git a/mode-leds.lua b/mode-leds.lua index 51568f8..1b43184 100644 --- a/mode-leds.lua +++ b/mode-leds.lua @@ -21,14 +21,20 @@ socket = require("socket") +function process_cmd(message) + log.printf(log.DEBUG, "received message: '%s'", message) + + return 0 +end + function main_loop(opt) log.printf(log.NOTICE, "main_loop started") local sig = signal.init() - + local cmdfd = cmd.init() local return_value = 0 while return_value == 0 do - local readable, _, err = socket.select({ sig }, nil) + local readable, _, err = socket.select({ sig , cmdfd }, nil) if(err) then log.printf(log.ERROR, "select returned with error: %s", err) return_value = -1 @@ -37,6 +43,19 @@ function main_loop(opt) if(input == sig) then return_value = signal.handle() if(return_value == 1) then break end + else + if(input == cmdfd) then + return_value = cmd.recv_data(process_cmd) + if(return_value == 2) then + log.printf(log.ERROR, "connection to server lost, exitting") + return_value = -1 + end + if(return_value ~= 0) then break end + else + log.printf(log.ERROR, "select returned invalid handle??") + return_value = -1 + break; + end end end end diff --git a/switchctl.c b/switchctl.c index 9b704bb..59f7e8d 100644 --- a/switchctl.c +++ b/switchctl.c @@ -559,6 +559,35 @@ int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, op return 0; } +int nonblock_recvline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst, options_t* opt) +{ + int ret = 0; + for(;;) { + ret = recv(fd, &buffer->buf[buffer->offset], 1, 0); + if(!ret) + return 2; + if(ret == -1 && errno == EAGAIN) + return 0; + else if(ret < 0) + break; + + if(buffer->buf[buffer->offset] == '\n') { + buffer->buf[buffer->offset] = 0; + ret = process_cmd(buffer->buf, fd, cmd_q, client_lst, opt); + buffer->offset = 0; + break; + } + + buffer->offset++; + if(buffer->offset >= sizeof(buffer->buf)) { + log_printf(DEBUG, "string too long (fd=%d)", fd); + buffer->offset = 0; + return 0; + } + } + + return ret; +} #define SEND_TO_LISTENER(STRING, LEN, FLAG) \ if(!strncmp(buffer->buf, STRING, LEN)) { \ @@ -110,36 +110,6 @@ int send_string(int fd, const char* string) return ret; } -int nonblock_recvline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst, options_t* opt) -{ - int ret = 0; - for(;;) { - ret = recv(fd, &buffer->buf[buffer->offset], 1, 0); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - else if(ret < 0) - break; - - if(buffer->buf[buffer->offset] == '\n') { - buffer->buf[buffer->offset] = 0; - ret = process_cmd(buffer->buf, fd, cmd_q, client_lst, opt); - buffer->offset = 0; - break; - } - - buffer->offset++; - if(buffer->offset >= sizeof(buffer->buf)) { - log_printf(DEBUG, "string too long (fd=%d)", fd); - buffer->offset = 0; - return 0; - } - } - - return ret; -} - int setup_tty(int fd, speed_t speed) { struct termios tmio; @@ -30,7 +30,6 @@ int init_command_socket(const char* path); int connect_command_socket(const char* path); int send_string(int fd, const char* string); -int nonblock_recvline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst, options_t* opt); int setup_tty(int fd, speed_t speed); #endif |