]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Add routine to call a generic lua function
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 6 Apr 2020 13:28:02 +0000 (14:28 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 6 Apr 2020 17:23:44 +0000 (18:23 +0100)
src/lua/lua_common.c
src/lua/lua_common.h

index ce5fff6c5d4d89bf80b87cd99691a9de38aaba27..8a562f7b3157db58acaa725e07b76bb902c65f2e 100644 (file)
@@ -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
index aea6ebf26014291d57f90b8ea090f2058b347282..8252da0049842bba13d702a8e1dae11c50bdbf33 100644 (file)
@@ -577,6 +577,27 @@ gint rspamd_lua_push_words (lua_State *L, GArray *words,
  */
 gchar *rspamd_lua_get_module_name (lua_State *L);
 
+/**
+ * Call Lua function in a universal way. Arguments string:
+ * - 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)
+ * @param L lua state
+ * @param cbref LUA_REGISTRY reference
+ * @param strloc where this function is called from
+ * @param nret number of results (or LUA_MULTRET)
+ * @param args arguments format string
+ * @param err error to promote
+ * @param ... arguments
+ * @return true of pcall returned 0, false + err otherwise
+ */
+bool rspamd_lua_universal_pcall (lua_State *L, gint cbref, const gchar* strloc,
+               gint nret, const gchar *args, GError **err, ...);
+
 /* Paths defs */
 #define RSPAMD_CONFDIR_INDEX "CONFDIR"
 #define RSPAMD_LOCAL_CONFDIR_INDEX "LOCAL_CONFDIR"