dlua-script.c revision e88e76e782853e826d00524ee1133e64fb69b3d9
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "ok";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "yield";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "runtime error";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "syntax error";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "out of memory";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "gc management error";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "error while handling error";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "error loading file";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return "unknown error";
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistatic void *dlua_alloc(void *ctx, void *ptr, size_t osize, size_t nsize)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return p_realloc(script->pool, ptr, osize, nsize);
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistatic const char *dlua_reader(lua_State *L, void *ctx, size_t *size_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi const unsigned char *data;
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if (i_stream_read_more(script->in, &data, size_r) == -1 &&
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi luaL_error(L, t_strdup_printf("read(%s) failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return (const char*)data;
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistruct dlua_script *dlua_script_from_state(lua_State *L)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi for(script = dlua_scripts; script != NULL; script = script->next)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if (script->L == L)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomiint dlua_script_init(struct dlua_script *script, const char **error_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi /* see if there is a symbol for init */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if (ret != 0) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf("lua_pcall("LUA_SCRIPT_INIT_FN") failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf(LUA_SCRIPT_INIT_FN "() returned non-number");
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistatic struct dlua_script *dlua_create_script(const char *name)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi pool_t pool = pool_allocfree_create(t_strdup_printf("lua script %s", name));
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi struct dlua_script *script = p_new(pool, struct dlua_script, 1);
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi /* lua API says that lua_newstate will return NULL only if it's out of
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi memory. this cannot really happen with our allocator as it will
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi call i_fatal_status anyways if it runs out of memory */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistatic int dlua_run_script(struct dlua_script *script, const char **error_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if (err != 0) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf("lua_pcall(%s) failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistatic struct dlua_script *
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomidlua_script_find_previous_script(const char *filename)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi for(script = dlua_scripts; script != NULL; script = script->next)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomidlua_script_create_finish(struct dlua_script *script, struct dlua_script **script_r,
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi const char **error_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomiint dlua_script_create_string(const char *str, struct dlua_script **script_r,
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi const char **error_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi const char *fn;
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi fn = binary_to_hex(scripthash, sizeof(scripthash));
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if ((script = dlua_script_find_previous_script(fn)) != NULL) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if ((err = luaL_loadstring(script->L, str)) != 0) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf("lua_load(<string>) failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return dlua_script_create_finish(script, script_r, error_r);
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomiint dlua_script_create_file(const char *file, struct dlua_script **script_r,
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi const char **error_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if ((script = dlua_script_find_previous_script(file)) != NULL) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi /* lua reports file access errors poorly */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf("access(%s) failed: %m",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if ((err = luaL_loadfile(script->L, file)) != 0) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf("lua_load(%s) failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return dlua_script_create_finish(script, script_r, error_r);
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomiint dlua_script_create_stream(struct istream *is, struct dlua_script **script_r,
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi const char **error_r)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if ((script = dlua_script_find_previous_script(filename)) != NULL) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi script->filename = p_strdup(script->pool, filename);
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if ((err = lua_load(script->L, dlua_reader, script, filename, 0)) < 0) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi *error_r = t_strdup_printf("lua_load(%s) failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi return dlua_script_create_finish(script, script_r, error_r);
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomistatic void dlua_script_destroy(struct dlua_script *script)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi /* courtesy call */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi /* see if there is a symbol for deinit */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi if (ret != 0) {
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi i_warning("lua_pcall("LUA_SCRIPT_DEINIT_FN") failed: %s",
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomi /* then just release memory */
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomivoid dlua_script_unref(struct dlua_script **_script)
e88e76e782853e826d00524ee1133e64fb69b3d9Aki Tuomibool dlua_script_has_function(struct dlua_script *script, const char *fn)