2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
10 local config = require "core.configmanager";
11 local encodings = require "util.encodings";
12 local stringprep = encodings.stringprep;
13 local storagemanager = require "core.storagemanager";
14 local usermanager = require "core.usermanager";
15 local signal = require "util.signal";
16 local set = require "util.set";
17 local lfs = require "lfs";
21 local nodeprep, nameprep = stringprep.nodeprep, stringprep.nameprep;
23 local io, os = io, os;
25 local tostring, tonumber = tostring, tonumber;
27 local CFG_SOURCEDIR = _G.CFG_SOURCEDIR;
30 local prosody = prosody;
35 function show_message(msg, ...)
36 print(msg:format(...));
39 function show_warning(msg, ...)
40 print(msg:format(...));
43 function show_usage(usage, desc)
44 print("Usage: ".._G.arg[0].." "..usage);
51 local stty_ret = os.execute("stty raw -echo 2>/dev/null");
54 ok, char = pcall(io.read, n or 1);
55 os.execute("stty sane");
57 ok, char = pcall(io.read, "*l");
59 char = char:sub(1, n or 1);
68 local ok, line = pcall(io.read, "*l");
75 local stty_ret = os.execute("stty -echo 2>/dev/null");
77 io.write("\027[08m"); -- ANSI 'hidden' text attribute
79 local ok, pass = pcall(io.read, "*l");
81 os.execute("stty sane");
91 function show_yesno(prompt)
92 io.write(prompt, " ");
93 local choice = getchar():lower();
95 if not choice:match("%a") then
96 choice = prompt:match("%[.-(%U).-%]$");
97 if not choice then return nil; end
99 return (choice == "y");
102 function read_password()
105 io.write("Enter new password: ");
106 password = getpass();
108 show_message("No password - cancelled");
111 io.write("Retype new password: ");
112 if getpass() ~= password then
113 if not show_yesno [=[Passwords did not match, try again? [Y/n]]=] then
123 function show_prompt(prompt)
124 io.write(prompt, " ");
125 local line = getline();
126 line = line and line:gsub("\n$","");
127 return (line and #line > 0) and line or nil;
131 function adduser(params)
132 local user, host, password = nodeprep(params.user), nameprep(params.host), params.password;
134 return false, "invalid-username";
136 return false, "invalid-hostname";
139 local host_session = prosody.hosts[host];
140 if not host_session then
141 return false, "no-such-host";
144 storagemanager.initialize_host(host);
145 local provider = host_session.users;
146 if not(provider) or provider.name == "null" then
147 usermanager.initialize_host(host);
150 local ok, errmsg = usermanager.create_user(user, password, host);
152 return false, errmsg;
157 function user_exists(params)
158 local user, host, password = nodeprep(params.user), nameprep(params.host), params.password;
160 storagemanager.initialize_host(host);
161 local provider = prosody.hosts[host].users;
162 if not(provider) or provider.name == "null" then
163 usermanager.initialize_host(host);
166 return usermanager.user_exists(user, host);
169 function passwd(params)
170 if not _M.user_exists(params) then
171 return false, "no-such-user";
174 return _M.adduser(params);
177 function deluser(params)
178 if not _M.user_exists(params) then
179 return false, "no-such-user";
181 local user, host = nodeprep(params.user), nameprep(params.host);
183 return usermanager.delete_user(user, host);
187 local pidfile = config.get("*", "pidfile");
189 return false, "no-pidfile";
192 if type(pidfile) ~= "string" then
193 return false, "invalid-pidfile";
196 local modules_enabled = set.new(config.get("*", "modules_disabled"));
197 if prosody.platform ~= "posix" or modules_enabled:contains("posix") then
198 return false, "no-posix";
201 local file, err = io.open(pidfile, "r+");
203 return false, "pidfile-read-failed", err;
206 local locked, err = lfs.lock(file, "w");
209 return false, "pidfile-not-locked";
212 local pid = tonumber(file:read("*a"));
216 return false, "invalid-pid";
223 local ok, pid, err = _M.getpid();
225 if pid == "pidfile-read-failed" or pid == "pidfile-not-locked" then
226 -- Report as not running, since we can't open the pidfile
227 -- (it probably doesn't exist)
232 return true, signal.kill(pid, 0) == 0;
236 local ok, ret = _M.isrunning();
241 return false, "already-running";
243 if not CFG_SOURCEDIR then
244 os.execute("./prosody");
246 os.execute(CFG_SOURCEDIR.."/../../bin/prosody");
252 local ok, ret = _M.isrunning();
257 return false, "not-running";
260 local ok, pid = _M.getpid()
261 if not ok then return false, pid; end
263 signal.kill(pid, signal.SIGTERM);
268 local ok, ret = _M.isrunning();
273 return false, "not-running";
276 local ok, pid = _M.getpid()
277 if not ok then return false, pid; end
279 signal.kill(pid, signal.SIGHUP);