Software / code / prosody
Comparison
prosodyctl @ 1087:5e9475bec571
prosodyctl, util.prosodyctl: New prosodyctl utility for managing Prosody servers
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Sat, 02 May 2009 17:03:19 +0100 |
| child | 1089:a817cbaa0f46 |
comparison
equal
deleted
inserted
replaced
| 1086:0b895e1ac713 | 1087:5e9475bec571 |
|---|---|
| 1 #!/usr/bin/env lua | |
| 2 -- Prosody IM v0.4 | |
| 3 -- Copyright (C) 2008-2009 Matthew Wild | |
| 4 -- Copyright (C) 2008-2009 Waqas Hussain | |
| 5 -- | |
| 6 -- This project is MIT/X11 licensed. Please see the | |
| 7 -- COPYING file in the source package for more information. | |
| 8 -- | |
| 9 | |
| 10 -- prosodyctl - command-line controller for Prosody XMPP server | |
| 11 | |
| 12 -- Will be modified by configure script if run -- | |
| 13 | |
| 14 CFG_SOURCEDIR=nil; | |
| 15 CFG_CONFIGDIR=os.getenv("PROSODY_CFGDIR"); | |
| 16 CFG_PLUGINDIR=nil; | |
| 17 CFG_DATADIR=os.getenv("PROSODY_DATADIR"); | |
| 18 | |
| 19 -- -- -- -- -- -- -- ---- -- -- -- -- -- -- -- -- | |
| 20 | |
| 21 if CFG_SOURCEDIR then | |
| 22 package.path = CFG_SOURCEDIR.."/?.lua;"..package.path | |
| 23 package.cpath = CFG_SOURCEDIR.."/?.so;"..package.cpath | |
| 24 end | |
| 25 | |
| 26 if CFG_DATADIR then | |
| 27 if os.getenv("HOME") then | |
| 28 CFG_DATADIR = CFG_DATADIR:gsub("^~", os.getenv("HOME")); | |
| 29 end | |
| 30 end | |
| 31 | |
| 32 -- Required to be able to find packages installed with luarocks | |
| 33 pcall(require, "luarocks.require") | |
| 34 | |
| 35 | |
| 36 config = require "core.configmanager" | |
| 37 | |
| 38 do | |
| 39 -- TODO: Check for other formats when we add support for them | |
| 40 -- Use lfs? Make a new conf/ dir? | |
| 41 local ok, level, err = config.load((CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); | |
| 42 if not ok then | |
| 43 print("\n"); | |
| 44 print("**************************"); | |
| 45 if level == "parser" then | |
| 46 print("A problem occured while reading the config file "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); | |
| 47 local err_line, err_message = tostring(err):match("%[string .-%]:(%d*): (.*)"); | |
| 48 print("Error"..(err_line and (" on line "..err_line) or "")..": "..(err_message or tostring(err))); | |
| 49 print(""); | |
| 50 elseif level == "file" then | |
| 51 print("Prosody was unable to find the configuration file."); | |
| 52 print("We looked for: "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); | |
| 53 print("A sample config file is included in the Prosody download called prosody.cfg.lua.dist"); | |
| 54 print("Copy or rename it to prosody.cfg.lua and edit as necessary."); | |
| 55 end | |
| 56 print("More help on configuring Prosody can be found at http://prosody.im/doc/configure"); | |
| 57 print("Good luck!"); | |
| 58 print("**************************"); | |
| 59 print(""); | |
| 60 os.exit(1); | |
| 61 end | |
| 62 end | |
| 63 | |
| 64 local error_messages = setmetatable({ | |
| 65 ["invalid-username"] = "The given username is invalid in a Jabber ID"; | |
| 66 ["invalid-hostname"] = "The given hostname is invalid"; | |
| 67 ["no-password"] = "No password was supplied"; | |
| 68 ["no-such-user"] = "The given user does not exist on the server"; | |
| 69 }, { __index = function (t,k) return "Error: "..(tostring(k):gsub("%-", " "):gsub("^.", string.upper)); end }); | |
| 70 | |
| 71 hosts = {}; | |
| 72 | |
| 73 require "core.hostmanager" | |
| 74 require "core.eventmanager".fire_event("server-starting"); | |
| 75 | |
| 76 require "util.prosodyctl" | |
| 77 ----------------------- | |
| 78 | |
| 79 function show_message(msg, ...) | |
| 80 print(msg:format(...)); | |
| 81 end | |
| 82 | |
| 83 function show_warning(msg, ...) | |
| 84 print(msg:format(...)); | |
| 85 end | |
| 86 | |
| 87 function show_usage(usage, desc) | |
| 88 print("Usage: "..arg[0].." "..usage); | |
| 89 if desc then | |
| 90 print(" "..desc); | |
| 91 end | |
| 92 end | |
| 93 | |
| 94 local function getchar(n) | |
| 95 os.execute("stty raw -echo"); | |
| 96 local char = io.read(n or 1); | |
| 97 os.execute("stty sane"); | |
| 98 return char; | |
| 99 end | |
| 100 | |
| 101 local function getpass() | |
| 102 os.execute("stty -echo"); | |
| 103 local pass = io.read("*l"); | |
| 104 os.execute("stty sane"); | |
| 105 io.write("\n"); | |
| 106 return pass; | |
| 107 end | |
| 108 | |
| 109 function show_yesno(prompt) | |
| 110 io.write(prompt, " "); | |
| 111 local choice = getchar():lower(); | |
| 112 io.write("\n"); | |
| 113 if not choice:match("%a") then | |
| 114 choice = prompt:match("%[.-(%U).-%]$"); | |
| 115 if not choice then return nil; end | |
| 116 end | |
| 117 return (choice == "y"); | |
| 118 end | |
| 119 | |
| 120 local function read_password() | |
| 121 local password; | |
| 122 while true do | |
| 123 io.write("Enter new password: "); | |
| 124 password = getpass(); | |
| 125 io.write("Retype new password: "); | |
| 126 if getpass() ~= password then | |
| 127 if not show_yesno [=[Passwords did not match, try again? [Y/n]]=] then | |
| 128 return; | |
| 129 end | |
| 130 else | |
| 131 break; | |
| 132 end | |
| 133 end | |
| 134 return password; | |
| 135 end | |
| 136 ----------------------- | |
| 137 local commands = {}; | |
| 138 local command = arg[1]; | |
| 139 | |
| 140 function commands.adduser(arg) | |
| 141 if not arg[1] or arg[1] == "--help" then | |
| 142 show_usage([[adduser JID]], [[Create the specified user account in Prosody]]); | |
| 143 return 1; | |
| 144 end | |
| 145 local user, host = arg[1]:match("([^@]+)@(.+)"); | |
| 146 if not user and host then | |
| 147 show_message [[Failed to understand JID, please supply the JID you want to create]] | |
| 148 show_usage [[adduser user@host]] | |
| 149 return 1; | |
| 150 end | |
| 151 | |
| 152 if not host then | |
| 153 show_message [[Please specify a JID, including a host. e.g. alice@example.com]]; | |
| 154 return 1; | |
| 155 end | |
| 156 | |
| 157 if prosodyctl.user_exists{ user = user, host = host } then | |
| 158 show_message [[That user already exists]]; | |
| 159 return 1; | |
| 160 end | |
| 161 | |
| 162 if not hosts[host] then | |
| 163 show_warning("The host '%s' is not listed in the configuration file (or is not enabled).", host) | |
| 164 show_warning("The user will not be able to log in until this is changed."); | |
| 165 end | |
| 166 | |
| 167 local password = read_password(); | |
| 168 if not password then return 1; end | |
| 169 | |
| 170 local ok, msg = prosodyctl.adduser { user = user, host = host, password = password }; | |
| 171 | |
| 172 if ok then return 0; end | |
| 173 | |
| 174 show_message(error_messages[msg]) | |
| 175 return 1; | |
| 176 end | |
| 177 | |
| 178 function commands.passwd(arg) | |
| 179 if not arg[1] or arg[1] == "--help" then | |
| 180 show_usage([[passwd JID]], [[Set the password for the specified user account in Prosody]]); | |
| 181 return 1; | |
| 182 end | |
| 183 local user, host = arg[1]:match("([^@]+)@(.+)"); | |
| 184 if not user and host then | |
| 185 show_message [[Failed to understand JID, please supply the JID you want to set the password for]] | |
| 186 show_usage [[passwd user@host]] | |
| 187 return 1; | |
| 188 end | |
| 189 | |
| 190 if not host then | |
| 191 show_message [[Please specify a JID, including a host. e.g. alice@example.com]]; | |
| 192 return 1; | |
| 193 end | |
| 194 | |
| 195 if not prosodyctl.user_exists { user = user, host = host } then | |
| 196 show_message [[That user does not exist, use prosodyctl adduser to create a new user]] | |
| 197 return 1; | |
| 198 end | |
| 199 | |
| 200 local password = read_password(); | |
| 201 if not password then return 1; end | |
| 202 | |
| 203 local ok, msg = prosodyctl.passwd { user = user, host = host, password = password }; | |
| 204 | |
| 205 if ok then return 0; end | |
| 206 | |
| 207 show_message(error_messages[msg]) | |
| 208 return 1; | |
| 209 end | |
| 210 | |
| 211 function commands.deluser(arg) | |
| 212 if not arg[1] or arg[1] == "--help" then | |
| 213 show_usage([[deluser JID]], [[Permanently remove the specified user account from Prosody]]); | |
| 214 return 1; | |
| 215 end | |
| 216 local user, host = arg[1]:match("([^@]+)@(.+)"); | |
| 217 if not user and host then | |
| 218 show_message [[Failed to understand JID, please supply the JID you want to set the password for]] | |
| 219 show_usage [[passwd user@host]] | |
| 220 return 1; | |
| 221 end | |
| 222 | |
| 223 if not host then | |
| 224 show_message [[Please specify a JID, including a host. e.g. alice@example.com]]; | |
| 225 return 1; | |
| 226 end | |
| 227 | |
| 228 if not prosodyctl.user_exists { user = user, host = host } then | |
| 229 show_message [[That user does not exist on this server]] | |
| 230 return 1; | |
| 231 end | |
| 232 | |
| 233 local ok, msg = prosodyctl.passwd { user = user, host = host }; | |
| 234 | |
| 235 if ok then return 0; end | |
| 236 | |
| 237 show_message(error_messages[msg]) | |
| 238 return 1; | |
| 239 end | |
| 240 | |
| 241 function commands.start() | |
| 242 local ok, ret = prosodyctl.isrunning(); | |
| 243 if not ok then | |
| 244 show_message(error_messages[ret]); | |
| 245 return 1; | |
| 246 end | |
| 247 | |
| 248 if ret then | |
| 249 local ok, ret = prosodyctl.getpid(); | |
| 250 if not ok then | |
| 251 show_message("Couldn't get running Prosody's PID"); | |
| 252 show_message(error_messages[ret]); | |
| 253 return 1; | |
| 254 end | |
| 255 show_message("Prosody is already running with PID %s", ret or "(unknown)"); | |
| 256 return 1; | |
| 257 end | |
| 258 | |
| 259 local ok, ret = prosodyctl.start(); | |
| 260 if ok then return 0; end | |
| 261 | |
| 262 show_message("Failed to start Prosody"); | |
| 263 show_message(error_messages[ret]) | |
| 264 return 1; | |
| 265 end | |
| 266 | |
| 267 function commands.status() | |
| 268 local ok, ret = prosodyctl.isrunning(); | |
| 269 if not ok then | |
| 270 show_message(error_messages[ret]); | |
| 271 return 1; | |
| 272 end | |
| 273 | |
| 274 if ret then | |
| 275 local ok, ret = prosodyctl.getpid(); | |
| 276 if not ok then | |
| 277 show_message("Couldn't get running Prosody's PID"); | |
| 278 show_message(error_messages[ret]); | |
| 279 return 1; | |
| 280 end | |
| 281 show_message("Prosody is running with PID %s", ret or "(unknown)"); | |
| 282 return 0; | |
| 283 end | |
| 284 return 1; | |
| 285 end | |
| 286 | |
| 287 function commands.stop() | |
| 288 if not prosodyctl.isrunning() then | |
| 289 show_message("Prosody is not running"); | |
| 290 return 1; | |
| 291 end | |
| 292 | |
| 293 local ok, ret = prosodyctl.stop(); | |
| 294 if ok then return 0; end | |
| 295 | |
| 296 show_message(error_messages[ret]) | |
| 297 return 1; | |
| 298 end | |
| 299 | |
| 300 -- ejabberdctl compatibility | |
| 301 | |
| 302 function commands.register(arg) | |
| 303 local user, host, password = unpack(arg); | |
| 304 if (not (user and host)) or arg[1] == "--help" then | |
| 305 if not user and user ~= "--help" then | |
| 306 show_message [[No username specified]] | |
| 307 elseif not host then | |
| 308 show_message [[Please specify which host you want to register the user on]]; | |
| 309 end | |
| 310 show_usage("register USER HOST [PASSWORD]", "Register a user on the server, with the given password"); | |
| 311 return 1; | |
| 312 end | |
| 313 if not password then | |
| 314 password = read_password(); | |
| 315 if not password then | |
| 316 show_message [[Unable to register user with no password]]; | |
| 317 return 1; | |
| 318 end | |
| 319 end | |
| 320 | |
| 321 local ok, msg = prosodyctl.adduser { user = user, host = host, password = password }; | |
| 322 | |
| 323 if ok then return 0; end | |
| 324 | |
| 325 show_message(error_messages[msg]) | |
| 326 return 1; | |
| 327 end | |
| 328 | |
| 329 function commands.unregister(arg) | |
| 330 local user, host = unpack(arg); | |
| 331 if (not (user and host)) or arg[1] == "--help" then | |
| 332 if not user then | |
| 333 show_message [[No username specified]] | |
| 334 elseif not host then | |
| 335 show_message [[Please specify which host you want to unregister the user from]]; | |
| 336 end | |
| 337 show_usage("register USER HOST [PASSWORD]", "Permanently remove a user account from the server"); | |
| 338 return 1; | |
| 339 end | |
| 340 | |
| 341 local ok, msg = prosodyctl.deluser { user = user, host = host }; | |
| 342 | |
| 343 if ok then return 0; end | |
| 344 | |
| 345 show_message(error_messages[msg]) | |
| 346 return 1; | |
| 347 end | |
| 348 | |
| 349 | |
| 350 --------------------- | |
| 351 | |
| 352 if not commands[command] then -- Show help for all commands | |
| 353 function show_usage(usage, desc) | |
| 354 print(" "..usage); | |
| 355 print(" "..desc); | |
| 356 end | |
| 357 | |
| 358 print("prosodyctl - Manage a Prosody server"); | |
| 359 print(""); | |
| 360 print("Usage: "..arg[0].." COMMAND [OPTIONS]"); | |
| 361 print(""); | |
| 362 print("Where COMMAND may be one of:\n"); | |
| 363 | |
| 364 local commands_order = { "adduser", "passwd", "deluser" }; | |
| 365 | |
| 366 local done = {}; | |
| 367 | |
| 368 for _, command_name in ipairs(commands_order) do | |
| 369 local command = commands[command_name]; | |
| 370 if command then | |
| 371 command{ "--help" }; | |
| 372 print"" | |
| 373 done[command_name] = true; | |
| 374 end | |
| 375 end | |
| 376 | |
| 377 for command_name, command in pairs(commands) do | |
| 378 if not done[command_name] then | |
| 379 command{ "--help" }; | |
| 380 print"" | |
| 381 done[command_name] = true; | |
| 382 end | |
| 383 end | |
| 384 | |
| 385 | |
| 386 os.exit(0); | |
| 387 end | |
| 388 | |
| 389 os.exit(commands[command]({ select(2, unpack(arg)) })); |