Merge with backout
[prosody.git] / util / prosodyctl.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 -- 
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9
10 local config = require "core.configmanager";
11 local encodings = require "util.encodings";
12 local stringprep = encodings.stringprep;
13 local usermanager = require "core.usermanager";
14 local signal = require "util.signal";
15 local lfs = require "lfs";
16
17 local nodeprep, nameprep = stringprep.nodeprep, stringprep.nameprep;
18
19 local io, os = io, os;
20 local tostring, tonumber = tostring, tonumber;
21
22 local CFG_SOURCEDIR = _G.CFG_SOURCEDIR;
23
24 module "prosodyctl"
25
26 function adduser(params)
27         local user, host, password = nodeprep(params.user), nameprep(params.host), params.password;
28         if not user then
29                 return false, "invalid-username";
30         elseif not host then
31                 return false, "invalid-hostname";
32         end
33         
34         local ok = usermanager.create_user(user, password, host);
35         if not ok then
36                 return false, "unable-to-save-data";
37         end
38         return true;
39 end
40
41 function user_exists(params)
42         return usermanager.user_exists(params.user, params.host);
43 end
44
45 function passwd(params)
46         if not _M.user_exists(params) then
47                 return false, "no-such-user";
48         end
49         
50         return _M.adduser(params);
51 end
52
53 function deluser(params)
54         if not _M.user_exists(params) then
55                 return false, "no-such-user";
56         end
57         params.password = nil;
58         
59         return _M.adduser(params);
60 end
61
62 function getpid()
63         local pidfile = config.get("*", "core", "pidfile");
64         if not pidfile then
65                 return false, "no-pidfile";
66         end
67         
68         local file, err = io.open(pidfile, "r+");
69         if not file then
70                 return false, "pidfile-read-failed", err;
71         end
72         
73         local locked, err = lfs.lock(file, "w");
74         if locked then
75                 file:close();
76                 return false, "pidfile-not-locked";
77         end
78         
79         local pid = tonumber(file:read("*a"));
80         file:close();
81         
82         if not pid then
83                 return false, "invalid-pid";
84         end
85         
86         return true, pid;
87 end
88
89 function isrunning()
90         local ok, pid, err = _M.getpid();
91         if not ok then
92                 if pid == "pidfile-read-failed" or pid == "pidfile-not-locked" then
93                         -- Report as not running, since we can't open the pidfile
94                         -- (it probably doesn't exist)
95                         return true, false;
96                 end
97                 return ok, pid;
98         end
99         return true, signal.kill(pid, 0) == 0;
100 end
101
102 function start()
103         local ok, ret = _M.isrunning();
104         if not ok then
105                 return ok, ret;
106         end
107         if ret then
108                 return false, "already-running";
109         end
110         if not CFG_SOURCEDIR then
111                 os.execute("./prosody");
112         else
113                 os.execute(CFG_SOURCEDIR.."/../../bin/prosody");
114         end
115         return true;
116 end
117
118 function stop()
119         local ok, ret = _M.isrunning();
120         if not ok then
121                 return ok, ret;
122         end
123         if not ret then
124                 return false, "not-running";
125         end
126         
127         local ok, pid = _M.getpid()
128         if not ok then return false, pid; end
129         
130         signal.kill(pid, signal.SIGTERM);
131         return true;
132 end