/src/irssi/src/core/chat-commands.c
Line | Count | Source |
1 | | /* |
2 | | chat-commands.c : irssi |
3 | | |
4 | | Copyright (C) 2000 Timo Sirainen |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 2 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License along |
17 | | with this program; if not, write to the Free Software Foundation, Inc., |
18 | | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | | */ |
20 | | |
21 | | #include "module.h" |
22 | | #include <irssi/src/core/network.h> |
23 | | #include <irssi/src/core/signals.h> |
24 | | #include <irssi/src/core/commands.h> |
25 | | #include <irssi/src/core/special-vars.h> |
26 | | #include <irssi/src/core/settings.h> |
27 | | |
28 | | #include <irssi/src/core/chat-protocols.h> |
29 | | #include <irssi/src/core/servers.h> |
30 | | #include <irssi/src/core/servers-setup.h> |
31 | | #include <irssi/src/core/servers-reconnect.h> |
32 | | #include <irssi/src/core/channels.h> |
33 | | #include <irssi/src/core/chatnets.h> |
34 | | #include <irssi/src/core/queries.h> |
35 | | #include <irssi/src/core/window-item-def.h> |
36 | | #include <irssi/src/core/rawlog.h> |
37 | | |
38 | | static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, |
39 | | char **rawlog_file) |
40 | 0 | { |
41 | 0 | CHAT_PROTOCOL_REC *proto; |
42 | 0 | SERVER_CONNECT_REC *conn; |
43 | 0 | GHashTable *optlist; |
44 | 0 | char *addr, *portstr, *password, *nick, *chatnet, *host; |
45 | 0 | void *free_arg; |
46 | |
|
47 | 0 | g_return_val_if_fail(data != NULL, NULL); |
48 | | |
49 | 0 | if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_OPTIONS, |
50 | 0 | "connect", &optlist, &addr, &portstr, |
51 | 0 | &password, &nick)) |
52 | 0 | return NULL; |
53 | 0 | if (plus_addr != NULL) *plus_addr = *addr == '+'; |
54 | 0 | if (*addr == '+') addr++; |
55 | 0 | if (*addr == '\0') { |
56 | 0 | signal_emit("error command", 1, |
57 | 0 | GINT_TO_POINTER(CMDERR_NOT_ENOUGH_PARAMS)); |
58 | 0 | cmd_params_free(free_arg); |
59 | 0 | return NULL; |
60 | 0 | } |
61 | | |
62 | 0 | if (g_strcmp0(password, "-") == 0) |
63 | 0 | *password = '\0'; |
64 | | |
65 | | /* check if -<chatnet> option is used to specify chat protocol */ |
66 | 0 | proto = chat_protocol_find_net(optlist); |
67 | | |
68 | | /* connect to server */ |
69 | 0 | chatnet = proto == NULL ? NULL : |
70 | 0 | g_hash_table_lookup(optlist, proto->chatnet); |
71 | |
|
72 | 0 | if (chatnet == NULL) |
73 | 0 | chatnet = g_hash_table_lookup(optlist, "network"); |
74 | |
|
75 | 0 | conn = server_create_conn_opt(proto != NULL ? proto->id : -1, addr, atoi(portstr), chatnet, |
76 | 0 | password, nick, optlist); |
77 | 0 | if (conn == NULL) { |
78 | 0 | signal_emit("error command", 1, |
79 | 0 | GINT_TO_POINTER(CMDERR_NO_SERVER_DEFINED)); |
80 | 0 | cmd_params_free(free_arg); |
81 | 0 | return NULL; |
82 | 0 | } |
83 | | |
84 | 0 | if (proto == NULL) |
85 | 0 | proto = chat_protocol_find_id(conn->chat_type); |
86 | |
|
87 | 0 | if (proto->not_initialized) { |
88 | | /* trying to use protocol that isn't yet initialized */ |
89 | 0 | signal_emit("chat protocol unknown", 1, proto->name); |
90 | 0 | server_connect_unref(conn); |
91 | 0 | cmd_params_free(free_arg); |
92 | 0 | return NULL; |
93 | 0 | } |
94 | | |
95 | 0 | if (strchr(addr, '/') != NULL && chatnet_find(addr) == NULL) |
96 | 0 | conn->unix_socket = TRUE; |
97 | | |
98 | | /* TLS options are handled in server_create_conn_opt ... -> server_setup_fill_optlist */ |
99 | |
|
100 | 0 | *rawlog_file = g_strdup(g_hash_table_lookup(optlist, "rawlog")); |
101 | |
|
102 | 0 | host = g_hash_table_lookup(optlist, "host"); |
103 | 0 | if (host != NULL && *host != '\0') { |
104 | 0 | IPADDR ip4 = { 0 }; |
105 | 0 | IPADDR ip6 = { 0 }; |
106 | 0 | if (net_gethostbyname_first_ips(host, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, &ip4, |
107 | 0 | &ip6) == 0) |
108 | 0 | server_connect_own_ip_save(conn, &ip4, &ip6); |
109 | 0 | } |
110 | |
|
111 | 0 | cmd_params_free(free_arg); |
112 | 0 | return conn; |
113 | 0 | } |
114 | | |
115 | | /* SYNTAX: CONNECT [-4 | -6] [-tls_cert <cert>] [-tls_pkey <pkey>] [-tls_pass <password>] |
116 | | [-tls_verify] [-tls_cafile <cafile>] [-tls_capath <capath>] |
117 | | [-tls_ciphers <list>] [-tls_pinned_cert <fingerprint>] |
118 | | [-tls_pinned_pubkey <fingerprint>] [-!] [-noautosendcmd] [-tls | -notls] |
119 | | [-nocap] [-starttls | -disallow_starttls] [-noproxy] |
120 | | [-network <network>] [-host <hostname>] [-rawlog <file>] |
121 | | <address>|<chatnet> [<port> [<password> [<nick>]]] */ |
122 | | /* NOTE: -network replaces the old -ircnet flag. */ |
123 | | static void cmd_connect(const char *data) |
124 | 0 | { |
125 | 0 | SERVER_CONNECT_REC *conn; |
126 | 0 | SERVER_REC *server; |
127 | 0 | char *rawlog_file; |
128 | |
|
129 | 0 | conn = get_server_connect(data, NULL, &rawlog_file); |
130 | 0 | if (conn != NULL) { |
131 | 0 | server = server_connect(conn); |
132 | 0 | server_connect_unref(conn); |
133 | |
|
134 | 0 | if (server != NULL && rawlog_file != NULL) |
135 | 0 | rawlog_open(server->rawlog, rawlog_file); |
136 | |
|
137 | 0 | g_free(rawlog_file); |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | | static RECONNECT_REC *find_reconnect_server(int chat_type, |
142 | | const char *addr, int port) |
143 | 0 | { |
144 | 0 | RECONNECT_REC *match, *last_proto_match; |
145 | 0 | GSList *tmp; |
146 | 0 | int count; |
147 | |
|
148 | 0 | g_return_val_if_fail(addr != NULL, NULL); |
149 | | |
150 | | /* check if there's a reconnection to the same host and maybe even |
151 | | the same port */ |
152 | 0 | match = last_proto_match = NULL; count = 0; |
153 | 0 | for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { |
154 | 0 | RECONNECT_REC *rec = tmp->data; |
155 | |
|
156 | 0 | if (rec->conn->chat_type == chat_type) { |
157 | 0 | count++; last_proto_match = rec; |
158 | 0 | if (g_ascii_strcasecmp(rec->conn->address, addr) == 0) { |
159 | 0 | if (rec->conn->port == port) |
160 | 0 | return rec; |
161 | 0 | match = rec; |
162 | 0 | } |
163 | 0 | } |
164 | 0 | } |
165 | | |
166 | 0 | if (count == 1) { |
167 | | /* only one reconnection with wanted protocol, |
168 | | we probably want to use it */ |
169 | 0 | return last_proto_match; |
170 | 0 | } |
171 | | |
172 | 0 | return match; |
173 | 0 | } |
174 | | |
175 | | static void update_reconnection(SERVER_CONNECT_REC *conn, SERVER_REC *server) |
176 | 0 | { |
177 | 0 | SERVER_CONNECT_REC *oldconn; |
178 | 0 | RECONNECT_REC *recon; |
179 | |
|
180 | 0 | if (server != NULL) { |
181 | 0 | oldconn = server->connrec; |
182 | 0 | server_connect_ref(oldconn); |
183 | 0 | reconnect_save_status(conn, server); |
184 | 0 | } else { |
185 | | /* maybe we can reconnect some server from |
186 | | reconnection queue */ |
187 | 0 | recon = find_reconnect_server(conn->chat_type, |
188 | 0 | conn->address, conn->port); |
189 | 0 | if (recon == NULL) return; |
190 | | |
191 | 0 | oldconn = recon->conn; |
192 | 0 | server_connect_ref(oldconn); |
193 | 0 | server_reconnect_destroy(recon); |
194 | |
|
195 | 0 | conn->away_reason = g_strdup(oldconn->away_reason); |
196 | 0 | conn->channels = g_strdup(oldconn->channels); |
197 | 0 | } |
198 | | |
199 | 0 | conn->reconnection = TRUE; |
200 | |
|
201 | 0 | if (conn->chatnet == NULL && oldconn->chatnet != NULL) |
202 | 0 | conn->chatnet = g_strdup(oldconn->chatnet); |
203 | |
|
204 | 0 | server_connect_unref(oldconn); |
205 | 0 | if (server != NULL) { |
206 | 0 | signal_emit("command disconnect", 2, |
207 | 0 | "* Changing server", server); |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | static void cmd_server(const char *data, SERVER_REC *server, WI_ITEM_REC *item) |
212 | 0 | { |
213 | 0 | command_runsub("server", data, server, item); |
214 | 0 | } |
215 | | |
216 | | /* SYNTAX: SERVER CONNECT [-4 | -6] [-tls | -notls] [-tls_cert <cert>] [-tls_pkey <pkey>] |
217 | | [-tls_pass <password>] [-tls_verify | -notls_verify] [-tls_cafile <cafile>] |
218 | | [-tls_capath <capath>] [-tls_ciphers <list>] |
219 | | [-tls_pinned_cert <fingerprint>] [-tls_pinned_pubkey <fingerprint>] |
220 | | [-!] [-noautosendcmd] [-nocap] |
221 | | [-noproxy] [-network <network>] [-host <hostname>] |
222 | | [-rawlog <file>] |
223 | | [+]<address>|<chatnet> [<port> [<password> [<nick>]]] */ |
224 | | /* NOTE: -network replaces the old -ircnet flag. */ |
225 | | static void cmd_server_connect(const char *data, SERVER_REC *server) |
226 | 0 | { |
227 | 0 | SERVER_CONNECT_REC *conn; |
228 | 0 | char *rawlog_file; |
229 | 0 | int plus_addr; |
230 | |
|
231 | 0 | g_return_if_fail(data != NULL); |
232 | | |
233 | | /* create connection record */ |
234 | 0 | conn = get_server_connect(data, &plus_addr, &rawlog_file); |
235 | 0 | if (conn != NULL) { |
236 | 0 | if (!plus_addr) |
237 | 0 | update_reconnection(conn, server); |
238 | 0 | server = server_connect(conn); |
239 | 0 | server_connect_unref(conn); |
240 | |
|
241 | 0 | if (server != NULL && rawlog_file != NULL) |
242 | 0 | rawlog_open(server->rawlog, rawlog_file); |
243 | |
|
244 | 0 | g_free(rawlog_file); |
245 | 0 | } |
246 | 0 | } |
247 | | |
248 | | /* SYNTAX: DISCONNECT *|<tag> [<message>] */ |
249 | | static void cmd_disconnect(const char *data, SERVER_REC *server) |
250 | 0 | { |
251 | 0 | char *tag, *msg; |
252 | 0 | void *free_arg; |
253 | |
|
254 | 0 | g_return_if_fail(data != NULL); |
255 | | |
256 | 0 | if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) |
257 | 0 | return; |
258 | | |
259 | 0 | if (*tag != '\0' && g_strcmp0(tag, "*") != 0) { |
260 | 0 | server = server_find_tag(tag); |
261 | 0 | if (server == NULL) |
262 | 0 | server = server_find_lookup_tag(tag); |
263 | 0 | } |
264 | 0 | if (server == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); |
265 | | |
266 | 0 | if (*msg == '\0') msg = (char *) settings_get_str("quit_message"); |
267 | 0 | signal_emit("server quit", 2, server, msg); |
268 | |
|
269 | 0 | cmd_params_free(free_arg); |
270 | 0 | server_disconnect(server); |
271 | 0 | } |
272 | | |
273 | | /* SYNTAX: QUIT [<message>] */ |
274 | | static void cmd_quit(const char *data) |
275 | 0 | { |
276 | 0 | GSList *tmp, *next; |
277 | 0 | const char *quitmsg; |
278 | 0 | char *str; |
279 | |
|
280 | 0 | g_return_if_fail(data != NULL); |
281 | | |
282 | 0 | quitmsg = *data != '\0' ? data : |
283 | 0 | settings_get_str("quit_message"); |
284 | | |
285 | | /* disconnect from every server */ |
286 | 0 | for (tmp = servers; tmp != NULL; tmp = next) { |
287 | 0 | next = tmp->next; |
288 | |
|
289 | 0 | str = g_strdup_printf("* %s", quitmsg); |
290 | 0 | cmd_disconnect(str, tmp->data); |
291 | 0 | g_free(str); |
292 | 0 | } |
293 | |
|
294 | 0 | signal_emit("gui exit", 0); |
295 | 0 | } |
296 | | |
297 | | /* SYNTAX: MSG [-<server tag>] [-channel | -nick] *|<targets> <message> */ |
298 | | static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) |
299 | 0 | { |
300 | 0 | GHashTable *optlist; |
301 | 0 | char *target, *origtarget, *msg; |
302 | 0 | void *free_arg; |
303 | 0 | int free_ret, target_type = SEND_TARGET_NICK; |
304 | |
|
305 | 0 | g_return_if_fail(data != NULL); |
306 | | |
307 | 0 | if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | |
308 | 0 | PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, |
309 | 0 | "msg", &optlist, &target, &msg)) |
310 | 0 | return; |
311 | 0 | if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); |
312 | | |
313 | 0 | server = cmd_options_get_server("msg", optlist, server); |
314 | 0 | if (server == NULL || !server->connected) |
315 | 0 | cmd_param_error(CMDERR_NOT_CONNECTED); |
316 | | |
317 | 0 | origtarget = target; |
318 | 0 | free_ret = FALSE; |
319 | 0 | if (g_strcmp0(target, ",") == 0 || g_strcmp0(target, ".") == 0) { |
320 | 0 | target = parse_special(&target, server, item, |
321 | 0 | NULL, &free_ret, NULL, 0); |
322 | 0 | if (target != NULL && *target == '\0') { |
323 | 0 | if (free_ret) |
324 | 0 | g_free(target); |
325 | 0 | target = NULL; |
326 | 0 | free_ret = FALSE; |
327 | 0 | } |
328 | 0 | } |
329 | |
|
330 | 0 | if (target != NULL) { |
331 | 0 | if (g_strcmp0(target, "*") == 0) { |
332 | | /* send to active channel/query */ |
333 | 0 | if (item == NULL) |
334 | 0 | cmd_param_error(CMDERR_NOT_JOINED); |
335 | | |
336 | 0 | target_type = IS_CHANNEL(item) ? |
337 | 0 | SEND_TARGET_CHANNEL : SEND_TARGET_NICK; |
338 | 0 | target = (char *) window_item_get_target(item); |
339 | 0 | } else if (g_hash_table_lookup(optlist, "channel") != NULL) |
340 | 0 | target_type = SEND_TARGET_CHANNEL; |
341 | 0 | else if (g_hash_table_lookup(optlist, "nick") != NULL) |
342 | 0 | target_type = SEND_TARGET_NICK; |
343 | 0 | else { |
344 | | /* Need to rely on server_ischannel(). If the protocol |
345 | | doesn't really know if it's channel or nick based on |
346 | | the name, it should just assume it's nick, because |
347 | | when typing text to channels it's always sent with |
348 | | /MSG -channel. */ |
349 | 0 | target_type = server_ischannel(server, target) ? |
350 | 0 | SEND_TARGET_CHANNEL : SEND_TARGET_NICK; |
351 | 0 | } |
352 | 0 | } |
353 | 0 | if (target != NULL) { |
354 | 0 | char **splitmsgs; |
355 | 0 | char **tmp = NULL; |
356 | 0 | char *singlemsg[] = { msg, NULL }; |
357 | 0 | char *m; |
358 | 0 | int n = 0; |
359 | | |
360 | | /* |
361 | | * If split_message is NULL, the server doesn't need to split |
362 | | * long messages. |
363 | | */ |
364 | 0 | if (server->split_message != NULL) |
365 | 0 | splitmsgs = tmp = server->split_message(server, target, |
366 | 0 | msg); |
367 | 0 | else |
368 | 0 | splitmsgs = singlemsg; |
369 | |
|
370 | 0 | while ((m = splitmsgs[n++])) { |
371 | 0 | signal_emit("server sendmsg", 4, server, target, m, |
372 | 0 | GINT_TO_POINTER(target_type)); |
373 | 0 | signal_emit(target_type == SEND_TARGET_CHANNEL ? |
374 | 0 | "message own_public" : |
375 | 0 | "message own_private", 4, server, m, |
376 | 0 | target, origtarget); |
377 | 0 | } |
378 | 0 | g_strfreev(tmp); |
379 | 0 | } else { |
380 | 0 | signal_emit("message own_private", 4, server, msg, target, |
381 | 0 | origtarget); |
382 | 0 | } |
383 | |
|
384 | 0 | if (free_ret && target != NULL) g_free(target); |
385 | 0 | cmd_params_free(free_arg); |
386 | 0 | } |
387 | | |
388 | | static void sig_server_sendmsg(SERVER_REC *server, const char *target, |
389 | | const char *msg, void *target_type_p) |
390 | 0 | { |
391 | 0 | server->send_message(server, target, msg, |
392 | 0 | GPOINTER_TO_INT(target_type_p)); |
393 | 0 | } |
394 | | |
395 | | static void cmd_foreach(const char *data, SERVER_REC *server, |
396 | | WI_ITEM_REC *item) |
397 | 0 | { |
398 | 0 | command_runsub("foreach", data, server, item); |
399 | 0 | } |
400 | | |
401 | | /* SYNTAX: FOREACH SERVER <command> */ |
402 | | static void cmd_foreach_server(const char *data, SERVER_REC *server) |
403 | 0 | { |
404 | 0 | GSList *list; |
405 | 0 | const char *cmdchars; |
406 | 0 | char *str; |
407 | |
|
408 | 0 | cmdchars = settings_get_str("cmdchars"); |
409 | 0 | str = strchr(cmdchars, *data) != NULL ? g_strdup(data) : |
410 | 0 | g_strdup_printf("%c%s", *cmdchars, data); |
411 | |
|
412 | 0 | list = g_slist_copy(servers); |
413 | 0 | while (list != NULL) { |
414 | 0 | signal_emit("send command", 3, str, list->data, NULL); |
415 | 0 | list = g_slist_remove(list, list->data); |
416 | 0 | } |
417 | |
|
418 | 0 | g_free(str); |
419 | 0 | } |
420 | | |
421 | | /* SYNTAX: FOREACH CHANNEL <command> */ |
422 | | static void cmd_foreach_channel(const char *data) |
423 | 0 | { |
424 | 0 | GSList *list; |
425 | 0 | const char *cmdchars; |
426 | 0 | char *str; |
427 | |
|
428 | 0 | cmdchars = settings_get_str("cmdchars"); |
429 | 0 | str = strchr(cmdchars, *data) != NULL ? g_strdup(data) : |
430 | 0 | g_strdup_printf("%c%s", *cmdchars, data); |
431 | |
|
432 | 0 | list = g_slist_copy(channels); |
433 | 0 | while (list != NULL) { |
434 | 0 | CHANNEL_REC *rec = list->data; |
435 | |
|
436 | 0 | signal_emit("send command", 3, str, rec->server, rec); |
437 | 0 | list = g_slist_remove(list, list->data); |
438 | 0 | } |
439 | |
|
440 | 0 | g_free(str); |
441 | 0 | } |
442 | | |
443 | | /* SYNTAX: FOREACH QUERY <command> */ |
444 | | static void cmd_foreach_query(const char *data) |
445 | 0 | { |
446 | 0 | GSList *list; |
447 | 0 | const char *cmdchars; |
448 | 0 | char *str; |
449 | |
|
450 | 0 | cmdchars = settings_get_str("cmdchars"); |
451 | 0 | str = strchr(cmdchars, *data) != NULL ? g_strdup(data) : |
452 | 0 | g_strdup_printf("%c%s", *cmdchars, data); |
453 | | |
454 | |
|
455 | 0 | list = g_slist_copy(queries); |
456 | 0 | while (list != NULL) { |
457 | 0 | QUERY_REC *rec = list->data; |
458 | |
|
459 | 0 | signal_emit("send command", 3, str, rec->server, rec); |
460 | 0 | list = g_slist_remove(list, list->data); |
461 | 0 | } |
462 | |
|
463 | 0 | g_free(str); |
464 | 0 | } |
465 | | |
466 | | void chat_commands_init(void) |
467 | 8 | { |
468 | 8 | settings_add_str("misc", "quit_message", "leaving"); |
469 | | |
470 | 8 | command_bind("server", NULL, (SIGNAL_FUNC) cmd_server); |
471 | 8 | command_bind("server connect", NULL, (SIGNAL_FUNC) cmd_server_connect); |
472 | 8 | command_bind("connect", NULL, (SIGNAL_FUNC) cmd_connect); |
473 | 8 | command_bind("disconnect", NULL, (SIGNAL_FUNC) cmd_disconnect); |
474 | 8 | command_bind("quit", NULL, (SIGNAL_FUNC) cmd_quit); |
475 | 8 | command_bind("msg", NULL, (SIGNAL_FUNC) cmd_msg); |
476 | 8 | command_bind("foreach", NULL, (SIGNAL_FUNC) cmd_foreach); |
477 | 8 | command_bind("foreach server", NULL, (SIGNAL_FUNC) cmd_foreach_server); |
478 | 8 | command_bind("foreach channel", NULL, (SIGNAL_FUNC) cmd_foreach_channel); |
479 | 8 | command_bind("foreach query", NULL, (SIGNAL_FUNC) cmd_foreach_query); |
480 | | |
481 | 8 | signal_add("server sendmsg", (SIGNAL_FUNC) sig_server_sendmsg); |
482 | | |
483 | 8 | command_set_options( |
484 | 8 | "connect", |
485 | 8 | "4 6 !! -network ~ssl ~+ssl_cert ~+ssl_pkey ~+ssl_pass ~ssl_verify ~+ssl_cafile " |
486 | 8 | "~+ssl_capath ~+ssl_ciphers ~+ssl_pinned_cert ~+ssl_pinned_pubkey tls notls +tls_cert " |
487 | 8 | "+tls_pkey +tls_pass tls_verify notls_verify +tls_cafile +tls_capath +tls_ciphers " |
488 | 8 | "+tls_pinned_cert +tls_pinned_pubkey +host noproxy -rawlog noautosendcmd"); |
489 | 8 | command_set_options("msg", "channel nick"); |
490 | 8 | } |
491 | | |
492 | | void chat_commands_deinit(void) |
493 | 0 | { |
494 | 0 | command_unbind("server", (SIGNAL_FUNC) cmd_server); |
495 | 0 | command_unbind("server connect", (SIGNAL_FUNC) cmd_server_connect); |
496 | 0 | command_unbind("connect", (SIGNAL_FUNC) cmd_connect); |
497 | 0 | command_unbind("disconnect", (SIGNAL_FUNC) cmd_disconnect); |
498 | 0 | command_unbind("quit", (SIGNAL_FUNC) cmd_quit); |
499 | 0 | command_unbind("msg", (SIGNAL_FUNC) cmd_msg); |
500 | 0 | command_unbind("foreach", (SIGNAL_FUNC) cmd_foreach); |
501 | 0 | command_unbind("foreach server", (SIGNAL_FUNC) cmd_foreach_server); |
502 | 0 | command_unbind("foreach channel", (SIGNAL_FUNC) cmd_foreach_channel); |
503 | 0 | command_unbind("foreach query", (SIGNAL_FUNC) cmd_foreach_query); |
504 | |
|
505 | | signal_remove("server sendmsg", (SIGNAL_FUNC) sig_server_sendmsg); |
506 | 0 | } |