Add initial mod_console
authorMatthew Wild <mwild1@gmail.com>
Sun, 23 Nov 2008 04:54:44 +0000 (04:54 +0000)
committerMatthew Wild <mwild1@gmail.com>
Sun, 23 Nov 2008 04:54:44 +0000 (04:54 +0000)
main.lua
plugins/mod_console.lua [new file with mode: 0644]

index 97c97c5cdf1d2c33586018c4f16b4e94a136f6d2..d93ce8f0a642a00eca8d169c53358401f52b6fca 100644 (file)
--- a/main.lua
+++ b/main.lua
@@ -88,6 +88,8 @@ end
 start("xmppclient", { ssl = global_ssl_ctx })
 start("xmppserver", { ssl = global_ssl_ctx })
 
+start("console")
+
 modulemanager.fire_event("server-started");
 
 server.loop();
diff --git a/plugins/mod_console.lua b/plugins/mod_console.lua
new file mode 100644 (file)
index 0000000..5787ad2
--- /dev/null
@@ -0,0 +1,140 @@
+\r
+local connlisteners_register = require "net.connlisteners".register;\r
+\r
+local console_listener = { default_port = 5582; default_mode = "*l"; };\r
+\r
+local commands = {};\r
+local default_env = {};\r
+local default_env_mt = { __index = default_env };\r
+\r
+console = {};\r
+\r
+function console:new_session(conn)\r
+       local w = conn.write;\r
+       return { conn = conn;\r
+                       send = function (t) w(tostring(t)); end;\r
+                       print = function (t) w("| "..tostring(t).."\n"); end;\r
+                       disconnect = function () conn.close(); end;\r
+                       env = setmetatable({}, default_env_mt);\r
+                       };\r
+end\r
+\r
+local sessions = {};\r
+\r
+function console_listener.listener(conn, data)\r
+       local session = sessions[conn];\r
+       \r
+       if not session then\r
+               -- Handle new connection\r
+               session = console:new_session(conn);\r
+               sessions[conn] = session;\r
+               session.print("Welcome to the lxmppd admin console!");\r
+       end\r
+       if data then\r
+               -- Handle data\r
+               \r
+               if data:match("[!.]$") then\r
+                       local command = data:lower();\r
+                       command = data:match("^%w+") or data:match("%p");\r
+                       if commands[command] then\r
+                               commands[command](session, data);\r
+                               return;\r
+                       end\r
+               end\r
+               \r
+               session.env._ = data;\r
+               \r
+               local chunk, err = loadstring("return "..data);\r
+               if not chunk then\r
+                       chunk, err = loadstring(data);\r
+                       if not chunk then\r
+                               err = err:gsub("^%[string .-%]:%d+: ", "");\r
+                               err = err:gsub("^:%d+: ", "");\r
+                               err = err:gsub("'<eof>'", "the end of the line");\r
+                               session.print("Sorry, I couldn't understand that... "..err);\r
+                               return;\r
+                       end\r
+               end\r
+               \r
+               setfenv(chunk, session.env);\r
+               local ranok, taskok, message = pcall(chunk);\r
+               \r
+               if not ranok then\r
+                       session.print("Fatal error while running command, it did not complete");\r
+                       session.print("Error: "..taskok);\r
+                       return;\r
+               end\r
+               \r
+               if not message then\r
+                       session.print("Result: "..tostring(taskok));\r
+                       return;\r
+               elseif (not taskok) and message then\r
+                       session.print("Command completed with a problem");\r
+                       session.print("Message: "..tostring(message));\r
+                       return;\r
+               end\r
+               \r
+               session.print("OK: "..tostring(message));\r
+       end\r
+end\r
+\r
+function console_listener.disconnect(conn, err)\r
+       \r
+end\r
+\r
+connlisteners_register('console', console_listener);\r
+\r
+-- Console commands --\r
+-- These are simple commands, not valid standalone in Lua\r
+\r
+function commands.bye(session)\r
+       session.print("See you! :)");\r
+       session.disconnect();\r
+end\r
+\r
+commands["!"] = function (session, data)\r
+       if data:match("^!!") then\r
+               session.print("!> "..session.env._);\r
+               return console_listener.listener(session.conn, session.env._);\r
+       end\r
+       local old, new = data:match("^!(.-[^\\])!(.-)!$");\r
+       if old and new then\r
+               local ok, res = pcall(string.gsub, session.env._, old, new);\r
+               if not ok then\r
+                       session.print(res)\r
+                       return;\r
+               end\r
+               session.print("!> "..res);\r
+               return console_listener.listener(session.conn, res);\r
+       end\r
+       session.print("Sorry, not sure what you want");\r
+end\r
+\r
+-- Session environment --\r
+-- Anything in default_env will be accessible within the session as a global variable\r
+\r
+default_env.server = {};\r
+function default_env.server.reload()\r
+       dofile "main.lua"\r
+       return true, "Server reloaded";\r
+end\r
+\r
+default_env.module = {};\r
+function default_env.module.load(name)\r
+       local mm = require "modulemanager";\r
+       local ok, err = mm.load(name);\r
+       if not ok then\r
+               return false, err or "Unknown error loading module";\r
+       end\r
+       return true, "Module loaded";\r
+end\r
+\r
+default_env.config = {};\r
+function default_env.config.load(filename, format)\r
+       local cfgm_load = require "core.configmanager".load;\r
+       local ok, err = cfgm_load(filename, format);\r
+       if not ok then\r
+               return false, err or "Unknown error loading config";\r
+       end\r
+       return true, "Config loaded";\r
+end\r