diff --git a/smmapdfw/Makefile b/smmapdfw/Makefile index 2e9fab7..fca5ea4 100644 --- a/smmapdfw/Makefile +++ b/smmapdfw/Makefile @@ -17,8 +17,10 @@ endif ifeq ($(OS), Linux) BDB_INC ?= /usr/include BDB_LIB ?= /usr/lib/libdb.a -CFLAGS = $(COMMON_CFLAGS) -DLINUX -I$(BDB_INC) -LDFLAGS = $(COMMON_LDFLAGS) -lresolv -pthread -ldl +LUA_INC ?= /usr/include/lua50 +LUA_LIB ?= /usr/lib/liblualib50.a /usr/lib/liblua50.a +CFLAGS = $(COMMON_CFLAGS) -DLINUX -I$(BDB_INC) -I$(LUA_INC) +LDFLAGS = $(COMMON_LDFLAGS) -lresolv -pthread -ldl -lm SHARED = -shared endif @@ -36,7 +38,7 @@ LIBS = MOD_LIBS = CC = gcc -all: smmapd test_workers.so verify_worker.so cyrus_worker.so +all: smmapd test_workers.so verify_worker.so cyrus_worker.so lua_worker.so smmapd: $(MAIN_OBJ) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) @@ -50,6 +52,10 @@ verify_worker.so: verify_worker.o config_public.o dns.o queue.o smtp.o $(BDB_LIB cyrus_worker.so: cyrus_worker.o config_public.o smtp.o dns.o $(CC) $(LDFLAGS) $(SHARED) -o $@ $^ +lua_worker.so: lua_worker.o config_public.o $(LUA_LIB) + $(CC) $(LDFLAGS) $(SHARED) -o $@ $^ + + clean: -rm -f *o *so smmapd diff --git a/smmapdfw/lua_worker.c b/smmapdfw/lua_worker.c new file mode 100644 index 0000000..7e5a569 --- /dev/null +++ b/smmapdfw/lua_worker.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include + +#include "containers_public.h" +#include "smmapd.h" + + +#define CFG_LUALIB_NAMES "load" +#define CFG_LUALIB_DELIMITER " " +#define CFG_LUA_ENTRYPOINT "entrypoint" +#define CFG_LUA_FILENAME "file" + +int lua_init(cfgl_t *cfg, void **handle); +int lua_destroy(void *handle); +int lua_work_setup(void *handle, void **work_handle); +int lua_work_destroy(void *handle, void *work_handle); +int lua_work(void *handle, void *work_handle, char *input, char *output); + + +static const luaL_reg lualibs[] = { + { "base", luaopen_base }, + { "table", luaopen_table }, + { "io", luaopen_io }, + { "string", luaopen_string }, + { "math", luaopen_math }, + { "debug", luaopen_debug }, + { "loadlib", luaopen_loadlib }, + { NULL, NULL } +}; + + + +class_descriptor_t lua_worker = { + "lua_worker", + &lua_init, + &lua_destroy, + &lua_work_setup, + &lua_work, + &lua_work_destroy +}; + +struct lua_container_handle_s { + cfgl_t *cfg; + lua_State *l; + char *lua_entrypoint; +}; + +typedef struct lua_container_handle_s lua_container_handle_t; + +struct lua_worker_handle_s { + lua_container_handle_t *lch; + lua_State *l; +}; + +typedef struct lua_worker_handle_s lua_worker_handle_t; + + +int lua_init(cfgl_t *cfg, void **handle) { + lua_container_handle_t *lch; + char *lualibname, *lualibnames; + int res; + char *lua_filename; + const luaL_reg *lualib; + + lch = (lua_container_handle_t*) malloc(sizeof(lua_container_handle_t)); + lch->cfg = cfg; + + lua_filename = findcfgl(lch->cfg, CFG_LUA_FILENAME); + if (NULL == lua_filename) { + syslog(LOG_ERR, "lua_init: no lua_filename given in config"); + return -1; + } + + lch->lua_entrypoint = findcfglx(lch->cfg, CFG_LUA_ENTRYPOINT, "main"); + + lch->l = lua_open(); + + + lualibnames = findcfglx(lch->cfg, CFG_LUALIB_NAMES, ""); + while (NULL != (lualibname = strtok(lualibnames, CFG_LUALIB_DELIMITER))) { + lualibnames = NULL; /* this is for subsequence calls of strtok */ + syslog(LOG_DEBUG, "lua_init: loading lib %s", lualibname); + + for (lualib = lualibs; lualib->func != NULL; lualib++) { + if (0 == strcmp(lualib->name, lualibname)) { + lualib->func(lch->l); + lua_settop(lch->l, 0); + break; + } + } + } + + res = luaL_loadfile(lch->l, lua_filename); + if (0 != res) { + syslog(LOG_ERR, "lua_init: unable to load lua file %s", lua_filename); + lua_close(lch->l); + free(lch); + return -1; + } + syslog(LOG_DEBUG, "lua_init: lua file %s loaded and compiled", lua_filename); + + res = lua_pcall(lch->l, 0, 0, 0); + if (0 != res) { + syslog(LOG_ERR, "lua_init: unable to execute lua file %s", lua_filename); + lua_close(lch->l); + free(lch); + } + syslog(LOG_DEBUG, "lua_init: lua file %s executed", lua_filename); + + + *handle = lch; + return 0; +} + +int lua_destroy(void *handle) { + lua_container_handle_t *lch = (lua_container_handle_t*) handle; + + lua_close(lch->l); + free(lch); + + return 0; +} + +int lua_work_setup(void *handle, void **work_handle) { + lua_worker_handle_t *lwh = (lua_worker_handle_t*)malloc(sizeof(lua_worker_handle_t)); + lwh->lch = (lua_container_handle_t*) handle; + + lwh->l = lua_newthread(lwh->lch->l); + + *work_handle = lwh; + return 0; +} + +int lua_work_destroy(void *handle, void *work_handle) { + lua_worker_handle_t *lwh = (lua_worker_handle_t*) work_handle; + + free(lwh); +} + +int lua_work(void *handle, void *work_handle, char *input, char *output) { + static const char *SCRIPT_ERROR = "error in lua script"; + + lua_worker_handle_t *lwh = (lua_worker_handle_t*) work_handle; + int result, res; + char *lua_output; + + lua_getglobal(lwh->l, lwh->lch->lua_entrypoint); + lua_pushstring(lwh->l, input); + + res = lua_pcall(lwh->l, 1, 2, 0); + + lua_output = (char*) lua_tostring(lwh->l, lua_gettop(lwh->l)); + lua_pop(lwh->l, 1); + result = lua_tonumber(lwh->l, lua_gettop(lwh->l)); + lua_pop(lwh->l, 1); + + if (0 != res) { + syslog(LOG_ERR, "lua_work: error when calling entrypoint function: %d", res); + result = SMM_TEMP_NOK; + snprintf(output, ANSWER_BUFSIZE, "%s: %s", SCRIPT_ERROR, lua_output); + } else { + snprintf(output, ANSWER_BUFSIZE, lua_output); + } + + return result; +} diff --git a/smmapdfw/smmapd.ini b/smmapdfw/smmapd.ini index e1280d7..d64be22 100644 --- a/smmapdfw/smmapd.ini +++ b/smmapdfw/smmapd.ini @@ -1,10 +1,11 @@ [global] -do_fork = 1 +do_fork = 0 pid_file = smmapd.pid address = 127.0.0.1 port = 8887 -plugin_dir = /home/who/Sources/private/smmapd -plugins = test_worker1 test_worker2 verifier cyruscheck +plugin_dir = /home/who/Sources/sf/smmapdfw +; plugins = test_worker1 test_worker2 verifier cyruscheck lua_worker +plugins = lua_worker [test_worker1] obj = test_workers.so @@ -30,3 +31,11 @@ timeout = 10 sender_address = lhlo_arg = local lmtp_port = 24 + +[lua_worker] +obj = lua_worker.so +; load = base string table math loadlib io +load = base string io +lua_path = . +file = worker.l +entrypoint = f diff --git a/smmapdfw/worker.l b/smmapdfw/worker.l new file mode 100644 index 0000000..610385d --- /dev/null +++ b/smmapdfw/worker.l @@ -0,0 +1,5 @@ +function f (i) + io.write("[lua] output from lua\n") + io.write("[lua] ", i, "\n") + return 1, string.upper(i) +end