]> PatchyGit - patchyircd.git/commitdiff
admin: move command/hook dispatch to lua
authorEgor <egor@patchysicp.xyz>
Thu, 12 Feb 2026 00:42:47 +0000 (02:42 +0200)
committerEgor <egor@patchysicp.xyz>
Thu, 12 Feb 2026 00:42:47 +0000 (02:42 +0200)
lua/init.lua
src/admin.cpp
src/main.cpp

index 66da1ca..252be05 100644 (file)
@@ -1,11 +1,34 @@
 -- Copyright (c) 2023-2026 Egor
 -- SPDX-License-Identifier: GPL-2.0-or-later
+if not commands then
+       commands = {}
+end
+function dispatch_command(client, source, command, ...)
+       if client.regstate ~= 2 then -- REG_REGISTERED
+               -- TODO: err_notregistered(), sendbuf(client)
+               return
+       end
+       if client.umode & 2 == 0 then -- UMODE_OPER
+               -- TODO: err_noprivileges(), sendbuf(client)
+               return
+       end
+       commands[command](client, source, command, table.pack(...))
+end
+function commands.eval(client, source, command, args)
+       assert(load(args[1], args[1], "t"))()
+end
 function commands.reload(client, source, command, args)
        client_notice(client, "reloading...")
        dofile(getluafile "init.lua")
        client_notice(client, "done")
 end
 setmetatable(_G, getmetatable(ircd))
+if not hooks then
+       hooks = {}
+end
+function dispatch_hook(hook, cl1, cl2, chan, txt)
+       return hooks[hook](hook, cl1, cl2, chan, txt)
+end
 if not managed_hooks then
        managed_hooks = {}
 end
index 1a9acb2..bf47c3d 100644 (file)
@@ -274,15 +274,6 @@ static int globals_index(lua_State *L)
                return push(L, dyingclients), 1;
        return 0;
 }
-static int command_eval(lua_State *L)
-{
-       luaL_checktype(L, 4, LUA_TTABLE);
-       lua_geti(L, 4, 1);
-       if (LUA_OK != luaL_dostring(L, lua_tostring(L, -1))) {
-               fprintf(stderr, "%s\n", lua_tostring(L, -1));
-       }
-       return 0;
-}
 static int fn_client_privmsg(lua_State *L)
 {
        Client *cl = ClientRef::check(L, 1);
@@ -473,12 +464,6 @@ void admin_init(void)
        lua_newuserdatauv(L, 0, 0);
        luaL_setmetatable(L, "globals");
        lua_setglobal(L, "ircd");
-       lua_newtable(L);
-       lua_pushcfunction(L, command_eval);
-       lua_setfield(L, -2, "eval");
-       lua_setglobal(L, "commands");
-       lua_newtable(L);
-       lua_setglobal(L, "hooks");
        {
                luaL_Reg funcs[] = {
                        {"client_privmsg", fn_client_privmsg},
@@ -519,35 +504,20 @@ void admin_dostring(const char *command)
 }
 bool admin_command(Client *client, char *source, char *command, int argc, char *args[])
 {
-       if (!is_registered(client))
-               return err_notregistered(), sendbuf(client), false;
-       if (!(client->umode & UMODE_OPER))
-               return err_noprivileges(client), sendbuf(client), false;
        lua_State *L = GL;
 
-       if (lua_getglobal(L, "commands") != LUA_TTABLE) {
-               fprintf(stderr, "no command table\n");
-               lua_pop(L, 1);
-               return false;
-       }
-       lua_getfield(L, -1, command);
-       lua_remove(L, -2);
-       if (!lua_isfunction(L, -1)) {
-               fprintf(stderr, "command not found: %s\n", command);
-               lua_pop(L, 1);
-               return false;
-       }
+       lua_getglobal(L, "dispatch_command");
        push(L, client);
        lua_pushstring(L, source);
        lua_pushstring(L, command);
-       lua_createtable(L, argc, 1);
-       for (int i = 0; i < argc; i++) {
-               lua_pushstring(L, args[i]);
-               lua_seti(L, -2, i+1);
+       if (!lua_checkstack(L, argc)) {
+               fprintf(stderr, "no lua stack space\n");
+               lua_settop(L, 0);
+               return false;
        }
-       lua_pushinteger(L, argc);
-       lua_setfield(L, -2, "n");
-       if (LUA_OK != lua_pcall(L, 4, 0, 0)) {
+       for (int i = 0; i < argc; i++)
+               lua_pushstring(L, args[i]);
+       if (LUA_OK != lua_pcall(L, 3+argc, 0, 0)) {
                fprintf(stderr, "%s\n", lua_tostring(L, -1));
                lua_pop(L, 1);
        }
@@ -556,16 +526,7 @@ bool admin_command(Client *client, char *source, char *command, int argc, char *
 int admin_hook(const char *hook, Client *cl1, Client *cl2, Channel *chan, char *txt)
 {
        lua_State *L = GL;
-       if (lua_getglobal(L, "hooks") != LUA_TTABLE) {
-               lua_pop(L, 1);
-               return 0;
-       }
-       lua_getfield(L, -1, hook);
-       lua_remove(L, -2);
-       if (!lua_isfunction(L, -1)) {
-               lua_pop(L, 1);
-               return 0;
-       }
+       lua_getglobal(L, "dispatch_hook");
        lua_pushstring(L, hook);
        cl1 ? push(L, cl1) : lua_pushnil(L);
        cl2 ? push(L, cl2) : lua_pushnil(L);
index 05a3e58..b15288e 100644 (file)
@@ -292,6 +292,16 @@ int main(int argc, char *argv[])
                netpoll::reg(listener.fd, UV_READABLE);
        }
 
+       // make eval work even if the rest of the runtime is missing
+       admin_dostring(R"(
+               function dispatch_command(client, source, command, ...)
+                       -- UMODE_OPER
+                       if client.umode & 2 ~= 0 and command == "eval" then
+                               local s = table.pack(...)[1]
+                               assert(load(s, s, "t"))()
+                       end
+               end
+       )");
        admin_dostring("dofile(getluafile'init.lua')");
 
        fchanlog = fopen(getdatafile("chanlog.txt"), "abe");