192 lines
4.8 KiB
C
192 lines
4.8 KiB
C
#include <stdlib.h>
|
|
#include <syslog.h>
|
|
#include <string.h>
|
|
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include <lauxlib.h>
|
|
|
|
#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, cnt;
|
|
char *lua_filename;
|
|
const luaL_reg *lualib;
|
|
cfgl_t *cfgl_iter;
|
|
|
|
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)) {
|
|
res = lualib->func(lch->l);
|
|
/* syslog(LOG_DEBUG, "lua_init %s loaded, result %d", lualibname, res); */
|
|
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);
|
|
|
|
lua_newtable(lch->l);
|
|
cnt = 0;
|
|
for (cfgl_iter = lch->cfg; cfgl_iter != NULL; cfgl_iter = cfgl_iter->next) {
|
|
lua_pushstring(lch->l, cfgl_iter->name);
|
|
lua_pushstring(lch->l, cfgl_iter->value);
|
|
lua_rawset(lch->l, -3);
|
|
cnt++;
|
|
}
|
|
|
|
lua_pushliteral(lch->l, "n"); /* Pushes the literal */
|
|
lua_pushnumber(lch->l, cnt); /* Pushes the total number of cells */
|
|
lua_rawset(lch->l, -3); /* Stores the pair in the table */
|
|
|
|
lua_setglobal(lch->l, "config");
|
|
|
|
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);
|
|
return -1;
|
|
}
|
|
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);
|
|
|
|
/* peek the result from the stack */
|
|
lua_output = (char*) lua_tostring(lwh->l, lua_gettop(lwh->l));
|
|
result = lua_tonumber(lwh->l, lua_gettop(lwh->l));
|
|
|
|
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);
|
|
}
|
|
|
|
/* remove the result from the stack */
|
|
lua_pop(lwh->l, 2);
|
|
|
|
return result;
|
|
}
|