aboutsummaryrefslogtreecommitdiffstats
path: root/src/lua/lua_common.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2020-04-06 14:28:02 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2020-04-06 18:23:44 +0100
commit422bf8b8f4208191ad9818a8b0890721ae4d5cf2 (patch)
treec3aee10478f3328bad21aa2d2c4b9c2768eabd9d /src/lua/lua_common.c
parentf8f0d971bfbe08132e091664f3e3a8fb1fb5285b (diff)
downloadrspamd-422bf8b8f4208191ad9818a8b0890721ae4d5cf2.tar.gz
rspamd-422bf8b8f4208191ad9818a8b0890721ae4d5cf2.zip
[Project] Add routine to call a generic lua function
Diffstat (limited to 'src/lua/lua_common.c')
-rw-r--r--src/lua/lua_common.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c
index ce5fff6c5..8a562f7b3 100644
--- a/src/lua/lua_common.c
+++ b/src/lua/lua_common.c
@@ -2407,4 +2407,92 @@ rspamd_lua_get_module_name (lua_State *L)
}
return NULL;
+}
+
+bool
+rspamd_lua_universal_pcall (lua_State *L, gint cbref, const gchar* strloc,
+ gint nret, const gchar *args, GError **err, ...)
+{
+ va_list ap;
+ const gchar *argp = args, *classname;
+ gint err_idx, nargs = 0;
+ gpointer *cls_ptr;
+ gsize sz;
+
+ /* Error function */
+ lua_pushcfunction (L, &rspamd_lua_traceback);
+ err_idx = lua_gettop (L);
+
+ va_start (ap, err);
+ /* Called function */
+ lua_rawgeti (L, LUA_REGISTRYINDEX, cbref);
+ /*
+ * Possible arguments
+ * - i - lua_integer, argument - gint64
+ * - n - lua_number, argument - gdouble
+ * - s - lua_string, argument - const gchar * (zero terminated)
+ * - l - lua_lstring, argument - (size_t + const gchar *) pair
+ * - u - lua_userdata, argument - (const char * + void *) - classname + pointer
+ * - b - lua_boolean, argument - gboolean (not bool due to varargs promotion)
+ * - f - lua_function, argument - int - position of the function on stack (not lua_registry)
+ */
+ while (*argp) {
+ switch (*argp) {
+ case 'i':
+ lua_pushinteger (L, va_arg (ap, gint64));
+ nargs ++;
+ break;
+ case 'n':
+ lua_pushnumber (L, va_arg (ap, gdouble));
+ nargs ++;
+ break;
+ case 's':
+ lua_pushstring (L, va_arg (ap, const gchar *));
+ nargs ++;
+ break;
+ case 'l':
+ sz = va_arg (ap, gsize);
+ lua_pushlstring (L, va_arg (ap, const gchar *), sz);
+ nargs ++;
+ break;
+ case 'b':
+ lua_pushboolean (L, va_arg (ap, gboolean));
+ nargs ++;
+ break;
+ case 'u':
+ classname = va_arg (ap, const gchar *);
+ cls_ptr = (gpointer *)lua_newuserdata (L, sizeof (gpointer));
+ *cls_ptr = va_arg (ap, gpointer);
+ rspamd_lua_setclass (L, classname, -1);
+ nargs ++;
+ break;
+ case 'f':
+ lua_pushvalue (L, va_arg (ap, gint));
+ nargs ++;
+ break;
+ default:
+ lua_settop (L, err_idx - 1);
+ g_set_error (err, lua_error_quark (), EINVAL,
+ "invalid argument character: %c at %s",
+ *argp, argp);
+
+ return false;
+ }
+
+ argp ++;
+ }
+
+ if (lua_pcall (L, nargs, nret, err_idx) != 0) {
+ g_set_error (err, lua_error_quark (), EBADF,
+ "error when calling lua function from %s: %s",
+ strloc, lua_tostring (L, -1));
+ lua_settop (L, err_idx - 1);
+
+ return false;
+ }
+
+ lua_remove (L, err_idx);
+ va_end (ap);
+
+ return true;
} \ No newline at end of file