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)) }));