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 /luaclient.c | |
parent | 16797549c7788b05583f241e5c788a666debf6d0 (diff) |
added luaclient
Diffstat (limited to 'luaclient.c')
-rw-r--r-- | luaclient.c | 256 |
1 files changed, 256 insertions, 0 deletions
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; +} |