2
ctrlproxy: A modular IRC proxy
3
admin: module for remote administration. Available commands:
5
* ADDLISTEN <network> <type> [<key>=<value>] [...]
6
* ADDSERVER <network> <type> [<key>=<value>] [...]
9
* DISCONNECT [<network>]
11
* LOADMODULE <location>
12
* RELOADMODULE <location>
13
* UNLOADMODULE <location>
19
(c) 2003 Jelmer Vernooij <jelmer@nl.linux.org>
21
This program is free software; you can redistribute it and/or modify
22
it under the terms of the GNU General Public License as published by
23
the Free Software Foundation; either version 2 of the License, or
24
(at your option) any later version.
26
This program is distributed in the hope that it will be useful,
27
but WITHOUT ANY WARRANTY; without even the implied warranty of
28
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
GNU General Public License for more details.
31
You should have received a copy of the GNU General Public License
32
along with this program; if not, write to the Free Software
33
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37
#include "ctrlproxy.h"
40
static gboolean with_privmsg = FALSE;
41
static GList *commands = NULL;
43
struct admin_command {
45
void (*handler) (char **args, struct line *l);
48
void admin_out(struct line *l, char *fmt, ...)
51
char *msg, *tot, *server_name;
54
vasprintf(&msg, fmt, ap);
57
nick = xmlGetProp(l->network->xmlConf, "nick");
58
server_name = xmlGetProp(l->network->xmlConf, "name");
60
asprintf(&tot, ":ctrlproxy!ctrlproxy@%s PRIVMSG %s :%s\r\n", server_name, nick, msg);
63
transport_write(l->client->incoming, tot);
69
xmlNodePtr find_network_xml(char *name)
72
xmlNodePtr cur = xmlNode_networks->xmlChildrenNode;
75
nname = xmlGetProp(cur, "name");
76
if(nname && !strcmp(nname, name)){xmlFree(nname); return cur; }
83
struct network *find_network_struct(char *name)
88
struct network *n = (struct network *)g->data;
89
nname = xmlGetProp(n->xmlConf, "name");
90
if(!strcmp(nname, name)){ xmlFree(nname); return n; }
97
static void add_network (char **args, struct line *l)
101
admin_out(l, "No name specified");
105
if(find_network_xml(args[1])) {
106
admin_out(l, "Such a network already exists");
110
/* Add node to networks node with specified name */
111
cur = xmlNewNode(NULL, "network");
112
xmlSetProp(cur, "name", args[1]);
113
xmlAddChild(xmlNode_networks, cur);
115
/* Add a 'servers' element */
116
xmlAddChild(cur, xmlNewNode(NULL, "servers"));
119
static void add_listen (char **args, struct line *l)
121
xmlNodePtr net, serv, listen;
125
if(!args[1] || !args[2]) {
126
admin_out(l, "Not enough parameters");
130
net = find_network_xml(args[1]);
132
/* Add network if it didn't exist yet */
134
/* Add node to networks node with specified name */
135
net = xmlNewNode(NULL, "network");
136
xmlSetProp(net, "name", args[1]);
137
xmlAddChild(xmlNode_networks, net);
139
/* Add a 'listen' element */
140
xmlAddChild(net, xmlNewNode(NULL, "listen"));
143
listen = xmlFindChildByElementName(net, "listen");
145
/* Add listen node if it didn't exist yet */
147
listen = xmlNewNode(NULL, "listen");
148
xmlAddChild(net, listen);
151
serv = xmlNewNode(NULL, args[2]);
152
xmlAddChild(listen, serv);
154
for(i = 3; args[i]; i++) {
155
char *val = strchr(args[i], '=');
157
admin_out(l, "Properties should be in the format 'key=value'");
161
xmlSetProp(serv, args[i], val);
164
/* In case the network is active */
165
n = find_network_struct(args[1]);
167
if(!n->listen)n->listen = listen;
168
network_add_listen(n, serv);
172
static void add_server (char **args, struct line *l)
174
xmlNodePtr net, serv, servers;
177
if(!args[1] || !args[2]) {
178
admin_out(l, "Not enough parameters");
182
net = find_network_xml(args[1]);
184
/* Add network if it didn't exist yet */
186
/* Add node to networks node with specified name */
187
net = xmlNewNode(NULL, "network");
188
xmlSetProp(net, "name", args[1]);
189
xmlAddChild(xmlNode_networks, net);
191
/* Add a 'servers' element */
192
xmlAddChild(net, xmlNewNode(NULL, "servers"));
195
servers = xmlFindChildByElementName(net, "servers");
197
/* Add servers node if it didn't exist yet */
199
servers = xmlNewNode(NULL, "servers");
200
xmlAddChild(net, servers);
203
serv = xmlNewNode(NULL, args[2]);
204
xmlAddChild(servers, serv);
206
for(i = 3; args[i]; i++) {
207
char *val = strchr(args[i], '=');
209
admin_out(l, "Properties should be in the format 'key=value'");
213
xmlSetProp(serv, args[i], val);
217
static void connect_network (char **args, struct line *l)
221
admin_out(l, "No network specified");
225
n = find_network_xml(args[1]);
227
admin_out(l, "Can't find network named %s", args[1]);
231
g_message("Connecting to %s", args[1]);
233
connect_to_server(n);
236
static void disconnect_network (char **args, struct line *l)
239
if(!args[1])n = l->network;
241
n = find_network_struct(args[1]);
243
admin_out(l, "Can't find network with that name");
251
static void list_modules (char **args, struct line *l)
255
struct plugin *p = (struct plugin *)g->data;
256
admin_out(l, "%s", p->name);
261
static void unload_module (char **args, struct line *l)
266
admin_out(l, "Not enough arguments");
270
if(!strcmp(args[1], "admin")) {
271
admin_out(l, "Can't unload /this/ module");
275
/* Find specified plugins' GModule and xmlNodePtr */
277
struct plugin *p = (struct plugin *)g->data;
278
if(!strcmp(p->name, args[1])) {
279
if(unload_plugin(p)) plugins = g_list_remove(plugins, p);
285
admin_out(l, "No such plugin loaded");
288
static void load_module (char **args, struct line *l)
292
admin_out(l, "No file specified");
296
if(!strcmp(args[1], "admin")) {
297
admin_out(l, "Can't load this module /again/");
301
cur = xmlNewNode(NULL, "plugin");
302
xmlSetProp(cur, "file", args[1]);
303
xmlAddChild(xmlNode_plugins, cur);
309
static void reload_module (char **args, struct line *l)
311
unload_module(args, l);
312
load_module(args, l);
315
static void dump_config (char **args, struct line *l)
322
xmlDocDumpMemory(configuration, &buffer, &size);
323
for(i = 0; i < size; i++)
325
/* If we encounter a newline or a null-character, we
326
* print the last line */
327
if(buffer[i] != '\n' && buffer[i] != '\0') continue;
329
tmp = strndup(buffer + lastend, i - lastend);
336
static void save_config (char **args, struct line *l)
337
{ save_configuration(); }
339
static void help (char **args, struct line *l)
342
GList *gl = commands;
344
struct admin_command *cmd = (struct admin_command *)gl->data;
345
admin_out(l, cmd->name);
350
static void list_networks(char **args, struct line *l)
355
struct network *n = (struct network *)g->data;
356
nname = xmlGetProp(n->xmlConf, "name");
363
static void handle_die(char **args, struct line *l)
370
void register_admin_command(char *name, void (*handler) (char **args, struct line *l))
372
struct admin_command *cmd = malloc(sizeof(struct admin_command));
373
cmd->name = strdup(name);
374
cmd->handler = handler;
375
commands = g_list_append(commands, cmd);
378
void unregister_admin_command(char *name)
380
GList *gl = commands;
382
struct admin_command *cmd = (struct admin_command *)gl->data;
383
if(!strcasecmp(cmd->name, name)) {
385
commands = g_list_remove(gl, cmd);
393
struct admin_command builtin_commands[] = {
394
{ "ADDNETWORK", add_network },
395
{ "ADDSERVER", add_server },
396
{ "ADDLISTEN", add_listen },
397
{ "CONNECT", connect_network },
398
{ "DIE", handle_die },
399
{ "DISCONNECT", disconnect_network },
400
{ "LISTNETWORKS", list_networks },
401
{ "LOADMODULE", load_module },
402
{ "UNLOADMODULE", unload_module },
403
{ "RELOADMODULE", reload_module },
404
{ "LISTMODULES", list_modules },
405
{ "DUMPCONFIG", dump_config },
406
{ "SAVECONFIG", save_config },
411
static gboolean handle_data(struct line *l) {
412
char *tmp, **args = NULL, *p, *n;
417
if(l->direction != TO_SERVER) return TRUE;
418
if(strcasecmp(l->args[0], "CTRLPROXY") == 0)cmdoffset = 1;
419
if(with_privmsg && strcasecmp(l->args[0], "PRIVMSG") == 0 &&
420
strcasecmp(l->args[1], "CTRLPROXY") == 0) cmdoffset = 2;
422
if(cmdoffset == 0) return TRUE;
424
args = malloc(sizeof(char *) * 2);
425
l->options |= LINE_DONT_SEND | LINE_IS_PRIVATE;
426
tmp = strdup(l->args[cmdoffset]);
430
while((n = strchr(p, ' '))) {
431
args = realloc(args, (curarg + 2) * sizeof(char *));
432
args[++curarg] = n+1;
436
args[++curarg] = NULL;
438
/* Ok, arguments are processed now. Execute the corresponding command */
441
struct admin_command *cmd = (struct admin_command *)gl->data;
442
if(!strcasecmp(cmd->name, args[0])) {
443
cmd->handler(args, l);
450
admin_out(l, "Can't find command '%s'", args[0]);
458
gboolean fini_plugin(struct plugin *p) {
459
del_filter(handle_data);
463
gboolean init_plugin(struct plugin *p) {
467
add_filter("admin", handle_data);
468
cur = xmlFindChildByElementName(p->xmlConf, "with_privmsg");
469
if(cur) with_privmsg = TRUE;
471
for(i = 0; builtin_commands[i].name; i++) {
472
register_admin_command(builtin_commands[i].name, builtin_commands[i].handler);