mirror of https://github.com/bjc/prosody
remotes/origin/sasl
parent
2ced82baee
commit
2fb13bad65
@ -0,0 +1,389 @@ |
||||
#!/usr/bin/env lua |
||||
-- Prosody IM v0.4 |
||||
-- Copyright (C) 2008-2009 Matthew Wild |
||||
-- Copyright (C) 2008-2009 Waqas Hussain |
||||
-- |
||||
-- This project is MIT/X11 licensed. Please see the |
||||
-- COPYING file in the source package for more information. |
||||
-- |
||||
|
||||
-- prosodyctl - command-line controller for Prosody XMPP server |
||||
|
||||
-- Will be modified by configure script if run -- |
||||
|
||||
CFG_SOURCEDIR=nil; |
||||
CFG_CONFIGDIR=os.getenv("PROSODY_CFGDIR"); |
||||
CFG_PLUGINDIR=nil; |
||||
CFG_DATADIR=os.getenv("PROSODY_DATADIR"); |
||||
|
||||
-- -- -- -- -- -- -- ---- -- -- -- -- -- -- -- -- |
||||
|
||||
if CFG_SOURCEDIR then |
||||
package.path = CFG_SOURCEDIR.."/?.lua;"..package.path |
||||
package.cpath = CFG_SOURCEDIR.."/?.so;"..package.cpath |
||||
end |
||||
|
||||
if CFG_DATADIR then |
||||
if os.getenv("HOME") then |
||||
CFG_DATADIR = CFG_DATADIR:gsub("^~", os.getenv("HOME")); |
||||
end |
||||
end |
||||
|
||||
-- Required to be able to find packages installed with luarocks |
||||
pcall(require, "luarocks.require") |
||||
|
||||
|
||||
config = require "core.configmanager" |
||||
|
||||
do |
||||
-- TODO: Check for other formats when we add support for them |
||||
-- Use lfs? Make a new conf/ dir? |
||||
local ok, level, err = config.load((CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); |
||||
if not ok then |
||||
print("\n"); |
||||
print("**************************"); |
||||
if level == "parser" then |
||||
print("A problem occured while reading the config file "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); |
||||
local err_line, err_message = tostring(err):match("%[string .-%]:(%d*): (.*)"); |
||||
print("Error"..(err_line and (" on line "..err_line) or "")..": "..(err_message or tostring(err))); |
||||
print(""); |
||||
elseif level == "file" then |
||||
print("Prosody was unable to find the configuration file."); |
||||
print("We looked for: "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); |
||||
print("A sample config file is included in the Prosody download called prosody.cfg.lua.dist"); |
||||
print("Copy or rename it to prosody.cfg.lua and edit as necessary."); |
||||
end |
||||
print("More help on configuring Prosody can be found at http://prosody.im/doc/configure"); |
||||
print("Good luck!"); |
||||
print("**************************"); |
||||
print(""); |
||||
os.exit(1); |
||||
end |
||||
end |
||||
|
||||
local error_messages = setmetatable({ |
||||
["invalid-username"] = "The given username is invalid in a Jabber ID"; |
||||
["invalid-hostname"] = "The given hostname is invalid"; |
||||
["no-password"] = "No password was supplied"; |
||||
["no-such-user"] = "The given user does not exist on the server"; |
||||
}, { __index = function (t,k) return "Error: "..(tostring(k):gsub("%-", " "):gsub("^.", string.upper)); end }); |
||||
|
||||
hosts = {}; |
||||
|
||||
require "core.hostmanager" |
||||
require "core.eventmanager".fire_event("server-starting"); |
||||
|
||||
require "util.prosodyctl" |
||||
----------------------- |
||||
|
||||
function show_message(msg, ...) |
||||
print(msg:format(...)); |
||||
end |
||||
|
||||
function show_warning(msg, ...) |
||||
print(msg:format(...)); |
||||
end |
||||
|
||||
function show_usage(usage, desc) |
||||
print("Usage: "..arg[0].." "..usage); |
||||
if desc then |
||||
print(" "..desc); |
||||
end |
||||
end |
||||
|
||||
local function getchar(n) |
||||
os.execute("stty raw -echo"); |
||||
local char = io.read(n or 1); |
||||
os.execute("stty sane"); |
||||
return char; |
||||
end |
||||
|
||||
local function getpass() |
||||
os.execute("stty -echo"); |
||||
local pass = io.read("*l"); |
||||
os.execute("stty sane"); |
||||
io.write("\n"); |
||||
return pass; |
||||
end |
||||
|
||||
function show_yesno(prompt) |
||||
io.write(prompt, " "); |
||||
local choice = getchar():lower(); |
||||
io.write("\n"); |
||||
if not choice:match("%a") then |
||||
choice = prompt:match("%[.-(%U).-%]$"); |
||||
if not choice then return nil; end |
||||
end |
||||
return (choice == "y"); |
||||
end |
||||
|
||||
local function read_password() |
||||
local password; |
||||
while true do |
||||
io.write("Enter new password: "); |
||||
password = getpass(); |
||||
io.write("Retype new password: "); |
||||
if getpass() ~= password then |
||||
if not show_yesno [=[Passwords did not match, try again? [Y/n]]=] then |
||||
return; |
||||
end |
||||
else |
||||
break; |
||||
end |
||||
end |
||||
return password; |
||||
end |
||||
----------------------- |
||||
local commands = {}; |
||||
local command = arg[1]; |
||||
|
||||
function commands.adduser(arg) |
||||
if not arg[1] or arg[1] == "--help" then |
||||
show_usage([[adduser JID]], [[Create the specified user account in Prosody]]); |
||||
return 1; |
||||
end |
||||
local user, host = arg[1]:match("([^@]+)@(.+)"); |
||||
if not user and host then |
||||
show_message [[Failed to understand JID, please supply the JID you want to create]] |
||||
show_usage [[adduser user@host]] |
||||
return 1; |
||||
end |
||||
|
||||
if not host then |
||||
show_message [[Please specify a JID, including a host. e.g. alice@example.com]]; |
||||
return 1; |
||||
end |
||||
|
||||
if prosodyctl.user_exists{ user = user, host = host } then |
||||
show_message [[That user already exists]]; |
||||
return 1; |
||||
end |
||||
|
||||
if not hosts[host] then |
||||
show_warning("The host '%s' is not listed in the configuration file (or is not enabled).", host) |
||||
show_warning("The user will not be able to log in until this is changed."); |
||||
end |
||||
|
||||
local password = read_password(); |
||||
if not password then return 1; end |
||||
|
||||
local ok, msg = prosodyctl.adduser { user = user, host = host, password = password }; |
||||
|
||||
if ok then return 0; end |
||||
|
||||
show_message(error_messages[msg]) |
||||
return 1; |
||||
end |
||||
|
||||
function commands.passwd(arg) |
||||
if not arg[1] or arg[1] == "--help" then |
||||
show_usage([[passwd JID]], [[Set the password for the specified user account in Prosody]]); |
||||
return 1; |
||||
end |
||||
local user, host = arg[1]:match("([^@]+)@(.+)"); |
||||
if not user and host then |
||||
show_message [[Failed to understand JID, please supply the JID you want to set the password for]] |
||||
show_usage [[passwd user@host]] |
||||
return 1; |
||||
end |
||||
|
||||
if not host then |
||||
show_message [[Please specify a JID, including a host. e.g. alice@example.com]]; |
||||
return 1; |
||||
end |
||||
|
||||
if not prosodyctl.user_exists { user = user, host = host } then |
||||
show_message [[That user does not exist, use prosodyctl adduser to create a new user]] |
||||
return 1; |
||||
end |
||||
|
||||
local password = read_password(); |
||||
if not password then return 1; end |
||||
|
||||
local ok, msg = prosodyctl.passwd { user = user, host = host, password = password }; |
||||
|
||||
if ok then return 0; end |
||||
|
||||
show_message(error_messages[msg]) |
||||
return 1; |
||||
end |
||||
|
||||
function commands.deluser(arg) |
||||
if not arg[1] or arg[1] == "--help" then |
||||
show_usage([[deluser JID]], [[Permanently remove the specified user account from Prosody]]); |
||||
return 1; |
||||
end |
||||
local user, host = arg[1]:match("([^@]+)@(.+)"); |
||||
if not user and host then |
||||
show_message [[Failed to understand JID, please supply the JID you want to set the password for]] |
||||
show_usage [[passwd user@host]] |
||||
return 1; |
||||
end |
||||
|
||||
if not host then |
||||
show_message [[Please specify a JID, including a host. e.g. alice@example.com]]; |
||||
return 1; |
||||
end |
||||
|
||||
if not prosodyctl.user_exists { user = user, host = host } then |
||||
show_message [[That user does not exist on this server]] |
||||
return 1; |
||||
end |
||||
|
||||
local ok, msg = prosodyctl.passwd { user = user, host = host }; |
||||
|
||||
if ok then return 0; end |
||||
|
||||
show_message(error_messages[msg]) |
||||
return 1; |
||||
end |
||||
|
||||
function commands.start() |
||||
local ok, ret = prosodyctl.isrunning(); |
||||
if not ok then |
||||
show_message(error_messages[ret]); |
||||
return 1; |
||||
end |
||||
|
||||
if ret then |
||||
local ok, ret = prosodyctl.getpid(); |
||||
if not ok then |
||||
show_message("Couldn't get running Prosody's PID"); |
||||
show_message(error_messages[ret]); |
||||
return 1; |
||||
end |
||||
show_message("Prosody is already running with PID %s", ret or "(unknown)"); |
||||
return 1; |
||||
end |
||||
|
||||
local ok, ret = prosodyctl.start(); |
||||
if ok then return 0; end |
||||
|
||||
show_message("Failed to start Prosody"); |
||||
show_message(error_messages[ret]) |
||||
return 1; |
||||
end |
||||
|
||||
function commands.status() |
||||
local ok, ret = prosodyctl.isrunning(); |
||||
if not ok then |
||||
show_message(error_messages[ret]); |
||||
return 1; |
||||
end |
||||
|
||||
if ret then |
||||
local ok, ret = prosodyctl.getpid(); |
||||
if not ok then |
||||
show_message("Couldn't get running Prosody's PID"); |
||||
show_message(error_messages[ret]); |
||||
return 1; |
||||
end |
||||
show_message("Prosody is running with PID %s", ret or "(unknown)"); |
||||
return 0; |
||||
end |
||||
return 1; |
||||
end |
||||
|
||||
function commands.stop() |
||||
if not prosodyctl.isrunning() then |
||||
show_message("Prosody is not running"); |
||||
return 1; |
||||
end |
||||
|
||||
local ok, ret = prosodyctl.stop(); |
||||
if ok then return 0; end |
||||
|
||||
show_message(error_messages[ret]) |
||||
return 1; |
||||
end |
||||
|
||||
-- ejabberdctl compatibility |
||||
|
||||
function commands.register(arg) |
||||
local user, host, password = unpack(arg); |
||||
if (not (user and host)) or arg[1] == "--help" then |
||||
if not user and user ~= "--help" then |
||||
show_message [[No username specified]] |
||||
elseif not host then |
||||
show_message [[Please specify which host you want to register the user on]]; |
||||
end |
||||
show_usage("register USER HOST [PASSWORD]", "Register a user on the server, with the given password"); |
||||
return 1; |
||||
end |
||||
if not password then |
||||
password = read_password(); |
||||
if not password then |
||||
show_message [[Unable to register user with no password]]; |
||||
return 1; |
||||
end |
||||
end |
||||
|
||||
local ok, msg = prosodyctl.adduser { user = user, host = host, password = password }; |
||||
|
||||
if ok then return 0; end |
||||
|
||||
show_message(error_messages[msg]) |
||||
return 1; |
||||
end |
||||
|
||||
function commands.unregister(arg) |
||||
local user, host = unpack(arg); |
||||
if (not (user and host)) or arg[1] == "--help" then |
||||
if not user then |
||||
show_message [[No username specified]] |
||||
elseif not host then |
||||
show_message [[Please specify which host you want to unregister the user from]]; |
||||
end |
||||
show_usage("register USER HOST [PASSWORD]", "Permanently remove a user account from the server"); |
||||
return 1; |
||||
end |
||||
|
||||
local ok, msg = prosodyctl.deluser { user = user, host = host }; |
||||
|
||||
if ok then return 0; end |
||||
|
||||
show_message(error_messages[msg]) |
||||
return 1; |
||||
end |
||||
|
||||
|
||||
--------------------- |
||||
|
||||
if not commands[command] then -- Show help for all commands |
||||
function show_usage(usage, desc) |
||||
print(" "..usage); |
||||
print(" "..desc); |
||||
end |
||||
|
||||
print("prosodyctl - Manage a Prosody server"); |
||||
print(""); |
||||
print("Usage: "..arg[0].." COMMAND [OPTIONS]"); |
||||
print(""); |
||||
print("Where COMMAND may be one of:\n"); |
||||
|
||||
local commands_order = { "adduser", "passwd", "deluser" }; |
||||
|
||||
local done = {}; |
||||
|
||||
for _, command_name in ipairs(commands_order) do |
||||
local command = commands[command_name]; |
||||
if command then |
||||
command{ "--help" }; |
||||
print"" |
||||
done[command_name] = true; |
||||
end |
||||
end |
||||
|
||||
for command_name, command in pairs(commands) do |
||||
if not done[command_name] then |
||||
command{ "--help" }; |
||||
print"" |
||||
done[command_name] = true; |
||||
end |
||||
end |
||||
|
||||
|
||||
os.exit(0); |
||||
end |
||||
|
||||
os.exit(commands[command]({ select(2, unpack(arg)) })); |
||||
@ -0,0 +1,113 @@ |
||||
|
||||
local config = require "core.configmanager"; |
||||
local encodings = require "util.encodings"; |
||||
local stringprep = encodings.stringprep; |
||||
local usermanager = require "core.usermanager"; |
||||
local signal = require "util.signal"; |
||||
|
||||
local nodeprep, nameprep = stringprep.nodeprep, stringprep.nameprep; |
||||
|
||||
local io, os = io, os; |
||||
local tostring, tonumber = tostring, tonumber; |
||||
module "prosodyctl" |
||||
|
||||
function adduser(params) |
||||
local user, host, password = nodeprep(params.user), nameprep(params.host), params.password; |
||||
if not user then |
||||
return false, "invalid-username"; |
||||
elseif not host then |
||||
return false, "invalid-hostname"; |
||||
end |
||||
|
||||
usermanager.create_user(user, password, host); |
||||
return true; |
||||
end |
||||
|
||||
function user_exists(params) |
||||
return usermanager.user_exists(params.user, params.host); |
||||
end |
||||
|
||||
function passwd(params) |
||||
if not _M.user_exists(params) then |
||||
return false, "no-such-user"; |
||||
end |
||||
|
||||
return _M.adduser(params); |
||||
end |
||||
|
||||
function deluser(params) |
||||
if not _M.user_exists(params) then |
||||
return false, "no-such-user"; |
||||
end |
||||
params.password = nil; |
||||
|
||||
return _M.adduser(params); |
||||
end |
||||
|
||||
function getpid() |
||||
local pidfile = config.get("*", "core", "pidfile"); |
||||
if not pidfile then |
||||
return false, "no-pidfile"; |
||||
end |
||||
|
||||
local file, err = io.open(pidfile); |
||||
if not file then |
||||
return false, "pidfile-read-failed", ret; |
||||
end |
||||
|
||||
local pid = tonumber(file:read("*a")); |
||||
file:close(); |
||||
|
||||
if not pid then |
||||
return false, "invalid-pid"; |
||||
end |
||||
|
||||
return true, pid; |
||||
end |
||||
|
||||
function isrunning() |
||||
local ok, pid, err = _M.getpid(); |
||||
if not ok then |
||||
if pid == "pidfile-read-failed" then |
||||
-- Report as not running, since we can't open the pidfile |
||||
-- (it probably doesn't exist) |
||||
return true, false; |
||||
end |
||||
return ok, pid; |
||||
end |
||||
return true, signal.kill(pid, 0) == 0; |
||||
end |
||||
|
||||
function start() |
||||
local ok, ret = _M.isrunning(); |
||||
if not ok then |
||||
return ok, ret; |
||||
end |
||||
if ret then |
||||
return false, "already-running"; |
||||
end |
||||
if not CFG_SOURCEDIR then |
||||
os.execute("./prosody"); |
||||
elseif CFG_SOURCEDIR:match("^/usr/local") then |
||||
os.execute("/usr/local/bin/prosody"); |
||||
else |
||||
os.execute("prosody"); |
||||
end |
||||
return true; |
||||
end |
||||
|
||||
function stop() |
||||
local ok, ret = _M.isrunning(); |
||||
if not ok then |
||||
return ok, ret; |
||||
end |
||||
if not ret then |
||||
return false, "not-running"; |
||||
end |
||||
|
||||
local ok, pid = _M.getpid() |
||||
if not ok then return false, pid; end |
||||
|
||||
signal.kill(pid, signal.SIGTERM); |
||||
return true; |
||||
end |
||||
Loading…
Reference in new issue