/* * rhnop * * Copyright (C) 2011-2015 Christian Pointner * * 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 . */ #include #include #include #include #include #include #include #include #include "l_pipe.h" #include "config.h" #define LUA_MAIN_LOOP_FUNC "main_loop" #define QLISTENER DATAROOTDIR"/rhnop/qlistener.lua" #define TCPSERVER DATAROOTDIR"/rhnop/tcpserver.lua" #if LUA_VERSION_NUM > 501 static const luaL_Reg nopsyncd_lualibs[] = { {"_G", 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_BITLIBNAME, luaopen_bit32}, {LUA_PIPELIBNAME, luaopen_pipe}, {NULL, NULL} }; #else 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} }; #endif int init_main_loop(lua_State *L, const char* filename) { const luaL_Reg *lib = nopsyncd_lualibs; #if LUA_VERSION_NUM > 501 for (; lib->func; lib++) { luaL_requiref(L, lib->name, lib->func, 1); lua_pop(L, 1); } #else for (; lib->func; lib++) { lua_pushcfunction(L, lib->func); lua_pushstring(L, lib->name); lua_call(L, 1, 0); } #endif 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, DATAROOTDIR); lua_setglobal(L, "rhnoplibdir"); lua_pushstring(L, ETCDIR); lua_setglobal(L, "rhnopescdir"); 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; }