diff options
Diffstat (limited to 'src/nopsyncd.c')
-rw-r--r-- | src/nopsyncd.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/nopsyncd.c b/src/nopsyncd.c new file mode 100644 index 0000000..8a059d0 --- /dev/null +++ b/src/nopsyncd.c @@ -0,0 +1,171 @@ +/* + * rhnop + * + * Copyright (C) 2011-2015 Christian Pointner <equinox@helsinki.at> + * + * This file is part of rhnop. + * + * rhnop 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. + * + * rhnop 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 rhnop. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <pthread.h> + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#include "l_pipe.h" +#include "config.h" + +#define LUA_MAIN_LOOP_FUNC "main_loop" +#define QLISTENER LIBDIR"/qlistener.lua" +#define TCPSERVER LIBDIR"/tcpserver.lua" + +static const luaL_Reg nopsyncd_lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_PIPELIBNAME, luaopen_pipe}, + {NULL, NULL} +}; + +int init_main_loop(lua_State *L, const char* filename) +{ + const luaL_Reg *lib = nopsyncd_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: fprintf(stderr, "luaL_loadfile() syntax error: %s\n", err_str); break; + case LUA_ERRMEM: fprintf(stderr, "luaL_loadfile() malloc error: %s\n", err_str); break; + case LUA_ERRFILE: fprintf(stderr, "lauL_loadfile() error: %s\n", err_str); break; + default: fprintf(stderr, "luaL_loadfile() unknown error: %s\n", err_str); break; + } + return -1; + } + + lua_pushstring(L, LIBDIR); + lua_setglobal(L, "rhnoplibdir"); + + ret = lua_pcall(L, 0, 0, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: fprintf(stderr, "lua_pcall() runtime error: %s\n", err_str); break; + case LUA_ERRMEM: fprintf(stderr, "lua_pcall() malloc error: %s\n", err_str); break; + case LUA_ERRERR: fprintf(stderr, "lua_pcall() error at error handler function: %s\n", err_str); break; + } + return -1; + } + + return 0; +} + +int call_main_loop(lua_State* L, const char* filename) +{ + lua_getglobal(L, LUA_MAIN_LOOP_FUNC); + if(!lua_isfunction(L, -1)) { + fprintf(stderr, "there is no function '%s' at file '%s'\n", LUA_MAIN_LOOP_FUNC, filename); + return -1; + }; + + int ret = lua_pcall(L, 0, 1, 0); + if(ret) { + const char* err_str = luaL_checkstring(L, -1); + switch(ret) { + case LUA_ERRRUN: fprintf(stderr, "lua_pcall(%s:%s) runtime error: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; + case LUA_ERRMEM: fprintf(stderr, "lua_pcall(%s:%s) malloc error: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; + case LUA_ERRERR: fprintf(stderr, "lua_pcall(%s:%s) error at error handler function: %s\n", filename, LUA_MAIN_LOOP_FUNC, err_str); break; + } + return -1; + } + + ret = lua_tointeger(L, 1); + return ret; +} + +void* main_loop(void* file) +{ + if(!file) + pthread_exit(NULL); + + + lua_State *L; + L = luaL_newstate(); + if(!L) { + fprintf(stderr, "error creating lua state\n"); + pthread_exit(NULL); + } + + int ret = init_main_loop(L, (char*)file); + if(!ret) + ret = call_main_loop(L, (char*)file); + + printf("%s returned with %d\n", (char*)file, ret); + + lua_close(L); + + /* this should bring down the other thread as well + at least this is true for the tcp-server thread */ + pipe_close(); + + pthread_exit(NULL); +} + +int main(int argc, char* argv[]) +{ + printf("starting nopsyncd...\n"); + + pthread_t qlistener, tcpserver; + + int ret = pipe_init(); + if(ret) { + fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); + return 1; + } + + ret = pthread_create(&qlistener, NULL, main_loop, QLISTENER); + if(ret) { + fprintf(stderr, "Error creating qlistener thread (code: %d)\n", ret); + return 1; + } + pthread_detach(qlistener); /* can't kill this thread so don't join to it */ + + ret = pthread_create(&tcpserver, NULL, main_loop, TCPSERVER); + if(ret) { + fprintf(stderr, "Error creating tcpserver thread (code: %d)\n", ret); + return 1; + } + +/* this thread can't be cancelled so don't wait for it */ +/* pthread_join(qlistener, NULL); */ + pthread_join(tcpserver, NULL); + + printf("stopping nopsyncd.\n"); + return 0; +} |