diff options
author | Christian Pointner <equinox@helsinki.at> | 2010-01-11 20:37:13 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2010-01-11 20:37:13 (GMT) |
commit | d035636d833c393f86eb4eacb5c5934c94eb1a06 (patch) | |
tree | 3b4c7e7933878d0a0f47e11bbd2edf075801969c | |
parent | 16797549c7788b05583f241e5c788a666debf6d0 (diff) |
added luaclient
-rw-r--r-- | Makefile | 19 | ||||
-rwxr-xr-x | configure | 80 | ||||
-rw-r--r-- | l_log.c | 120 | ||||
-rw-r--r-- | l_log.h | 40 | ||||
-rw-r--r-- | l_sig_handler.c | 99 | ||||
-rw-r--r-- | l_sig_handler.h | 40 | ||||
-rw-r--r-- | luaclient.c | 256 | ||||
-rw-r--r-- | mode-leds.lua | 47 | ||||
-rw-r--r-- | options.c | 78 | ||||
-rw-r--r-- | options.h | 10 |
10 files changed, 786 insertions, 3 deletions
@@ -27,6 +27,7 @@ EXE_SWITCHCTL := switchctl EXE_SERIALCLIENT := serialclient EXE_STDIOCLIENT := stdioclient EXE_HEARTBEATCLIENT := heartbeatclient +EXE_LUACLIENT := luaclient COMMONOBJ := log.o \ sig_handler.o \ @@ -48,12 +49,17 @@ STDIOCLIENTOBJ := opt-stdioclient.o \ HEARTBEATCLIENTOBJ := opt-heartbeatclient.o \ heartbeatclient.o +LUACLIENTOBJ := opt-luaclient.o \ + l_log.o \ + l_sig_handler.o \ + luaclient.o -SRC := $(COMMONOBJ:%.o=%.c) $(SWITCHCTLOBJ:%.o=%.c) $(SERIALCLIENTOBJ:%.o=%.c) $(STDIOCLIENTOBJ:%.o=%.c) $(HEARTBEATCLIENTOBJ:%.o=%.c) options.c + +SRC := $(COMMONOBJ:%.o=%.c) $(SWITCHCTLOBJ:%.o=%.c) $(SERIALCLIENTOBJ:%.o=%.c) $(STDIOCLIENTOBJ:%.o=%.c) $(HEARTBEATCLIENTOBJ:%.o=%.c) $(LUACLIENTOBJ:%.o=%.c) options.c .PHONY: clean distclean -all: $(EXE_SWITCHCTL) $(EXE_SERIALCLIENT) $(EXE_STDIOCLIENT) $(EXE_HEARTBEATCLIENT) +all: $(EXE_SWITCHCTL) $(EXE_SERIALCLIENT) $(EXE_STDIOCLIENT) $(EXE_HEARTBEATCLIENT) $(EXE_LUACLIENT) %.d: %.c @set -e; rm -f $@; \ @@ -77,6 +83,9 @@ $(EXE_STDIOCLIENT): $(COMMONOBJ) $(STDIOCLIENTOBJ) $(EXE_HEARTBEATCLIENT): $(COMMONOBJ) $(HEARTBEATCLIENTOBJ) $(CC) $(COMMONOBJ) $(HEARTBEATCLIENTOBJ) -o $@ $(LDFLAGS) +$(EXE_LUACLIENT): $(COMMONOBJ) $(LUACLIENTOBJ) + $(CC) $(COMMONOBJ) $(LUACLIENTOBJ) -o $@ $(LDFLAGS) $(LUA_LDFLAGS) + opt-switchctl.o: options.c $(CC) $(CFLAGS) -DOPT_SWITCHCTL -o $@ -c $< @@ -89,6 +98,9 @@ opt-stdioclient.o: options.c opt-heartbeatclient.o: options.c $(CC) $(CFLAGS) -DOPT_HEARTBEATCLIENT -o $@ -c $< +opt-luaclient.o: options.c + $(CC) $(CFLAGS) -DOPT_LUACLIENT -o $@ -c $< + %.o: %.c $(CC) $(CFLAGS) -c $< @@ -105,4 +117,5 @@ clean: rm -f $(EXE_SWITCHCTL) rm -f $(EXE_SERIALCLIENT) rm -f $(EXE_STDIOCLIENT) - rm -f $(EXE_HEARTBEATCLIENT)
\ No newline at end of file + rm -f $(EXE_HEARTBEATCLIENT) + rm -f $(EXE_LUACLIENT)
\ No newline at end of file @@ -26,9 +26,15 @@ TARGET=`uname -s` CFLAGS='-g -O2' LDFLAGS='-g -Wall -O2' +LUA_LDFLAGS='-lm' +LUA_DIR='' +LUA='' +LUAC='' + print_usage() { echo "configure --help print this" echo " --target=<TARGET> build target i.e. Linux (default: autodetect)" + echo " --with-lua=<DIR> use this lua tree instead of system default" } for arg @@ -37,6 +43,9 @@ do --target=*) TARGET=${arg#--target=} ;; + --with-lua=*) + LUA_DIR=${arg#--with-lua=} + ;; --help) print_usage exit 0 @@ -53,6 +62,7 @@ rm -f include.mk case $TARGET in Linux) echo "Linux specific build options" + LUA_LDFLAGS=$LUA_LDFLAGS' -ldl' ;; OpenBSD|FreeBSD|NetBSD) echo "BSD specific build options" @@ -65,6 +75,73 @@ case $TARGET in ;; esac +test_lua_version() +{ + LUA_VERSION=`cat $1 | grep "#define LUA_VERSION[ ]" | cut -f2- | tr -d '"' | sed -e 's/Lua \([0-9][0-9.]*\)/\1/'` + LUA_VERSION_NUM=`cat $1 | grep "#define LUA_VERSION_NUM" | awk '{ print $3 }'` + LUA_RELEASE=`cat $1 | grep "#define LUA_RELEASE[ ]" | cut -f2-` + + if [ $LUA_VERSION_NUM -ge 501 ]; then + return 1; + else + return 0; + fi +} + +if [ -z "$LUA_DIR" ]; then + for prefix in /usr /usr/local; do + if [ -e $prefix/include/lua.h ]; then + test_lua_version $prefix/include/lua.h + if [ $? -eq 1 ]; then + echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $prefix/include" + CFLAGS="$CFLAGS -I$prefix/include" + LUA_LDFLAGS="$LUA_LDFLAGS -L$prefix/lib -llua" + LUA=$prefix/lua + LUAC=$prefix/luac + break + fi + else + for dir in `ls -d $prefix/include/lua* 2> /dev/null`; do + if [ -e $dir/lua.h ]; then + test_lua_version $dir/lua.h + if [ $? -eq 1 ]; then + echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $dir" + CFLAGS="$CFLAGS -I$dir" + if [ -x "$prefix/bin/lua$LUA_VERSION" ]; then + LUA_LDFLAGS="$LUA_LDFLAGS -L$prefix/lib -llua$LUA_VERSION" + LUA=$prefix/bin/lua$LUA_VERSION + LUAC=$prefix/bin/luac$LUA_VERSION + elif [ -x "$prefix/bin/lua-$LUA_VERSION" ]; then + LUA_LDFLAGS="$LUA_LDFLAGS -L$prefix/lib -llua-$LUA_VERSION" + LUA=$prefix/bin/lua-$LUA_VERSION + LUAC=$prefix/bin/luac-$LUA_VERSION + else + echo "ERROR: found lua.h at $dir/lua.h but no matching lua and luac" + return 1 + fi + break + fi + fi + done + if [ -n "$LUAC" ]; then + break + fi + fi + done + + if [ -z "$LUAC" ]; then + echo "ERROR: no suitable lua found .. please install lua 5.1 or higher or use --with-lua" + return 1 + fi + +else + CFLAGS="$CFLAGS -I$LUA_DIR/include" + LUA_LDFLAGS="$LUA_LDFLAGS $LUA_DIR/lib/liblua.a" + LUA=$LUA_DIR/bin/lua + LUAC=$LUA_DIR/bin/luac +fi + + cat >> include.mk <<EOF # this file was created automatically # do not edit this file directly @@ -74,6 +151,9 @@ TARGET := $TARGET CC := gcc CFLAGS := $CFLAGS LDFLAGS := $LDFLAGS +LUA_LDFLAGS := $LUA_LDFLAGS +LUA := $LUA +LUAC := $LUAC EOF exit 0 @@ -0,0 +1,120 @@ +/* + * anylike + * + * anylike is an IKEv2 Implementation written in Lua and C. It's main + * design goal is to provide anytun and uanytun or any other SATP + * implementation with a key exchange mechanism but it should also be + * possible to use anylike as key exchange daemon for IPSec security + * associations. The use of Lua guarantees that anylike is easily + * portable to many platforms including very small ones like wireless + * routers. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@anylike.org> + * Christian Pointner <equinox@anylike.org> + * + * This file is part of anylike. + * + * anylike 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. + * + * anylike 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 anylike. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lua.h> +#include <lauxlib.h> + +#include <stdlib.h> + +#include "datatypes.h" +#include "log.h" + +#include "l_log.h" + +static int l_log_init(lua_State *L) +{ + log_init(); + return 0; +} + +static int l_log_close(lua_State *L) +{ + log_close(); + return 0; +} + +static int l_log_add_target(lua_State *L) +{ + int ret = log_add_target(luaL_checkstring(L,1)); + if(ret) { + lua_pushboolean(L, 0); + switch(ret) { + case -2: lua_pushstring(L, "memory error at log_add_target"); break; + case -3: lua_pushstring(L, "unknown log target"); break; + case -4: lua_pushstring(L, "this log target is only allowed once"); break; + default: lua_pushstring(L, "syntax error"); break; + } + return 2; + } + + lua_pushboolean(L, 1); + return 1; +} + +static int l_log_printf(lua_State *L) +{ + int numargs = lua_gettop(L); + if(numargs < 2) + return luaL_error(L, "log.printf too few arguments"); + + if(numargs > 2) { + lua_getglobal(L, "string"); + lua_pushliteral(L, "format"); + lua_gettable(L, -2); + lua_insert(L, 2); + lua_remove(L, -1); + lua_call(L, numargs - 1, 1); + } + + log_prio_t prio = luaL_checkint(L,1); + log_printf(prio, "%s", luaL_checkstring(L, 2)); + return 0; +} + +static const struct luaL_reg log_funcs [] = { + { "init", l_log_init }, + { "close", l_log_close }, + { "add_target", l_log_add_target }, + { "printf", l_log_printf }, + { NULL, NULL } +}; + + +LUALIB_API int luaopen_log(lua_State *L) +{ + luaL_register(L, LUA_LOGLIBNAME, log_funcs); + lua_pushliteral(L, "ERROR"); + lua_pushinteger(L, ERROR); + lua_settable(L, -3); + lua_pushliteral(L, "WARNING"); + lua_pushinteger(L, WARNING); + lua_settable(L, -3); + lua_pushliteral(L, "NOTICE"); + lua_pushinteger(L, NOTICE); + lua_settable(L, -3); + lua_pushliteral(L, "INFO"); + lua_pushinteger(L, INFO); + lua_settable(L, -3); + lua_pushliteral(L, "DEBUG"); + lua_pushinteger(L, DEBUG); + lua_settable(L, -3); + return 1; +} @@ -0,0 +1,40 @@ +/* + * anylike + * + * anylike is an IKEv2 Implementation written in Lua and C. It's main + * design goal is to provide anytun and uanytun or any other SATP + * implementation with a key exchange mechanism but it should also be + * possible to use anylike as key exchange daemon for IPSec security + * associations. The use of Lua guarantees that anylike is easily + * portable to many platforms including very small ones like wireless + * routers. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@anylike.org> + * Christian Pointner <equinox@anylike.org> + * + * This file is part of anylike. + * + * anylike 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. + * + * anylike 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 anylike. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ANYLIKE_l_log_h_INCLUDED +#define ANYLIKE_l_log_h_INCLUDED + +#include <lua.h> + +#define LUA_LOGLIBNAME "log" +LUALIB_API int luaopen_log(lua_State *L); + +#endif diff --git a/l_sig_handler.c b/l_sig_handler.c new file mode 100644 index 0000000..0bdcffc --- /dev/null +++ b/l_sig_handler.c @@ -0,0 +1,99 @@ +/* + * anylike + * + * anylike is an IKEv2 Implementation written in Lua and C. It's main + * design goal is to provide anytun and uanytun or any other SATP + * implementation with a key exchange mechanism but it should also be + * possible to use anylike as key exchange daemon for IPSec security + * associations. The use of Lua guarantees that anylike is easily + * portable to many platforms including very small ones like wireless + * routers. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@anylike.org> + * Christian Pointner <equinox@anylike.org> + * + * This file is part of anylike. + * + * anylike 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. + * + * anylike 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 anylike. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lua.h> +#include <lauxlib.h> + +#include "sig_handler.h" + +#include "l_sig_handler.h" + +static int l_signal_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_signal_dirty(lua_State *L) +{ + lua_pushboolean(L, 0); + return 1; +} + +static int l_signal_init(lua_State *L) +{ + int sig_fd = signal_init(); + if(sig_fd < 0) + luaL_error(L, "error at signal init"); + + lua_newtable(L); + lua_pushliteral(L, "fd"); + lua_pushinteger(L, sig_fd); + lua_settable(L, -3); + lua_pushliteral(L, "getfd"); + lua_pushcfunction(L, l_signal_getfd); + lua_settable(L, -3); + lua_pushliteral(L, "dirty"); + lua_pushcfunction(L, l_signal_dirty); + lua_settable(L, -3); + return 1; +} + +static int l_signal_stop(lua_State *L) +{ + signal_stop(); + return 0; +} + +static int l_signal_handle(lua_State *L) +{ + int ret = signal_handle(); + lua_pushinteger(L, ret); + return 1; +} + +static const struct luaL_reg signal_funcs [] = { + { "init", l_signal_init }, + { "stop", l_signal_stop }, + { "handle", l_signal_handle }, + { NULL, NULL } +}; + + +LUALIB_API int luaopen_signal(lua_State *L) +{ + luaL_register(L, LUA_SIGNALLIBNAME, signal_funcs); + return 1; +} diff --git a/l_sig_handler.h b/l_sig_handler.h new file mode 100644 index 0000000..06a5f75 --- /dev/null +++ b/l_sig_handler.h @@ -0,0 +1,40 @@ +/* + * anylike + * + * anylike is an IKEv2 Implementation written in Lua and C. It's main + * design goal is to provide anytun and uanytun or any other SATP + * implementation with a key exchange mechanism but it should also be + * possible to use anylike as key exchange daemon for IPSec security + * associations. The use of Lua guarantees that anylike is easily + * portable to many platforms including very small ones like wireless + * routers. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@anylike.org> + * Christian Pointner <equinox@anylike.org> + * + * This file is part of anylike. + * + * anylike 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. + * + * anylike 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 anylike. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ANYLIKE_l_signal_handler_h_INCLUDED +#define ANYLIKE_l_signal_handler_h_INCLUDED + +#include <lua.h> + +#define LUA_SIGNALLIBNAME "signal" +LUALIB_API int luaopen_signal(lua_State *L); + +#endif diff --git a/luaclient.c b/luaclient.c new file mode 100644 index 0000000..f77dbe0 --- /dev/null +++ b/luaclient.c @@ -0,0 +1,256 @@ +/* + * 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 "datatypes.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#include "l_log.h" +#include "l_sig_handler.h" + +#include "log.h" +#include "options.h" + +#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" + +static const luaL_Reg anylike_lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_SIGNALLIBNAME, luaopen_signal}, + {LUA_LOGLIBNAME, luaopen_log}, + {NULL, NULL} +}; + +int init_main_loop(lua_State *L, const char* filename) +{ + const luaL_Reg *lib = anylike_lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } + + int ret = luaL_loadfile(L, filename); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRSYNTAX: log_printf(ERROR, "luaL_loadfile(%s) syntax error: %s", filename, err_str); break; + case LUA_ERRMEM: log_printf(ERROR, "luaL_loadfile(%s) malloc error: %s", filename, err_str); break; + case LUA_ERRFILE: log_printf(ERROR, "luaL_loadfile(%s) file access error: %s", filename, err_str); break; + default: log_printf(ERROR, "luaL_loadfile(%s) unknown error: %s", filename, err_str); break; + } + return -1; + } + + ret = lua_pcall(L, 0, 0, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: log_printf(ERROR, "lua_pcall() runtime error: %s", err_str); break; + case LUA_ERRMEM: log_printf(ERROR, "lua_pcall() malloc error: %s", err_str); break; + case LUA_ERRERR: log_printf(ERROR, "lua_pcall() error at error handler function: %s", err_str); break; + } + return -1; + } + + return 0; +} + +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); + return -1; + }; + + options_lua_push(opt, L); + + int ret = lua_pcall(L, 1, LUA_MULTRET, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: log_printf(ERROR, "lua_pcall(%s) runtime error: %s", LUA_MAIN_LOOP_FUNC, err_str); break; + case LUA_ERRMEM: log_printf(ERROR, "lua_pcall(%s) malloc error: %s", LUA_MAIN_LOOP_FUNC, err_str); break; + case LUA_ERRERR: log_printf(ERROR, "lua_pcall(%s) error at error handler function: %s", LUA_MAIN_LOOP_FUNC, err_str); break; + } + return -1; + } + + int n = lua_gettop(L); + log_printf(DEBUG, "%s returned %d values", LUA_MAIN_LOOP_FUNC, n); + int i; + for (i = 1; i <= n; i++) + log_printf(DEBUG, "return value [%d] = '%s'", i, luaL_checkstring(L, i)); + + ret = lua_tointeger(L, 1); + return ret; +} + +int main_loop(int cmd_fd, options_t* opt) +{ + lua_State *L; + L = luaL_newstate(); + if(!L) { + log_printf(ERROR, "error creating lua state"); + return -1; + } + + int ret = init_main_loop(L, opt->lua_file_); + if(!ret) + ret = call_main_loop(L, cmd_fd, opt); + + lua_close(L); + return ret; +} + +int main(int argc, char* argv[]) +{ + log_init(); + + options_t opt; + int ret = options_parse(&opt, argc, argv); + if(ret) { + if(ret > 0) { + fprintf(stderr, "syntax error near: %s\n\n", argv[ret]); + } + if(ret == -2) { + fprintf(stderr, "memory error on options_parse, exiting\n"); + } + + if(ret != -2) + options_print_usage(); + + options_clear(&opt); + log_close(); + exit(ret); + } + string_list_element_t* tmp = opt.log_targets_.first_; + if(!tmp) { + log_add_target("syslog:3,luaclient,daemon"); + } + else { + while(tmp) { + ret = log_add_target(tmp->string_); + if(ret) { + switch(ret) { + case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break; + case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break; + case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; + default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; + } + + options_clear(&opt); + log_close(); + exit(ret); + } + tmp = tmp->next_; + } + } + log_printf(NOTICE, "just started..."); + if(options_parse_post(&opt)) { + options_clear(&opt); + log_close(); + exit(-1); + } + + priv_info_t priv; + if(opt.username_) + if(priv_init(&priv, opt.username_, opt.groupname_)) { + options_clear(&opt); + log_close(); + exit(-1); + } + + FILE* pid_file = NULL; + if(opt.pid_file_) { + pid_file = fopen(opt.pid_file_, "w"); + if(!pid_file) { + log_printf(WARNING, "unable to open pid file: %s", strerror(errno)); + } + } + + if(opt.chroot_dir_) + if(do_chroot(opt.chroot_dir_)) { + options_clear(&opt); + log_close(); + exit(-1); + } + if(opt.username_) + if(priv_drop(&priv)) { + options_clear(&opt); + log_close(); + exit(-1); + } + + if(opt.daemonize_) { + pid_t oldpid = getpid(); + daemonize(); + log_printf(INFO, "running in background now (old pid: %d)", oldpid); + } + + if(pid_file) { + pid_t pid = getpid(); + fprintf(pid_file, "%d", pid); + fclose(pid_file); + } + + int cmd_fd = connect_command_socket(opt.command_sock_); + if(cmd_fd < 0) { + options_clear(&opt); + log_close(); + exit(-1); + } + + ret = main_loop(cmd_fd, &opt); + + close(cmd_fd); + + if(!ret) + log_printf(NOTICE, "normal shutdown"); + else if(ret < 0) + log_printf(NOTICE, "shutdown after error"); + else + log_printf(NOTICE, "shutdown after signal"); + + options_clear(&opt); + log_close(); + + return ret; +} diff --git a/mode-leds.lua b/mode-leds.lua new file mode 100644 index 0000000..51568f8 --- /dev/null +++ b/mode-leds.lua @@ -0,0 +1,47 @@ +-- +-- 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/>. +-- + +socket = require("socket") + +function main_loop(opt) + log.printf(log.NOTICE, "main_loop started") + local sig = signal.init() + + + local return_value = 0 + while return_value == 0 do + local readable, _, err = socket.select({ sig }, nil) + if(err) then + log.printf(log.ERROR, "select returned with error: %s", err) + return_value = -1 + else + for _, input in ipairs(readable) do + if(input == sig) then + return_value = signal.handle() + if(return_value == 1) then break end + end + end + end + end + + signal.stop() + return return_value +end @@ -198,6 +198,9 @@ int options_parse(options_t* opt, int argc, char* argv[]) PARSE_INT_PARAM("-t","--timeout", opt->timeout_) PARSE_STRING_PARAM("-l","--led", opt->led_filename_) #endif +#ifdef OPT_LUACLIENT + PARSE_STRING_PARAM("-f","--lua-file", opt->lua_file_) +#endif else return i; } @@ -299,6 +302,9 @@ void options_default(options_t* opt) #ifdef OPT_HEARTBEATCLIENT opt->progname_ = strdup("heartbeatclient"); #endif +#ifdef OPT_LUACLIENT + opt->progname_ = strdup("luaclient"); +#endif /* common */ opt->daemonize_ = 1; @@ -327,8 +333,69 @@ void options_default(options_t* opt) /* heartbeatclient only */ opt->timeout_ = 15; opt->led_filename_ = NULL; + +/* luaclient only */ + opt->lua_file_ = strdup("/usr/share/rhctl/mode-leds.lua"); +} + +#ifdef OPT_LUACLIENT +void options_lua_push_string(lua_State* L, const int tidx, const char* key, const char* value) +{ + lua_pushstring(L, key); + lua_pushstring(L, value); + lua_settable(L, tidx); +} + +void options_lua_push_int(lua_State* L, const int tidx, const char* key, const u_int32_t value) +{ + lua_pushstring(L, key); + lua_pushinteger(L, value); + lua_settable(L, tidx); } +void options_lua_push_boolean(lua_State* L, const int tidx, const char* key, const u_int32_t value) +{ + lua_pushstring(L, key); + lua_pushboolean(L, value); + lua_settable(L, tidx); +} + +void options_lua_push_string_list(lua_State* L, const int tidx, string_list_t* lst) +{ + if(!lst) + return; + + string_list_element_t* tmp = lst->first_; + if(tmp) { + lua_pushstring(L, "log_targets"); + lua_newtable(L); + int i = 1; + while(tmp) { + lua_pushinteger(L, i++); + lua_pushstring(L, tmp->string_); + lua_settable(L, -3); + tmp = tmp->next_; + } + lua_settable(L, tidx); + } +} + +void options_lua_push(options_t* opt, lua_State* L) +{ + lua_newtable(L); + + options_lua_push_string(L, -3, "progname", opt->progname_); + options_lua_push_boolean(L, -3, "daemonize", opt->daemonize_); + options_lua_push_string(L, -3, "username", opt->username_); + options_lua_push_string(L, -3, "groupname", opt->groupname_); + options_lua_push_string(L, -3, "chroot_dir", opt->chroot_dir_); + options_lua_push_string(L, -3, "pid_file", opt->pid_file_); + options_lua_push_string_list(L, -3, &(opt->log_targets_)); + options_lua_push_string(L, -3, "command_sock", opt->command_sock_); + options_lua_push_string(L, -3, "lua_file", opt->lua_file_); +} +#endif + void options_clear(options_t* opt) { if(!opt) @@ -368,6 +435,10 @@ void options_clear(options_t* opt) /* heartbeatcleint only */ if(opt->led_filename_) free(opt->led_filename_); + +/* luacleint only */ + if(opt->lua_file_) + free(opt->lua_file_); } void options_print_usage() @@ -414,6 +485,9 @@ void options_print_usage() printf(" [-t|--timeout] <timeout> heartbeat timeout in tenths of a second e.g. 15 -> 1.5s\n"); printf(" [-l|--led] <led filename> sysfs filename of led device to blink\n"); #endif +#ifdef OPT_LUACLIENT + printf(" [-f|--lua-file] <file> the configuration file e.g. /usr/share/rhctl/mode-leds.lua\n"); +#endif } void options_print(options_t* opt) @@ -469,4 +543,8 @@ void options_print(options_t* opt) printf("timeout: %d\n", opt->timeout_); printf("led_filename: '%s'\n", opt->led_filename_); #endif + +#ifdef OPT_LUACLIENT + printf("lua_file: '%s'\n", opt->lua_file_); +#endif } @@ -22,6 +22,8 @@ #ifndef RHCTL_options_h_INCLUDED #define RHCTL_options_h_INCLUDED +#include <lua.h> + #include "string_list.h" #include "key_value_storage.h" #include <termios.h> @@ -61,6 +63,9 @@ struct options_struct { /* heartbeatclient only */ u_int32_t timeout_; char* led_filename_; + +/* luaclient only */ + char* lua_file_; }; typedef struct options_struct options_t; @@ -69,6 +74,11 @@ int options_parse_hex_string(const char* hex, buffer_t* buffer); int options_parse(options_t* opt, int argc, char* argv[]); int options_parse_post(options_t* opt); void options_default(options_t* opt); +void options_lua_push_string(lua_State* L, const int tidx, const char* key, const char* value); +void options_lua_push_int(lua_State* L, const int tidx, const char* key, const u_int32_t value); +void options_lua_push_boolean(lua_State* L, const int tidx, const char* key, const u_int32_t value); +void options_lua_push_string_list(lua_State* L, const int tidx, string_list_t* lst); +void options_lua_push(options_t* opt, lua_State* L); void options_clear(options_t* opt); void options_print_usage(); void options_print(options_t* opt); |