Parent Directory
|
Revision Log
|
Revision Graph
* Removed share.mod (will be part of the new botnet module). * More transfer removal. * More botnet removal. * Regenerated gettext stuff. * More doc stuff. * Removed eggdrop.conf (replaced by config.tcl for now).
1 | /* |
2 | * cmds.c -- |
3 | * |
4 | * commands from a user via dcc |
5 | * (split in 2, this portion contains no-irc commands) |
6 | */ |
7 | /* |
8 | * Copyright (C) 1997 Robey Pointer |
9 | * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team |
10 | * |
11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License |
13 | * as published by the Free Software Foundation; either version 2 |
14 | * of the License, or (at your option) any later version. |
15 | * |
16 | * This program is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU General Public License for more details. |
20 | * |
21 | * You should have received a copy of the GNU General Public License |
22 | * along with this program; if not, write to the Free Software |
23 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
24 | */ |
25 | |
26 | #ifndef lint |
27 | static const char rcsid[] = "$Id: cmds.c,v 1.114 2003/02/15 00:23:51 wcc Exp $"; |
28 | #endif |
29 | |
30 | #include "main.h" |
31 | #include "modules.h" |
32 | #include "logfile.h" |
33 | #include "misc.h" |
34 | #include "cmdt.h" /* cmd_t */ |
35 | #include "core_binds.h" /* check_bind_act, check_bind_chpt, |
36 | check_bind_chjn, check_bind_chof */ |
37 | #include "users.h" /* get_user_by_host, set_user, |
38 | USERENTRY_PASS */ |
39 | #include "chanprog.h" /* masktype, tell_verbose_status, |
40 | tell_settings, maskname, logmodes |
41 | isowner, reload */ |
42 | #include "dccutil.h" /* dprintf_eggdrop, not_away, set_away |
43 | tell_dcc, do_boot, chanout_but, |
44 | dcc_chatter, flush_lines */ |
45 | #include "net.h" /* tell_netdebug, killsock */ |
46 | #include "cmds.h" /* prototypes */ |
47 | |
48 | #include <ctype.h> |
49 | #include "traffic.h" /* egg_traffic_t */ |
50 | |
51 | extern struct chanset_t *chanset; |
52 | extern struct dcc_t *dcc; |
53 | extern user_t *userlist; |
54 | extern int dcc_total, backgrd, make_userfile, do_restart, conmask, strict_host, |
55 | term_z, con_chan; |
56 | extern egg_traffic_t traffic; |
57 | extern char myname[], ver[], network[], owner[], spaces[], quit_msg[]; |
58 | extern time_t now, online_since; |
59 | extern module_entry *module_list; |
60 | |
61 | #ifndef MAKING_MODS |
62 | extern struct dcc_table DCC_CHAT, DCC_BOT, DCC_RELAY, DCC_FORK_BOT, |
63 | DCC_CHAT_PASS; |
64 | #endif /* MAKING_MODS */ |
65 | |
66 | static char *btos(unsigned long); |
67 | |
68 | |
69 | static void tell_who(user_t *u, int idx, int chan) |
70 | { |
71 | int i, k, ok = 0, atr = u ? u->flags : 0, len; |
72 | char s[1024]; /* temp fix - 1.4 has a better one */ |
73 | |
74 | if (!chan) |
75 | dprintf(idx, "Party line members: (* = owner, + = master, @ = op)\n"); |
76 | else { |
77 | dprintf(idx, |
78 | "People on channel %s%d: (* = owner, + = master, @ = op)\n", |
79 | (chan < 100000) ? "" : "*", chan % 100000); |
80 | } |
81 | for (i = 0; i < dcc_total; i++) |
82 | if (dcc[i].type == &DCC_CHAT) |
83 | if (dcc[i].u.chat->channel == chan) { |
84 | spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0; |
85 | if (atr & USER_OWNER) { |
86 | sprintf(s, " [%.2lu] %c%s%s %s", dcc[i].sock, |
87 | (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)), |
88 | dcc[i].nick, spaces, dcc[i].host); |
89 | } else { |
90 | sprintf(s, " %c%s%s %s", |
91 | (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)), |
92 | dcc[i].nick, spaces, dcc[i].host); |
93 | } |
94 | spaces[len] = ' '; |
95 | if (atr & USER_MASTER) { |
96 | if (dcc[i].u.chat->con_flags) |
97 | sprintf(&s[strlen(s)], " (con:%s)", |
98 | masktype(dcc[i].u.chat->con_flags)); |
99 | } |
100 | if (now - dcc[i].timeval > 300) { |
101 | unsigned long days, hrs, mins; |
102 | |
103 | days = (now - dcc[i].timeval) / 86400; |
104 | hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600; |
105 | mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60; |
106 | if (days > 0) |
107 | sprintf(&s[strlen(s)], " (idle %lud%luh)", days, hrs); |
108 | else if (hrs > 0) |
109 | sprintf(&s[strlen(s)], " (idle %luh%lum)", hrs, mins); |
110 | else |
111 | sprintf(&s[strlen(s)], " (idle %lum)", mins); |
112 | } |
113 | dprintf(idx, "%s\n", s); |
114 | if (dcc[i].u.chat->away != NULL) |
115 | dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away); |
116 | } |
117 | ok = 0; |
118 | for (i = 0; i < dcc_total; i++) { |
119 | if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->channel != chan)) { |
120 | if (!ok) { |
121 | ok = 1; |
122 | dprintf(idx, _("Other people on the bot:\n")); |
123 | } |
124 | spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0; |
125 | if (atr & USER_OWNER) { |
126 | sprintf(s, " [%.2lu] %c%s%s ", |
127 | dcc[i].sock, |
128 | (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)), |
129 | dcc[i].nick, spaces); |
130 | } else { |
131 | sprintf(s, " %c%s%s ", |
132 | (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)), |
133 | dcc[i].nick, spaces); |
134 | } |
135 | spaces[len] = ' '; |
136 | if (atr & USER_MASTER) { |
137 | if (dcc[i].u.chat->channel < 0) |
138 | strcat(s, "(-OFF-) "); |
139 | else if (!dcc[i].u.chat->channel) |
140 | strcat(s, "(party) "); |
141 | else |
142 | sprintf(&s[strlen(s)], "(%5d) ", dcc[i].u.chat->channel); |
143 | } |
144 | strcat(s, dcc[i].host); |
145 | if (atr & USER_MASTER) { |
146 | if (dcc[i].u.chat->con_flags) |
147 | sprintf(&s[strlen(s)], " (con:%s)", |
148 | masktype(dcc[i].u.chat->con_flags)); |
149 | } |
150 | if (now - dcc[i].timeval > 300) { |
151 | k = (now - dcc[i].timeval) / 60; |
152 | if (k < 60) |
153 | sprintf(&s[strlen(s)], " (idle %dm)", k); |
154 | else |
155 | sprintf(&s[strlen(s)], " (idle %dh%dm)", k / 60, k % 60); |
156 | } |
157 | dprintf(idx, "%s\n", s); |
158 | if (dcc[i].u.chat->away != NULL) |
159 | dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away); |
160 | } |
161 | if ((atr & USER_MASTER) && dcc[i].type && (dcc[i].type->flags & DCT_SHOWWHO) && |
162 | (dcc[i].type != &DCC_CHAT)) { |
163 | if (!ok) { |
164 | ok = 1; |
165 | dprintf(idx, _("Other people on the bot:\n")); |
166 | } |
167 | spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0; |
168 | if (atr & USER_OWNER) { |
169 | sprintf(s, " [%.2lu] %c%s%s (files) %s", |
170 | dcc[i].sock, dcc[i].status & STAT_CHAT ? '+' : ' ', |
171 | dcc[i].nick, spaces, dcc[i].host); |
172 | } else { |
173 | sprintf(s, " %c%s%s (files) %s", |
174 | dcc[i].status & STAT_CHAT ? '+' : ' ', |
175 | dcc[i].nick, spaces, dcc[i].host); |
176 | } |
177 | spaces[len] = ' '; |
178 | dprintf(idx, "%s\n", s); |
179 | } |
180 | } |
181 | } |
182 | |
183 | static int cmd_me(user_t *u, int idx, char *par) |
184 | { |
185 | int i; |
186 | |
187 | if (dcc[idx].u.chat->channel < 0) { |
188 | dprintf(idx, _("You have chat turned off.\n")); |
189 | return(0); |
190 | } |
191 | if (!par[0]) { |
192 | dprintf(idx, "Usage: me <action>\n"); |
193 | return(0); |
194 | } |
195 | if (dcc[idx].u.chat->away != NULL) |
196 | not_away(idx); |
197 | for (i = 0; i < dcc_total; i++) |
198 | check_bind_act(dcc[idx].nick, dcc[idx].u.chat->channel, par); |
199 | return(0); |
200 | } |
201 | |
202 | static int cmd_motd(user_t *u, int idx, char *par) |
203 | { |
204 | show_motd(idx); |
205 | return(1); |
206 | } |
207 | |
208 | static int cmd_away(user_t *u, int idx, char *par) |
209 | { |
210 | if (strlen(par) > 60) |
211 | par[60] = 0; |
212 | set_away(idx, par); |
213 | return(1); |
214 | } |
215 | |
216 | static int cmd_back(user_t *u, int idx, char *par) |
217 | { |
218 | not_away(idx); |
219 | return(1); |
220 | } |
221 | |
222 | static int cmd_newpass(user_t *u, int idx, char *par) |
223 | { |
224 | char *new; |
225 | |
226 | if (!par[0]) { |
227 | dprintf(idx, "Usage: newpass <newpassword>\n"); |
228 | return(0); |
229 | } |
230 | new = newsplit(&par); |
231 | if (strlen(new) > 16) |
232 | new[16] = 0; |
233 | if (strlen(new) < 6) { |
234 | dprintf(idx, _("Please use at least 6 characters.\n")); |
235 | return(0); |
236 | } |
237 | set_user(&USERENTRY_PASS, u, new); |
238 | putlog(LOG_CMDS, "*", "#%s# newpass ...", dcc[idx].nick); |
239 | dprintf(idx, _("Changed password to '%s'\n"), new); |
240 | return(0); |
241 | } |
242 | |
243 | static int cmd_rehelp(user_t *u, int idx, char *par) |
244 | { |
245 | dprintf(idx, _("Reload help cache...\n")); |
246 | reload_help_data(); |
247 | return(1); |
248 | } |
249 | |
250 | static int cmd_help(user_t *u, int idx, char *par) |
251 | { |
252 | struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0}; |
253 | |
254 | get_user_flagrec(u, &fr, dcc[idx].u.chat->con_chan); |
255 | if (par[0]) { |
256 | if (!strcmp(par, "all")) |
257 | tellallhelp(idx, "all", &fr); |
258 | else if (strchr(par, '*') || strchr(par, '?')) { |
259 | char *p = par; |
260 | |
261 | /* Check if the search pattern only consists of '*' and/or '?' |
262 | * If it does, show help for "all" instead of listing all help |
263 | * entries. |
264 | */ |
265 | for (p = par; *p && ((*p == '*') || (*p == '?')); p++); |
266 | if (*p) |
267 | tellwildhelp(idx, par, &fr); |
268 | else |
269 | tellallhelp(idx, "all", &fr); |
270 | } else |
271 | tellhelp(idx, par, &fr, 0); |
272 | } else { |
273 | if (glob_op(fr) || glob_botmast(fr) || chan_op(fr)) |
274 | tellhelp(idx, "help", &fr, 0); |
275 | else |
276 | tellhelp(idx, "helpparty", &fr, 0); |
277 | } |
278 | return(1); |
279 | } |
280 | |
281 | static int cmd_who(user_t *u, int idx, char *par) |
282 | { |
283 | putlog(LOG_CMDS, "*", "#%s# who", dcc[idx].nick); |
284 | if (dcc[idx].u.chat->channel < 0) |
285 | tell_who(u, idx, 0); |
286 | else |
287 | tell_who(u, idx, dcc[idx].u.chat->channel); |
288 | |
289 | return(1); |
290 | } |
291 | |
292 | static int cmd_whois(user_t *u, int idx, char *par) |
293 | { |
294 | if (!par[0]) { |
295 | dprintf(idx, "Usage: whois <handle>\n"); |
296 | return(0); |
297 | } |
298 | tell_user_ident(idx, par, u ? (u->flags & USER_MASTER) : 0); |
299 | return(1); |
300 | } |
301 | |
302 | static int cmd_match(user_t *u, int idx, char *par) |
303 | { |
304 | int start = 1, limit = 20; |
305 | char *s, *s1, *chname; |
306 | |
307 | if (!par[0]) { |
308 | dprintf(idx, "Usage: match <nick/host> [[skip] count]\n"); |
309 | return(0); |
310 | } |
311 | s = newsplit(&par); |
312 | if (strchr(CHANMETA, par[0]) != NULL) |
313 | chname = newsplit(&par); |
314 | else |
315 | chname = ""; |
316 | if (atoi(par) > 0) { |
317 | s1 = newsplit(&par); |
318 | if (atoi(par) > 0) { |
319 | start = atoi(s1); |
320 | limit = atoi(par); |
321 | } else |
322 | limit = atoi(s1); |
323 | } |
324 | tell_users_match(idx, s, start, limit, u ? (u->flags & USER_MASTER) : 0, |
325 | chname); |
326 | return(1); |
327 | } |
328 | |
329 | static int cmd_uptime(user_t *u, int idx, char *par) |
330 | { |
331 | char s[256]; |
332 | unsigned long uptime, tmp, hr, min; |
333 | |
334 | uptime = now - online_since; |
335 | s[0] = 0; |
336 | if (uptime > 86400) { |
337 | tmp = (uptime / 86400); |
338 | sprintf(s, "%lu day%s, ", tmp, (tmp == 1) ? "" : "s"); |
339 | uptime -= (tmp * 86400); |
340 | } |
341 | hr = (uptime / 3600); |
342 | uptime -= (hr * 3600); |
343 | min = (uptime / 60); |
344 | sprintf(&s[strlen(s)], "%02lu:%02lu", hr, min); |
345 | |
346 | dprintf(idx, "%s %s (%s)\n", _("Online for"), s, backgrd ? |
347 | _("background") : term_z ? _("terminal mode") : con_chan ? |
348 | _("status mode") : _("log dump mode")); |
349 | return(1); |
350 | } |
351 | |
352 | static int cmd_status(user_t *u, int idx, char *par) |
353 | { |
354 | int atr = u ? u->flags : 0; |
355 | |
356 | if (!strcasecmp(par, "all")) { |
357 | if (!(atr & USER_MASTER)) { |
358 | dprintf(idx, _("You do not have Bot Master privileges.\n")); |
359 | return(0); |
360 | } |
361 | tell_verbose_status(idx); |
362 | dprintf(idx, "\n"); |
363 | tell_settings(idx); |
364 | do_module_report(idx, 1, NULL); |
365 | } else { |
366 | tell_verbose_status(idx); |
367 | do_module_report(idx, 0, NULL); |
368 | } |
369 | return(1); |
370 | } |
371 | |
372 | static int cmd_dccstat(user_t *u, int idx, char *par) |
373 | { |
374 | tell_dcc(idx); |
375 | return(1); |
376 | } |
377 | |
378 | static int cmd_boot(user_t *u, int idx, char *par) |
379 | { |
380 | int i, files = 0, ok = 0; |
381 | char *who; |
382 | user_t *u2; |
383 | |
384 | if (!par[0]) { |
385 | dprintf(idx, "Usage: boot nick[@bot]\n"); |
386 | return(0); |
387 | } |
388 | who = newsplit(&par); |
389 | for (i = 0; i < dcc_total; i++) |
390 | if (dcc[i].type && !strcasecmp(dcc[i].nick, who) |
391 | && !ok && (dcc[i].type->flags & DCT_CANBOOT)) { |
392 | u2 = get_user_by_handle(userlist, dcc[i].nick); |
393 | if (u2 && (u2->flags & USER_OWNER) |
394 | && strcasecmp(dcc[idx].nick, who)) { |
395 | dprintf(idx, _("You can't boot a bot owner.\n")); |
396 | return(0); |
397 | } |
398 | if (u2 && (u2->flags & USER_MASTER) && !(u && (u->flags & USER_MASTER))) { |
399 | dprintf(idx, _("You can't boot a bot master.\n")); |
400 | return(0); |
401 | } |
402 | files = (dcc[i].type->flags & DCT_FILES); |
403 | if (files) |
404 | dprintf(idx, _("Booted %s from the file area.\n"), dcc[i].nick); |
405 | else |
406 | dprintf(idx, _("Booted %s from the party line.\n"), dcc[i].nick); |
407 | do_boot(i, dcc[idx].nick, par); |
408 | ok = 1; |
409 | } |
410 | if (!ok) { |
411 | dprintf(idx, _("Who? No such person on the party line.\n")); |
412 | return(0); |
413 | } |
414 | return(1); |
415 | } |
416 | |
417 | static int cmd_console(user_t *u, int idx, char *par) |
418 | { |
419 | char *nick, s[2], s1[512]; |
420 | int dest = 0, i, ok = 0, pls, md; |
421 | struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0}; |
422 | module_entry *me; |
423 | |
424 | if (!par[0]) { |
425 | dprintf(idx, "Your console is %s: %s (%s).\n", |
426 | dcc[idx].u.chat->con_chan, |
427 | masktype(dcc[idx].u.chat->con_flags), |
428 | maskname(dcc[idx].u.chat->con_flags)); |
429 | return(1); |
430 | } |
431 | get_user_flagrec(u, &fr, dcc[idx].u.chat->con_chan); |
432 | strcpy(s1, par); |
433 | nick = newsplit(&par); |
434 | /* Don't remove '+' as someone couldn't have '+' in CHANMETA cause |
435 | * he doesn't use IRCnet ++rtc. |
436 | */ |
437 | if (nick[0] && !strchr(CHANMETA "+-*", nick[0]) && glob_master(fr)) { |
438 | for (i = 0; i < dcc_total; i++) |
439 | if (dcc[i].type && !strcasecmp(nick, dcc[i].nick) && |
440 | (dcc[i].type == &DCC_CHAT) && (!ok)) { |
441 | ok = 1; |
442 | dest = i; |
443 | } |
444 | if (!ok) { |
445 | dprintf(idx, "No such user on the party line!\n"); |
446 | return(0); |
447 | } |
448 | nick[0] = 0; |
449 | } else |
450 | dest = idx; |
451 | if (!nick[0]) |
452 | nick = newsplit(&par); |
453 | /* Consider modeless channels, starting with '+' */ |
454 | if ((nick [0] == '+' && findchan_by_dname(nick)) || |
455 | (nick [0] != '+' && strchr(CHANMETA "*", nick[0]))) { |
456 | if (strcmp(nick, "*") && !findchan_by_dname(nick)) { |
457 | dprintf(idx, "Invalid console channel: %s.\n", nick); |
458 | return(0); |
459 | } |
460 | get_user_flagrec(u, &fr, nick); |
461 | if (!chan_op(fr) && !glob_op(fr)) { |
462 | dprintf(idx, "You don't have op or master access to channel %s.\n", |
463 | nick); |
464 | return(0); |
465 | } |
466 | strlcpy(dcc[dest].u.chat->con_chan, nick, 81); |
467 | nick[0] = 0; |
468 | if ((dest == idx) && !glob_master(fr) && !chan_master(fr)) |
469 | /* Consoling to another channel for self */ |
470 | dcc[dest].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS | LOG_WALL); |
471 | } |
472 | if (!nick[0]) |
473 | nick = newsplit(&par); |
474 | pls = 1; |
475 | if (nick[0]) { |
476 | if ((nick[0] != '+') && (nick[0] != '-')) |
477 | dcc[dest].u.chat->con_flags = 0; |
478 | for (; *nick; nick++) { |
479 | if (*nick == '+') |
480 | pls = 1; |
481 | else if (*nick == '-') |
482 | pls = 0; |
483 | else { |
484 | s[0] = *nick; |
485 | s[1] = 0; |
486 | md = logmodes(s); |
487 | if ((dest == idx) && !glob_master(fr) && pls) { |
488 | if (chan_master(fr)) |
489 | md &= ~(LOG_FILES | LOG_LEV1 | LOG_LEV2 | LOG_LEV3 | |
490 | LOG_LEV4 | LOG_LEV5 | LOG_LEV6 | LOG_LEV7 | |
491 | LOG_LEV8 | LOG_DEBUG); |
492 | else |
493 | md &= ~(LOG_MISC | LOG_CMDS | LOG_FILES | LOG_LEV1 | |
494 | LOG_LEV2 | LOG_LEV3 | LOG_LEV4 | LOG_LEV5 | |
495 | LOG_LEV6 | LOG_LEV7 | LOG_LEV8 | LOG_WALL | |
496 | LOG_DEBUG); |
497 | } |
498 | if (!glob_owner(fr) && pls) |
499 | md &= ~(LOG_RAW | LOG_SRVOUT); |
500 | if (!glob_botmast(fr) && pls) |
501 | md &= ~LOG_BOTS; |
502 | if (pls) |
503 | dcc[dest].u.chat->con_flags |= md; |
504 | else |
505 | dcc[dest].u.chat->con_flags &= ~md; |
506 | } |
507 | } |
508 | } |
509 | if (dest == idx) { |
510 | dprintf(idx, "Set your console to %s: %s (%s).\n", |
511 | dcc[idx].u.chat->con_chan, |
512 | masktype(dcc[idx].u.chat->con_flags), |
513 | maskname(dcc[idx].u.chat->con_flags)); |
514 | } else { |
515 | dprintf(idx, "Set console of %s to %s: %s (%s).\n", dcc[dest].nick, |
516 | dcc[dest].u.chat->con_chan, |
517 | masktype(dcc[dest].u.chat->con_flags), |
518 | maskname(dcc[dest].u.chat->con_flags)); |
519 | dprintf(dest, "%s set your console to %s: %s (%s).\n", dcc[idx].nick, |
520 | dcc[dest].u.chat->con_chan, |
521 | masktype(dcc[dest].u.chat->con_flags), |
522 | maskname(dcc[dest].u.chat->con_flags)); |
523 | } |
524 | /* New style autosave -- drummer,07/25/1999*/ |
525 | if ((me = module_find("console", 1, 1))) { |
526 | Function *func = me->funcs; |
527 | (func[CONSOLE_DOSTORE]) (dest); |
528 | } |
529 | return(1); |
530 | } |
531 | |
532 | static int cmd_pls_bot(user_t *u, int idx, char *par) |
533 | { |
534 | char *handle, *addr, *p, *q, *host; |
535 | user_t *u1; |
536 | struct bot_addr *bi; |
537 | int addrlen; |
538 | |
539 | if (!par[0]) { |
540 | dprintf(idx, "Usage: +bot <handle> [address[:telnet-port[/relay-port]]] " |
541 | "[host]\n"); |
542 | return(0); |
543 | } |
544 | |
545 | handle = newsplit(&par); |
546 | addr = newsplit(&par); |
547 | host = newsplit(&par); |
548 | |
549 | if (strlen(handle) > HANDLEN) |
550 | handle[HANDLEN] = 0; |
551 | |
552 | if (get_user_by_handle(userlist, handle)) |
553 | dprintf(idx, _("Someone already exists by that name.\n")); |
554 | return(0); |
555 | } |
556 | |
557 | if (strchr(BADHANDCHARS, handle[0]) != NULL) { |
558 | dprintf(idx, _("You can't start a botnick with '%c'.\n"), handle[0]); |
559 | return(0); |
560 | } |
561 | |
562 | if (strlen(addr) > 60) |
563 | addr[60] = 0; |
564 | |
565 | userlist = adduser(userlist, handle, "none", "-", USER_BOT); |
566 | u1 = get_user_by_handle(userlist, handle); |
567 | bi = malloc(sizeof(struct bot_addr)); |
568 | |
569 | if (*addr == '[') { |
570 | addr++; |
571 | if ((q = strchr(addr, ']'))) { |
572 | addrlen = q - addr; |
573 | q++; |
574 | if (*q != ':') |
575 | q = 0; |
576 | } else |
577 | addrlen = strlen(addr); |
578 | } else { |
579 | if ((q = strchr(addr, ':'))) |
580 | addrlen = q - addr; |
581 | else |
582 | addrlen = strlen(addr); |
583 | } |
584 | if (!q) { |
585 | bi->address = strdup(addr); |
586 | bi->telnet_port = 3333; |
587 | bi->relay_port = 3333; |
588 | } else { |
589 | bi->address = malloc(addrlen + 1); |
590 | strlcpy(bi->address, addr, addrlen + 1); |
591 | p = q + 1; |
592 | bi->telnet_port = atoi(p); |
593 | q = strchr(p, '/'); |
594 | if (!q) |
595 | bi->relay_port = bi->telnet_port; |
596 | else |
597 | bi->relay_port = atoi(q + 1); |
598 | } |
599 | set_user(&USERENTRY_BOTADDR, u1, bi); |
600 | dprintf(idx, _("Added bot '%s' with %s%s%s%s and %s%s%s%s.\n"), handle, |
601 | addr[0] ? "address " : "no address ", addr[0] ? "'" : "", |
602 | addr[0] ? addr : "", addr[0] ? "'" : "", |
603 | host[0] ? "hostmask " : "no hostmask", addr[0] ? "'" : "", |
604 | host[0] ? host : "", addr[0] ? "'" : ""); |
605 | if (host[0]) |
606 | addhost_by_handle(handle, host); |
607 | else if (!add_bot_hostmask(idx, handle)) |
608 | dprintf(idx, _("You'll want to add a hostmask if this bot will ever be on any channels that I'm on.\n")); |
609 | return(1); |
610 | } |
611 | |
612 | static int cmd_chhandle(user_t *u, int idx, char *par) |
613 | { |
614 | char hand[HANDLEN + 1], newhand[HANDLEN + 1]; |
615 | int i, atr = u ? u->flags : 0, atr2; |
616 | user_t *u2; |
617 | |
618 | strlcpy(hand, newsplit(&par), sizeof hand); |
619 | strlcpy(newhand, newsplit(&par), sizeof newhand); |
620 | |
621 | if (!hand[0] || !newhand[0]) { |
622 | dprintf(idx, "Usage: chhandle <oldhandle> <newhandle>\n"); |
623 | return(0); |
624 | } |
625 | for (i = 0; i < strlen(newhand); i++) |
626 | if ((newhand[i] <= 32) || (newhand[i] >= 127) || (newhand[i] == '@')) |
627 | newhand[i] = '?'; |
628 | if (strchr(BADHANDCHARS, newhand[0]) != NULL) |
629 | dprintf(idx, _("Bizarre quantum forces prevent nicknames from starting with %c.\n"), |
630 | newhand[0]); |
631 | else if (get_user_by_handle(userlist, newhand) && |
632 | strcasecmp(hand, newhand)) |
633 | dprintf(idx, _("Somebody is already using %s.\n"), newhand); |
634 | else { |
635 | u2 = get_user_by_handle(userlist, hand); |
636 | atr2 = u2 ? u2->flags : 0; |
637 | if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) && |
638 | !(atr2 & USER_BOT)) |
639 | dprintf(idx, _("You can't change handles for non-bots.\n")); |
640 | else if ((atr2 & USER_OWNER) && !(atr & USER_OWNER) && |
641 | strcasecmp(dcc[idx].nick, hand)) |
642 | dprintf(idx, _("You can't change a bot owner's handle.\n")); |
643 | else if (isowner(hand) && strcasecmp(dcc[idx].nick, hand)) |
644 | dprintf(idx, _("You can't change a permanent bot owner's handle.\n")); |
645 | else if (!strcasecmp(newhand, myname) && !(atr2 & USER_BOT)) |
646 | dprintf(idx, _("Hey! That's MY name!\n")); |
647 | else if (change_handle(u2, newhand)) { |
648 | dprintf(idx, _("Changed.\n")); |
649 | } else |
650 | dprintf(idx, _("Failed.\n")); |
651 | } |
652 | return(1); |
653 | } |
654 | |
655 | static int cmd_handle(user_t *u, int idx, char *par) |
656 | { |
657 | char oldhandle[HANDLEN + 1], newhandle[HANDLEN + 1]; |
658 | int i; |
659 | |
660 | strlcpy(newhandle, newsplit(&par), sizeof newhandle); |
661 | |
662 | if (!newhandle[0]) { |
663 | dprintf(idx, "Usage: handle <new-handle>\n"); |
664 | return(0); |
665 | } |
666 | for (i = 0; i < strlen(newhandle); i++) |
667 | if ((newhandle[i] <= 32) || (newhandle[i] >= 127) || (newhandle[i] == '@')) |
668 | newhandle[i] = '?'; |
669 | if (strchr(BADHANDCHARS, newhandle[0]) != NULL) { |
670 | dprintf(idx, _("Bizarre quantum forces prevent handle from starting with '%c'\n"), |
671 | newhandle[0]); |
672 | } else if (get_user_by_handle(userlist, newhandle) && |
673 | strcasecmp(dcc[idx].nick, newhandle)) { |
674 | dprintf(idx, _("Somebody is already using %s.\n"), newhandle); |
675 | } else if (!strcasecmp(newhandle, myname)) { |
676 | dprintf(idx, _("Hey! That's MY name!\n")); |
677 | } else { |
678 | strlcpy(oldhandle, dcc[idx].nick, sizeof oldhandle); |
679 | if (change_handle(u, newhandle)) { |
680 | dprintf(idx, _("Okay, changed.\n")); |
681 | } else |
682 | dprintf(idx, _("Failed.\n")); |
683 | } |
684 | return(1); |
685 | } |
686 | |
687 | static int cmd_chpass(user_t *u, int idx, char *par) |
688 | { |
689 | char *handle, *new; |
690 | int atr = u ? u->flags : 0, l; |
691 | |
692 | if (!par[0]) |
693 | dprintf(idx, "Usage: chpass <handle> [password]\n"); |
694 | else { |
695 | handle = newsplit(&par); |
696 | u = get_user_by_handle(userlist, handle); |
697 | if (!u) |
698 | dprintf(idx, _("No such user.\n")); |
699 | else if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) && |
700 | !(u->flags & USER_BOT)) |
701 | dprintf(idx, _("You can't change passwords for non-bots.\n")); |
702 | else if ((u->flags & USER_OWNER) && !(atr & USER_OWNER) && |
703 | strcasecmp(handle, dcc[idx].nick)) |
704 | dprintf(idx, _("You can't change a bot owner's password.\n")); |
705 | else if (isowner(handle) && strcasecmp(dcc[idx].nick, handle)) |
706 | dprintf(idx, _("You can't change a permanent bot owner's password.\n")); |
707 | else if (!par[0]) { |
708 | set_user(&USERENTRY_PASS, u, NULL); |
709 | dprintf(idx, _("Removed password.\n")); |
710 | } else { |
711 | l = strlen(new = newsplit(&par)); |
712 | if (l > 16) |
713 | new[16] = 0; |
714 | if (l < 6) |
715 | dprintf(idx, _("Please use at least 6 characters.\n")); |
716 | else { |
717 | set_user(&USERENTRY_PASS, u, new); |
718 | dprintf(idx, _("Changed password.\n")); |
719 | } |
720 | } |
721 | } |
722 | return(0); |
723 | } |
724 | |
725 | static int cmd_chaddr(user_t *u, int idx, char *par) |
726 | { |
727 | int telnet_port = 3333, relay_port = 3333; |
728 | char *handle, *addr, *p, *q; |
729 | struct bot_addr *bi; |
730 | user_t *u1; |
731 | int addrlen; |
732 | |
733 | if (!par[0]) { |
734 | dprintf(idx, "Usage: chaddr <botname> <address[:telnet-port[/relay-port]]>\n"); |
735 | return(0); |
736 | } |
737 | handle = newsplit(&par); |
738 | addr = newsplit(&par); |
739 | if (strlen(addr) > UHOSTMAX) |
740 | addr[UHOSTMAX] = 0; |
741 | u1 = get_user_by_handle(userlist, handle); |
742 | if (!u1 || !(u1->flags & USER_BOT)) { |
743 | dprintf(idx, _("This command is only useful for tandem bots.\n")); |
744 | return(0); |
745 | } |
746 | dprintf(idx, _("Changed bot's address.\n")); |
747 | |
748 | bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u1); |
749 | if (bi) { |
750 | telnet_port = bi->telnet_port; |
751 | relay_port = bi->relay_port; |
752 | } |
753 | |
754 | bi = malloc(sizeof(struct bot_addr)); |
755 | |
756 | if (*addr == '[') { |
757 | addr++; |
758 | if ((q = strchr(addr, ']'))) { |
759 | addrlen = q - addr; |
760 | q++; |
761 | if (*q != ':') |
762 | q = 0; |
763 | } else |
764 | addrlen = strlen(addr); |
765 | } else { |
766 | if ((q = strchr(addr, ':'))) |
767 | addrlen = q - addr; |
768 | else |
769 | addrlen = strlen(addr); |
770 | } |
771 | if (!q) { |
772 | bi->address = strdup(addr); |
773 | bi->telnet_port = telnet_port; |
774 | bi->relay_port = relay_port; |
775 | } else { |
776 | bi->address = malloc(addrlen + 1); |
777 | strlcpy(bi->address, addr, addrlen + 1); |
778 | p = q + 1; |
779 | bi->telnet_port = atoi(p); |
780 | q = strchr(p, '/'); |
781 | if (!q) { |
782 | bi->relay_port = bi->telnet_port; |
783 | } else { |
784 | bi->relay_port = atoi(q + 1); |
785 | } |
786 | } |
787 | set_user(&USERENTRY_BOTADDR, u1, bi); |
788 | return(1); |
789 | } |
790 | |
791 | static int cmd_comment(user_t *u, int idx, char *par) |
792 | { |
793 | char *handle; |
794 | user_t *u1; |
795 | |
796 | if (!par[0]) { |
797 | dprintf(idx, "Usage: comment <handle> <newcomment>\n"); |
798 | return(0); |
799 | } |
800 | handle = newsplit(&par); |
801 | u1 = get_user_by_handle(userlist, handle); |
802 | if (!u1) { |
803 | dprintf(idx, _("No such user!\n")); |
804 | return(0); |
805 | } |
806 | if ((u1->flags & USER_OWNER) && !(u && (u->flags & USER_OWNER)) && |
807 | strcasecmp(handle, dcc[idx].nick)) { |
808 | dprintf(idx, _("Can't change comment on the bot owner.\n")); |
809 | return(0); |
810 | } |
811 | if (!strcasecmp(par, "none")) { |
812 | dprintf(idx, _("Okay, comment blanked.\n")); |
813 | set_user(&USERENTRY_COMMENT, u1, NULL); |
814 | return(0); |
815 | } |
816 | dprintf(idx, _("Changed comment.\n")); |
817 | set_user(&USERENTRY_COMMENT, u1, par); |
818 | return(1); |
819 | } |
820 | |
821 | static int cmd_restart(user_t *u, int idx, char *par) |
822 | { |
823 | if (!backgrd) { |
824 | dprintf(idx, "%s\n", _("You cannot .restart a bot when running -n (due to tcl).")); |
825 | return(0); |
826 | } |
827 | dprintf(idx, _("Restarting.\n")); |
828 | if (make_userfile) |
829 | make_userfile = 0; |
830 | write_userfile(-1); |
831 | putlog(LOG_MISC, "*", "%s", _("Restarting ...")); |
832 | do_restart = idx; |
833 | return(1); |
834 | } |
835 | |
836 | static int cmd_rehash(user_t *u, int idx, char *par) |
837 | { |
838 | dprintf(idx, "%s\n", _("Rehashing.")); |
839 | if (make_userfile) |
840 | make_userfile = 0; |
841 | write_userfile(-1); |
842 | putlog(LOG_MISC, "*", "%s", _("Rehashing...")); |
843 | do_restart = -2; |
844 | return(1); |
845 | } |
846 | |
847 | static int cmd_reload(user_t *u, int idx, char *par) |
848 | { |
849 | dprintf(idx, "%s\n", _("Reloading user file...")); |
850 | reload(); |
851 | return(1); |
852 | } |
853 | |
854 | void cmd_die(user_t *u, int idx, char *par) |
855 | { |
856 | char s1[1024], s2[1024]; |
857 | |
858 | if (par[0]) { |
859 | snprintf(s1, sizeof s1, "%s (%s: %s)", _("BOT SHUTDOWN"), dcc[idx].nick, |
860 | par); |
861 | snprintf(s2, sizeof s2, "%s %s!%s (%s)", _("DIE BY"), dcc[idx].nick, |
862 | dcc[idx].host, par); |
863 | strlcpy(quit_msg, par, 1024); |
864 | } else { |
865 | snprintf(s1, sizeof s1, "%s (%s %s)", _("BOT SHUTDOWN"), _("Authorized by"), |
866 | dcc[idx].nick); |
867 | snprintf(s2, sizeof s2, "%s %s!%s (%s)", _("DIE BY"), dcc[idx].nick, |
868 | dcc[idx].host, _("requested")); |
869 | strlcpy(quit_msg, dcc[idx].nick, 1024); |
870 | } |
871 | kill_bot(s1, s2); |
872 | } |
873 | |
874 | static int cmd_simul(user_t *u, int idx, char *par) |
875 | { |
876 | char *nick; |
877 | int i, ok = 0; |
878 | |
879 | nick = newsplit(&par); |
880 | if (!par[0]) { |
881 | dprintf(idx, "Usage: simul <hand> <text>\n"); |
882 | return(0); |
883 | } |
884 | if (isowner(nick)) { |
885 | dprintf(idx, _("Unable to '.simul' permanent owners.\n")); |
886 | return(0); |
887 | } |
888 | for (i = 0; i < dcc_total; i++) |
889 | if (dcc[i].type && !strcasecmp(nick, dcc[i].nick) && !ok && |
890 | (dcc[i].type->flags & DCT_SIMUL)) { |
891 | if (dcc[i].type && dcc[i].type->activity) { |
892 | dcc[i].type->activity(i, par, strlen(par)); |
893 | ok = 1; |
894 | } |
895 | } |
896 | if (!ok) |
897 | dprintf(idx, _("No such user on the party line.\n")); |
898 | return(1); |
899 | } |
900 | |
901 | static int cmd_save(user_t *u, int idx, char *par) |
902 | { |
903 | dprintf(idx, _("Saving user file...\n")); |
904 | write_userfile(-1); |
905 | return(1); |
906 | } |
907 | |
908 | static int cmd_backup(user_t *u, int idx, char *par) |
909 | { |
910 | dprintf(idx, _("Backing up the channel & user files...\n")); |
911 | call_hook(HOOK_BACKUP); |
912 | return(1); |
913 | } |
914 | |
915 | /* After messing with someone's user flags, make sure the dcc-chat flags |
916 | * are set correctly. |
917 | */ |
918 | int check_dcc_attrs(user_t *u, int oatr) |
919 | { |
920 | int i, stat; |
921 | |
922 | if (!u) |
923 | return 0; |
924 | /* Make sure default owners are +n */ |
925 | if (isowner(u->handle)) { |
926 | u->flags = sanity_check(u->flags | USER_OWNER); |
927 | } |
928 | for (i = 0; i < dcc_total; i++) { |
929 | if (dcc[i].type && (dcc[i].type->flags & DCT_MASTER) && |
930 | (!strcasecmp(u->handle, dcc[i].nick))) { |
931 | stat = dcc[i].status; |
932 | if ((oatr & USER_MASTER) && !(u->flags & USER_MASTER)) { |
933 | struct flag_record fr = {FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}; |
934 | |
935 | dcc[i].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS | LOG_RAW | |
936 | LOG_FILES | LOG_LEV1 | LOG_LEV2 | |
937 | LOG_LEV3 | LOG_LEV4 | LOG_LEV5 | |
938 | LOG_LEV6 | LOG_LEV7 | LOG_LEV8 | |
939 | LOG_WALL | LOG_DEBUG); |
940 | get_user_flagrec(u, &fr, NULL); |
941 | if (!chan_master(fr)) |
942 | dcc[i].u.chat->con_flags |= (LOG_MISC | LOG_CMDS); |
943 | dprintf(i, "*** POOF! ***\n"); |
944 | dprintf(i, _("You are no longer a master on this bot.\n")); |
945 | } |
946 | if (!(oatr & USER_MASTER) && (u->flags & USER_MASTER)) { |
947 | dcc[i].u.chat->con_flags |= conmask; |
948 | dprintf(i, "*** POOF! ***\n"); |
949 | dprintf(i, _("You are now a master on this bot.\n")); |
950 | } |
951 | if (!(oatr & USER_BOTMAST) && (u->flags & USER_BOTMAST)) { |
952 | dprintf(i, "### POOF! ###\n"); |
953 | dprintf(i, _("You are now a botnet master on this bot.\n")); |
954 | } |
955 | if ((oatr & USER_BOTMAST) && !(u->flags & USER_BOTMAST)) { |
956 | dprintf(i, "### POOF! ###\n"); |
957 | dprintf(i, _("You are no longer a botnet master on this bot.\n")); |
958 | } |
959 | if (!(oatr & USER_OWNER) && (u->flags & USER_OWNER)) { |
960 | dprintf(i, "@@@ POOF! @@@\n"); |
961 | dprintf(i, _("You are now an OWNER of this bot.\n")); |
962 | } |
963 | if ((oatr & USER_OWNER) && !(u->flags & USER_OWNER)) { |
964 | dprintf(i, "@@@ POOF! @@@\n"); |
965 | dprintf(i, _("You are no longer an owner of this bot.\n")); |
966 | } |
967 | if ((stat & STAT_PARTY) && (u->flags & USER_OP)) |
968 | stat &= ~STAT_PARTY; |
969 | if (!(stat & STAT_PARTY) && !(u->flags & USER_OP) && |
970 | !(u->flags & USER_MASTER)) |
971 | stat |= STAT_PARTY; |
972 | if ((stat & STAT_CHAT) && !(u->flags & USER_PARTY) && |
973 | !(u->flags & USER_MASTER)) |
974 | stat &= ~STAT_CHAT; |
975 | if ((dcc[i].type->flags & DCT_FILES) && !(stat & STAT_CHAT) && |
976 | ((u->flags & USER_MASTER) || (u->flags & USER_PARTY))) |
977 | stat |= STAT_CHAT; |
978 | dcc[i].status = stat; |
979 | /* Check if they no longer have access to wherever they are. |
980 | * |
981 | * NOTE: DON'T kick someone off the party line just cuz they lost +p |
982 | * (pinvite script removes +p after 5 mins automatically) |
983 | */ |
984 | if ((dcc[i].type->flags & DCT_FILES) && !(u->flags & USER_XFER) && |
985 | !(u->flags & USER_MASTER)) { |
986 | dprintf(i, "-+- POOF! -+-\n"); |
987 | dprintf(i, _("You no longer have file area access.\n\n")); |
988 | putlog(LOG_MISC, "*", _("DCC user [%s]%s removed from file system"), |
989 | dcc[i].nick, dcc[i].host); |
990 | if (dcc[i].status & STAT_CHAT) { |
991 | struct chat_info *ci; |
992 | |
993 | ci = dcc[i].u.file->chat; |
994 | free(dcc[i].u.file); |
995 | dcc[i].u.chat = ci; |
996 | dcc[i].status &= (~STAT_CHAT); |
997 | dcc[i].type = &DCC_CHAT; |
998 | if (dcc[i].u.chat->channel >= 0) { |
999 | chanout_but(-1, dcc[i].u.chat->channel, |
1000 | "*** %s has returned.\n", dcc[i].nick); |
1001 | } |
1002 | } else { |
1003 | killsock(dcc[i].sock); |
1004 | lostdcc(i); |
1005 | } |
1006 | } |
1007 | } |
1008 | } |
1009 | return u->flags; |
1010 | } |
1011 | |
1012 | int check_dcc_chanattrs(user_t *u, char *chname, int chflags, |
1013 | int ochatr) |
1014 | { |
1015 | int i, found = 0, atr = u ? u->flags : 0; |
1016 | struct chanset_t *chan; |
1017 | |
1018 | if (!u) |
1019 | return 0; |
1020 | for (i = 0; i < dcc_total; i++) { |
1021 | if (dcc[i].type && (dcc[i].type->flags & DCT_MASTER) && |
1022 | !strcasecmp(u->handle, dcc[i].nick)) { |
1023 | if ((ochatr & USER_MASTER) && !(chflags & USER_MASTER)) { |
1024 | if (!(atr & USER_MASTER)) |
1025 | dcc[i].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS); |
1026 | dprintf(i, "*** POOF! ***\n"); |
1027 | dprintf(i, _("You are no longer a master on %s.\n"), chname); |
1028 | } |
1029 | if (!(ochatr & USER_MASTER) && (chflags & USER_MASTER)) { |
1030 | dcc[i].u.chat->con_flags |= conmask; |
1031 | if (!(atr & USER_MASTER)) |
1032 | dcc[i].u.chat->con_flags &= |
1033 | ~(LOG_LEV1 | LOG_LEV2 | LOG_LEV3 | LOG_LEV4 | |
1034 | LOG_LEV5 | LOG_LEV6 | LOG_LEV7 | LOG_LEV8 | |
1035 | LOG_RAW | LOG_DEBUG | LOG_WALL | LOG_FILES | LOG_SRVOUT); |
1036 | dprintf(i, "*** POOF! ***\n"); |
1037 | dprintf(i, _("You are now a master on %s.\n"), chname); |
1038 | } |
1039 | if (!(ochatr & USER_OWNER) && (chflags & USER_OWNER)) { |
1040 | dprintf(i, "@@@ POOF! @@@\n"); |
1041 | dprintf(i, _("You are now an OWNER of %s.\n"), chname); |
1042 | } |
1043 | if ((ochatr & USER_OWNER) && !(chflags & USER_OWNER)) { |
1044 | dprintf(i, "@@@ POOF! @@@\n"); |
1045 | dprintf(i, _("You are no longer an owner of %s.\n"), chname); |
1046 | } |
1047 | if (((ochatr & (USER_OP | USER_MASTER | USER_OWNER)) && |
1048 | (!(chflags & (USER_OP | USER_MASTER | USER_OWNER)))) || |
1049 | ((chflags & (USER_OP | USER_MASTER | USER_OWNER)) && |
1050 | (!(ochatr & (USER_OP | USER_MASTER | USER_OWNER))))) { |
1051 | struct flag_record fr = {FR_CHAN, 0, 0, 0, 0, 0}; |
1052 | |
1053 | for (chan = chanset; chan && !found; chan = chan->next) { |
1054 | get_user_flagrec(u, &fr, chan->dname); |
1055 | if (fr.chan & (USER_OP | USER_MASTER | USER_OWNER)) |
1056 | found = 1; |
1057 | } |
1058 | if (!chan) |
1059 | chan = chanset; |
1060 | if (chan) |
1061 | strcpy(dcc[i].u.chat->con_chan, chan->dname); |
1062 | else |
1063 | strcpy(dcc[i].u.chat->con_chan, "*"); |
1064 | } |
1065 | } |
1066 | } |
1067 | return chflags; |
1068 | } |
1069 | |
1070 | static int cmd_chattr(user_t *u, int idx, char *par) |
1071 | { |
1072 | char *hand, *arg = NULL, *tmpchg = NULL, *chg = NULL, work[1024]; |
1073 | struct chanset_t *chan = NULL; |
1074 | user_t *u2; |
1075 | struct flag_record pls = {0, 0, 0, 0, 0, 0}, |
1076 | mns = {0, 0, 0, 0, 0, 0}, |
1077 | user = {0, 0, 0, 0, 0, 0}; |
1078 | module_entry *me; |
1079 | int fl = -1, of = 0, ocf = 0; |
1080 | |
1081 | if (!par[0]) { |
1082 | dprintf(idx, "Usage: chattr <handle> [changes] [channel]\n"); |
1083 | return(0); |
1084 | } |
1085 | hand = newsplit(&par); |
1086 | u2 = get_user_by_handle(userlist, hand); |
1087 | if (!u2) { |
1088 | dprintf(idx, _("No such user!\n")); |
1089 | return(0); |
1090 | } |
1091 | |
1092 | /* Parse args */ |
1093 | if (par[0]) { |
1094 | arg = newsplit(&par); |
1095 | if (par[0]) { |
1096 | /* .chattr <handle> <changes> <channel> */ |
1097 | chg = arg; |
1098 | arg = newsplit(&par); |
1099 | chan = findchan_by_dname(arg); |
1100 | } else { |
1101 | chan = findchan_by_dname(arg); |
1102 | /* Consider modeless channels, starting with '+' */ |
1103 | if (!(arg[0] == '+' && chan) && |
1104 | !(arg[0] != '+' && strchr (CHANMETA, arg[0]))) { |
1105 | /* .chattr <handle> <changes> */ |
1106 | chg = arg; |
1107 | chan = NULL; /* uh, !strchr (CHANMETA, channel[0]) && channel found?? */ |
1108 | arg = NULL; |
1109 | } |
1110 | /* .chattr <handle> <channel>: nothing to do... */ |
1111 | } |
1112 | } |
1113 | /* arg: pointer to channel name, NULL if none specified |
1114 | * chan: pointer to channel structure, NULL if none found or none specified |
1115 | * chg: pointer to changes, NULL if none specified |
1116 | */ |
1117 | assert(!(!arg && chan)); |
1118 | if (arg && !chan) { |
1119 | dprintf(idx, _("No channel record for %s.\n"), arg); |
1120 | return(0); |
1121 | } |
1122 | if (chg) { |
1123 | if (!arg && strpbrk(chg, "&|")) { |
1124 | /* .chattr <handle> *[&|]*: use console channel if found... */ |
1125 | if (!strcmp ((arg = dcc[idx].u.chat->con_chan), "*")) |
1126 | arg = NULL; |
1127 | else |
1128 | chan = findchan_by_dname(arg); |
1129 | if (arg && !chan) { |
1130 | dprintf (idx, _("Invalid console channel %s.\n"), arg); |
1131 | return(0); |
1132 | } |
1133 | } else if (arg && !strpbrk(chg, "&|")) { |
1134 | tmpchg = malloc(strlen(chg) + 2); |
1135 | strcpy(tmpchg, "|"); |
1136 | strcat(tmpchg, chg); |
1137 | chg = tmpchg; |
1138 | } |
1139 | } |
1140 | par = arg; |
1141 | user.match = FR_GLOBAL; |
1142 | if (chan) |
1143 | user.match |= FR_CHAN; |
1144 | get_user_flagrec(u, &user, chan ? chan->dname : 0); |
1145 | if (!chan && !glob_botmast(user)) { |
1146 | dprintf(idx, _("You do not have Bot Master privileges.\n")); |
1147 | if (tmpchg) |
1148 | free(tmpchg); |
1149 | return(0); |
1150 | } |
1151 | if (chan && !glob_master(user) && !chan_master(user)) { |
1152 | dprintf(idx, |
1153 | _("You do not have channel master privileges for channel %s.\n"), |
1154 | par); |
1155 | if (tmpchg) |
1156 | free(tmpchg); |
1157 | return(0); |
1158 | } |
1159 | user.match &= fl; |
1160 | if (chg) { |
1161 | pls.match = user.match; |
1162 | break_down_flags(chg, &pls, &mns); |
1163 | /* No-one can change these flags on-the-fly */ |
1164 | if (!glob_owner(user)) { |
1165 | pls.global &= ~(USER_OWNER | USER_MASTER | USER_BOTMAST); |
1166 | mns.global &= ~(USER_OWNER | USER_MASTER | USER_BOTMAST); |
1167 | |
1168 | if (chan) { |
1169 | pls.chan &= ~USER_OWNER; |
1170 | mns.chan &= ~USER_OWNER; |
1171 | } |
1172 | if (!glob_master(user)) { |
1173 | pls.global &= USER_PARTY | USER_XFER; |
1174 | mns.global &= USER_PARTY | USER_XFER; |
1175 | |
1176 | if (!glob_botmast(user)) { |
1177 | pls.global = 0; |
1178 | mns.global = 0; |
1179 | } |
1180 | } |
1181 | } |
1182 | if (chan && !chan_owner(user) && !glob_owner(user)) { |
1183 | pls.chan &= ~USER_MASTER; |
1184 | mns.chan &= ~USER_MASTER; |
1185 | if (!chan_master(user) && !glob_master(user)) { |
1186 | pls.chan = 0; |
1187 | mns.chan = 0; |
1188 | } |
1189 | } |
1190 | get_user_flagrec(u2, &user, par); |
1191 | if (user.match & FR_GLOBAL) { |
1192 | of = user.global; |
1193 | user.global = sanity_check((user.global |pls.global) &~mns.global); |
1194 | |
1195 | user.udef_global = (user.udef_global | pls.udef_global) |
1196 | & ~mns.udef_global; |
1197 | } |
1198 | if (chan) { |
1199 | ocf = user.chan; |
1200 | user.chan = chan_sanity_check((user.chan | pls.chan) & ~mns.chan, |
1201 | user.global); |
1202 | |
1203 | user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan; |
1204 | } |
1205 | set_user_flagrec(u2, &user, par); |
1206 | } |
1207 | /* Get current flags and display them */ |
1208 | if (user.match & FR_GLOBAL) { |
1209 | user.match = FR_GLOBAL; |
1210 | if (chg) |
1211 | check_dcc_attrs(u2, of); |
1212 | get_user_flagrec(u2, &user, NULL); |
1213 | build_flags(work, &user, NULL); |
1214 | if (work[0] != '-') |
1215 | dprintf(idx, _("Global flags for %1$s are now +%2$s.\n"), hand, work); |
1216 | else |
1217 | dprintf(idx, _("No global flags for %s.\n"), hand); |
1218 | } |
1219 | if (chan) { |
1220 | user.match = FR_CHAN; |
1221 | get_user_flagrec(u2, &user, par); |
1222 | if (chg) |
1223 | check_dcc_chanattrs(u2, chan->dname, user.chan, ocf); |
1224 | build_flags(work, &user, NULL); |
1225 | if (work[0] != '-') |
1226 | dprintf(idx, _("Channel flags for %1$s on %2$s are now +%3$s.\n"), hand, |
1227 | chan->dname, work); |
1228 | else |
1229 | dprintf(idx, _("No flags for %1$s on %2$s.\n"), hand, chan->dname); |
1230 | } |
1231 | if (chg && (me = module_find("irc", 0, 0))) { |
1232 | Function *func = me->funcs; |
1233 | |
1234 | (func[IRC_CHECK_THIS_USER]) (hand, 0, NULL); |
1235 | } |
1236 | if (tmpchg) |
1237 | free(tmpchg); |
1238 | return(1); |
1239 | } |
1240 | |
1241 | static int cmd_botattr(user_t *u, int idx, char *par) |
1242 | { |
1243 | char *hand, *chg = NULL, *arg = NULL, *tmpchg = NULL, work[1024]; |
1244 | struct chanset_t *chan = NULL; |
1245 | user_t *u2; |
1246 | struct flag_record pls = {0, 0, 0, 0, 0, 0}, |
1247 | mns = {0, 0, 0, 0, 0, 0}, |
1248 | user = {0, 0, 0, 0, 0, 0}; |
1249 | int idx2; |
1250 | |
1251 | if (!par[0]) { |
1252 | dprintf(idx, "Usage: botattr <handle> [changes] [channel]\n"); |
1253 | return(0); |
1254 | } |
1255 | hand = newsplit(&par); |
1256 | u2 = get_user_by_handle(userlist, hand); |
1257 | if (!u2 || !(u2->flags & USER_BOT)) { |
1258 | dprintf(idx, _("No such bot!\n")); |
1259 | return(0); |
1260 | } |
1261 | for (idx2 = 0; idx2 < dcc_total; idx2++) |
1262 | if (dcc[idx2].type && !strcasecmp(dcc[idx2].nick, hand)) |
1263 | break; |
1264 | if (idx2 != dcc_total) { |
1265 | dprintf(idx, |
1266 | _("You may not change the attributes of a directly linked bot.\n")); |
1267 | return(0); |
1268 | } |
1269 | /* Parse args */ |
1270 | if (par[0]) { |
1271 | arg = newsplit(&par); |
1272 | if (par[0]) { |
1273 | /* .botattr <handle> <changes> <channel> */ |
1274 | chg = arg; |
1275 | arg = newsplit(&par); |
1276 | chan = findchan_by_dname(arg); |
1277 | } else { |
1278 | chan = findchan_by_dname(arg); |
1279 | /* Consider modeless channels, starting with '+' */ |
1280 | if (!(arg[0] == '+' && chan) && |
1281 | !(arg[0] != '+' && strchr (CHANMETA, arg[0]))) { |
1282 | /* .botattr <handle> <changes> */ |
1283 | chg = arg; |
1284 | chan = NULL; /* uh, !strchr (CHANMETA, channel[0]) && channel found?? */ |
1285 | arg = NULL; |
1286 | } |
1287 | /* .botattr <handle> <channel>: nothing to do... */ |
1288 | } |
1289 | } |
1290 | /* arg: pointer to channel name, NULL if none specified |
1291 | * chan: pointer to channel structure, NULL if none found or none specified |
1292 | * chg: pointer to changes, NULL if none specified |
1293 | */ |
1294 | assert(!(!arg && chan)); |
1295 | if (arg && !chan) { |
1296 | dprintf(idx, _("No channel record for %s.\n"), arg); |
1297 | return(0); |
1298 | } |
1299 | if (chg) { |
1300 | if (!arg && strpbrk(chg, "&|")) { |
1301 | /* botattr <handle> *[&|]*: use console channel if found... */ |
1302 | if (!strcmp ((arg = dcc[idx].u.chat->con_chan), "*")) |
1303 | arg = NULL; |
1304 | else |
1305 | chan = findchan_by_dname(arg); |
1306 | if (arg && !chan) { |
1307 | dprintf (idx, _("Invalid console channel %s.\n"), arg); |
1308 | return(0); |
1309 | } |
1310 | } else if (arg && !strpbrk(chg, "&|")) { |
1311 | tmpchg = malloc(strlen(chg) + 2); |
1312 | strcpy(tmpchg, "|"); |
1313 | strcat(tmpchg, chg); |
1314 | chg = tmpchg; |
1315 | } |
1316 | } |
1317 | par = arg; |
1318 | |
1319 | user.match = FR_GLOBAL; |
1320 | get_user_flagrec(u, &user, chan ? chan->dname : 0); |
1321 | if (!glob_botmast(user)) { |
1322 | dprintf(idx, _("You do not have Bot Master privileges.\n")); |
1323 | if (tmpchg) |
1324 | free(tmpchg); |
1325 | return(0); |
1326 | } |
1327 | if (chg) { |
1328 | user.match = FR_BOT | (chan ? FR_CHAN : 0); |
1329 | pls.match = user.match; |
1330 | break_down_flags(chg, &pls, &mns); |
1331 | pls.chan = 0; |
1332 | mns.chan = 0; |
1333 | user.match = FR_BOT | (chan ? FR_CHAN : 0); |
1334 | get_user_flagrec(u2, &user, par); |
1335 | user.bot = (user.bot | pls.bot) & ~mns.bot; |
1336 | if (chan) |
1337 | user.chan = (user.chan | pls.chan) & ~mns.chan; |
1338 | set_user_flagrec(u2, &user, par); |
1339 | } |
1340 | /* get current flags and display them */ |
1341 | if (!chan || pls.bot || mns.bot) { |
1342 | user.match = FR_BOT; |
1343 | get_user_flagrec(u2, &user, NULL); |
1344 | build_flags(work, &user, NULL); |
1345 | if (work[0] != '-') |
1346 | dprintf(idx, _("Bot flags for %1$s are now +%2$s.\n"), hand, work); |
1347 | else |
1348 | dprintf(idx, _("No bot flags for %s.\n"), hand); |
1349 | } |
1350 | if (chan) { |
1351 | user.match = FR_CHAN; |
1352 | get_user_flagrec(u2, &user, par); |
1353 | build_flags(work, &user, NULL); |
1354 | if (work[0] != '-') |
1355 | dprintf(idx, _("Bot flags for %1$s on %2$s are now +%3$s.\n"), hand, |
1356 | chan->dname, work); |
1357 | else |
1358 | dprintf(idx, _("No bot flags for %1$s on %2$s.\n"), hand, chan->dname); |
1359 | } |
1360 | if (tmpchg) |
1361 | free(tmpchg); |
1362 | return(1); |
1363 | } |
1364 | |
1365 | static int cmd_su(user_t *u, int idx, char *par) |
1366 | { |
1367 | int atr = u ? u->flags : 0; |
1368 | struct flag_record fr = {FR_ANYWH | FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0}; |
1369 | |
1370 | u = get_user_by_handle(userlist, par); |
1371 | |
1372 | if (!par[0]) |
1373 | dprintf(idx, "Usage: su <user>\n"); |
1374 | else if (!u) |
1375 | dprintf(idx, _("No such user.\n")); |
1376 | else if (u->flags & USER_BOT) |
1377 | dprintf(idx, _("Can't su to a bot... then again, why would you wanna?\n")); |
1378 | else if (dcc[idx].u.chat->su_nick) |
1379 | dprintf(idx, _("You cannot currently double .su, try .su'ing directly\n")); |
1380 | else { |
1381 | get_user_flagrec(u, &fr, NULL); |
1382 | if (!glob_party(fr) && !(atr & USER_BOTMAST)) |
1383 | dprintf(idx, _("No party line access permitted for %s.\n"), par); |
1384 | else { |
1385 | correct_handle(par); |
1386 | if (!(atr & USER_OWNER) || |
1387 | ((u->flags & USER_OWNER) && (isowner(par)) && |
1388 | !(isowner(dcc[idx].nick)))) { |
1389 | /* This check is only important for non-owners */ |
1390 | if (u_pass_match(u, "-")) { |
1391 | dprintf(idx, |
1392 | _("No password set for user. You may not .su to them.\n")); |
1393 | return(0); |
1394 | } |
1395 | chanout_but(-1, dcc[idx].u.chat->channel, |
1396 | "*** %s left the party line.\n", dcc[idx].nick); |
1397 | /* Store the old nick in the away section, for weenies who can't get |
1398 | * their password right ;) |
1399 | */ |
1400 | if (dcc[idx].u.chat->away != NULL) |
1401 | free(dcc[idx].u.chat->away); |
1402 | dcc[idx].u.chat->away = calloc(1, strlen(dcc[idx].nick) + 1); |
1403 | strcpy(dcc[idx].u.chat->away, dcc[idx].nick); |
1404 | dcc[idx].u.chat->su_nick = calloc(1, strlen(dcc[idx].nick) + 1); |
1405 | strcpy(dcc[idx].u.chat->su_nick, dcc[idx].nick); |
1406 | dcc[idx].user = u; |
1407 | strcpy(dcc[idx].nick, par); |
1408 | /* Display password prompt and turn off echo (send IAC WILL ECHO). */ |
1409 | dprintf(idx, "Enter password for %s%s\n", par, |
1410 | (dcc[idx].status & STAT_TELNET) ? TLN_IAC_C TLN_WILL_C |
1411 | TLN_ECHO_C : ""); |
1412 | dcc[idx].type = &DCC_CHAT_PASS; |
1413 | } else if (atr & USER_OWNER) { |
1414 | chanout_but(-1, dcc[idx].u.chat->channel, |
1415 | "*** %s left the party line.\n", dcc[idx].nick); |
1416 | dprintf(idx, _("Setting your username to %s.\n"), par); |
1417 | if (atr & USER_MASTER) |
1418 | dcc[idx].u.chat->con_flags = conmask; |
1419 | dcc[idx].u.chat->su_nick = calloc(1, strlen(dcc[idx].nick) + 1); |
1420 | strcpy(dcc[idx].u.chat->su_nick, dcc[idx].nick); |
1421 | dcc[idx].user = u; |
1422 | strcpy(dcc[idx].nick, par); |
1423 | dcc_chatter(idx); |
1424 | } |
1425 | } |
1426 | } |
1427 | return(1); |
1428 | } |
1429 | |
1430 | static int cmd_fixcodes(user_t *u, int idx, char *par) |
1431 | { |
1432 | if (dcc[idx].status & STAT_ECHO) { |
1433 | dcc[idx].status |= STAT_TELNET; |
1434 | dcc[idx].status &= ~STAT_ECHO; |
1435 | dprintf(idx, _("Turned on telnet codes\n")); |
1436 | putlog(LOG_CMDS, "*", "#%s# fixcodes (telnet on)", dcc[idx].nick); |
1437 | return(0); |
1438 | } |
1439 | if (dcc[idx].status & STAT_TELNET) { |
1440 | dcc[idx].status |= STAT_ECHO; |
1441 | dcc[idx].status &= ~STAT_TELNET; |
1442 | dprintf(idx, _("Turned off telnet codes\n")); |
1443 | putlog(LOG_CMDS, "*", "#%s# fixcodes (telnet off)", dcc[idx].nick); |
1444 | return(0); |
1445 | } |
1446 | return(1); |
1447 | } |
1448 | |
1449 | static int cmd_page(user_t *u, int idx, char *par) |
1450 | { |
1451 | int a; |
1452 | module_entry *me; |
1453 | |
1454 | if (!par[0]) { |
1455 | if (dcc[idx].status & STAT_PAGE) { |
1456 | dprintf(idx, _("Currently paging outputs to %d lines.\n"), |
1457 | dcc[idx].u.chat->max_line); |
1458 | } else |
1459 | dprintf(idx, _("You don't have paging on.\n")); |
1460 | return(0); |
1461 | } |
1462 | a = atoi(par); |
1463 | if ((!a && !par[0]) || !strcasecmp(par, "off")) { |
1464 | dcc[idx].status &= ~STAT_PAGE; |
1465 | dcc[idx].u.chat->max_line = 0x7ffffff; /* flush_lines needs this */ |
1466 | while (dcc[idx].u.chat->buffer) |
1467 | flush_lines(idx, dcc[idx].u.chat); |
1468 | dprintf(idx, _("Paging turned off.\n")); |
1469 | putlog(LOG_CMDS, "*", "#%s# page off", dcc[idx].nick); |
1470 | } else if (a > 0) { |
1471 | dprintf(idx, P_("Paging turned on, stopping every %d line.\n", |
1472 | "Paging turned on, stopping every %d lines.\n", a), a); |
1473 | dcc[idx].status |= STAT_PAGE; |
1474 | dcc[idx].u.chat->max_line = a; |
1475 | dcc[idx].u.chat->line_count = 0; |
1476 | dcc[idx].u.chat->current_lines = 0; |
1477 | putlog(LOG_CMDS, "*", "#%s# page %d", dcc[idx].nick, a); |
1478 | } else { |
1479 | dprintf(idx, "Usage: page <off or #>\n"); |
1480 | return(0); |
1481 | } |
1482 | /* New style autosave here too -- rtc, 09/28/1999*/ |
1483 | if ((me = module_find("console", 1, 1))) { |
1484 | Function *func = me->funcs; |
1485 | (func[CONSOLE_DOSTORE]) (idx); |
1486 | } |
1487 | return(1); |
1488 | } |
1489 | |
1490 | static int cmd_module(user_t *u, int idx, char *par) |
1491 | { |
1492 | do_module_report(idx, 2, par[0] ? par : NULL); |
1493 | return(1); |
1494 | } |
1495 | |
1496 | static int cmd_loadmod(user_t *u, int idx, char *par) |
1497 | { |
1498 | const char *p; |
1499 | |
1500 | if (!isowner(dcc[idx].nick)) { |
1501 | dprintf(idx, _("What? You need .help\n")); |
1502 | return(0); |
1503 | } |
1504 | if (!par[0]) { |
1505 | dprintf(idx, "%s: loadmod <module>\n", _("Usage")); |
1506 | } else { |
1507 | p = module_load(par); |
1508 | if (p) |
1509 | dprintf(idx, "%s: %s %s\n", par, _("Error loading module:"), p); |
1510 | else { |
1511 | dprintf(idx, _("Module loaded: %-16s"), par); |
1512 | dprintf(idx, "\n"); |
1513 | } |
1514 | } |
1515 | return(1); |
1516 | } |
1517 | |
1518 | static int cmd_unloadmod(user_t *u, int idx, char *par) |
1519 | { |
1520 | char *p; |
1521 | |
1522 | if (!isowner(dcc[idx].nick)) { |
1523 | dprintf(idx, _("What? You need .help\n")); |
1524 | return(0); |
1525 | } |
1526 | if (!par[0]) { |
1527 | dprintf(idx, "%s: unloadmod <module>\n", _("Usage")); |
1528 | } else { |
1529 | p = module_unload(par, dcc[idx].nick); |
1530 | if (p) |
1531 | dprintf(idx, "%s %s: %s\n", _("Error unloading module:"), par, p); |
1532 | else { |
1533 | dprintf(idx, "%s %s\n", _("Module unloaded:"), par); |
1534 | } |
1535 | } |
1536 | return(1); |
1537 | } |
1538 | |
1539 | static int cmd_pls_ignore(user_t *u, int idx, char *par) |
1540 | { |
1541 | char *who; |
1542 | char s[UHOSTLEN]; |
1543 | unsigned long int expire_time = 0; |
1544 | |
1545 | if (!par[0]) { |
1546 | dprintf(idx, |
1547 | "Usage: +ignore <hostmask> [%%<XdXhXm>] [comment]\n"); |
1548 | return(0); |
1549 | } |
1550 | |
1551 | who = newsplit(&par); |
1552 | if (par[0] == '%') { |
1553 | char *p, *p_expire; |
1554 | unsigned long int expire_foo; |
1555 | |
1556 | p = newsplit(&par); |
1557 | p_expire = p + 1; |
1558 | while (*(++p) != 0) { |
1559 | switch (tolower(*p)) { |
1560 | case 'd': |
1561 | *p = 0; |
1562 | expire_foo = strtol(p_expire, NULL, 10); |
1563 | if (expire_foo > 365) |
1564 | expire_foo = 365; |
1565 | expire_time += 86400 * expire_foo; |
1566 | p_expire = p + 1; |
1567 | break; |
1568 | case 'h': |
1569 | *p = 0; |
1570 | expire_foo = strtol(p_expire, NULL, 10); |
1571 | if (expire_foo > 8760) |
1572 | expire_foo = 8760; |
1573 | expire_time += 3600 * expire_foo; |
1574 | p_expire = p + 1; |
1575 | break; |
1576 | case 'm': |
1577 | *p = 0; |
1578 | expire_foo = strtol(p_expire, NULL, 10); |
1579 | if (expire_foo > 525600) |
1580 | expire_foo = 525600; |
1581 | expire_time += 60 * expire_foo; |
1582 | p_expire = p + 1; |
1583 | } |
1584 | } |
1585 | } |
1586 | if (!par[0]) |
1587 | par = "requested"; |
1588 | else if (strlen(par) > 65) |
1589 | par[65] = 0; |
1590 | if (strlen(who) > UHOSTMAX - 4) |
1591 | who[UHOSTMAX - 4] = 0; |
1592 | |
1593 | /* Fix missing ! or @ BEFORE continuing */ |
1594 | if (!strchr(who, '!')) { |
1595 | if (!strchr(who, '@')) |
1596 | simple_sprintf(s, "%s!*@*", who); |
1597 | else |
1598 | simple_sprintf(s, "*!%s", who); |
1599 | } else if (!strchr(who, '@')) |
1600 | simple_sprintf(s, "%s@*", who); |
1601 | else |
1602 | strcpy(s, who); |
1603 | |
1604 | if (match_ignore(s)) |
1605 | dprintf(idx, _("That already matches an existing ignore.\n")); |
1606 | else { |
1607 | dprintf(idx, "Now ignoring: %s (%s)\n", s, par); |
1608 | addignore(s, dcc[idx].nick, par, expire_time ? now + expire_time : 0L); |
1609 | } |
1610 | return(1); |
1611 | } |
1612 | |
1613 | static int cmd_mns_ignore(user_t *u, int idx, char *par) |
1614 | { |
1615 | char buf[UHOSTLEN]; |
1616 | |
1617 | if (!par[0]) { |
1618 | dprintf(idx, "Usage: -ignore <hostmask | ignore #>\n"); |
1619 | return(0); |
1620 | } |
1621 | strlcpy(buf, par, sizeof buf); |
1622 | if (delignore(buf)) { |
1623 | dprintf(idx, _("No longer ignoring: %s\n"), buf); |
1624 | } else |
1625 | dprintf(idx, _("That ignore cannot be found.\n")); |
1626 | return(1); |
1627 | } |
1628 | |
1629 | static int cmd_ignores(user_t *u, int idx, char *par) |
1630 | { |
1631 | tell_ignores(idx, par); |
1632 | return(1); |
1633 | } |
1634 | |
1635 | static int cmd_pls_user(user_t *u, int idx, char *par) |
1636 | { |
1637 | char *handle, *host; |
1638 | |
1639 | if (!par[0]) { |
1640 | dprintf(idx, "Usage: +user <handle> [hostmask]\n"); |
1641 | return(0); |
1642 | } |
1643 | handle = newsplit(&par); |
1644 | host = newsplit(&par); |
1645 | if (strlen(handle) > HANDLEN) |
1646 | handle[HANDLEN] = 0; |
1647 | if (get_user_by_handle(userlist, handle)) |
1648 | dprintf(idx, _("Someone already exists by that name.\n")); |
1649 | else if (strchr(BADNICKCHARS, handle[0]) != NULL) |
1650 | dprintf(idx, _("You can't start a nick with '%c'.\n"), handle[0]); |
1651 | else if (!strcasecmp(handle, myname)) |
1652 | dprintf(idx, _("Hey! That's MY name!\n")); |
1653 | else { |
1654 | userlist = adduser(userlist, handle, host, "-", 0); |
1655 | dprintf(idx, _("Added %1$s (%2$s) with no password and no flags.\n"), |
1656 | handle, host[0] ? host : _("no host")); |
1657 | } |
1658 | return(1); |
1659 | } |
1660 | |
1661 | static int cmd_mns_user(user_t *u, int idx, char *par) |
1662 | { |
1663 | int idx2; |
1664 | char *handle; |
1665 | user_t *u2; |
1666 | module_entry *me; |
1667 | |
1668 | if (!par[0]) { |
1669 | dprintf(idx, "Usage: -user <hand>\n"); |
1670 | return(0); |
1671 | } |
1672 | handle = newsplit(&par); |
1673 | u2 = get_user_by_handle(userlist, handle); |
1674 | if (!u2 || !u) { |
1675 | dprintf(idx, _("No such user!\n")); |
1676 | return(0); |
1677 | } |
1678 | if (isowner(u2->handle)) { |
1679 | dprintf(idx, _("You can't remove the permanent bot owner!\n")); |
1680 | return(0); |
1681 | } |
1682 | if ((u2->flags & USER_OWNER) && !(u->flags & USER_OWNER)) { |
1683 | dprintf(idx, _("You can't remove a bot owner!\n")); |
1684 | return(0); |
1685 | } |
1686 | if (u2->flags & USER_BOT) { |
1687 | for (idx2 = 0; idx2 < dcc_total; idx2++) |
1688 | if (dcc[idx2].type && !strcasecmp(dcc[idx2].nick, handle)) |
1689 | break; |
1690 | if (idx2 != dcc_total) { |
1691 | dprintf(idx, _("You can't remove a directly linked bot.\n")); |
1692 | return(0); |
1693 | } |
1694 | } |
1695 | if ((u->flags & USER_BOTMAST) && !(u->flags & USER_MASTER) && |
1696 | !(u2->flags & USER_BOT)) { |
1697 | dprintf(idx, _("You can't remove users who aren't bots!\n")); |
1698 | return(0); |
1699 | } |
1700 | if ((me = module_find("irc", 0, 0))) { |
1701 | Function *func = me->funcs; |
1702 | |
1703 | (func[IRC_CHECK_THIS_USER]) (handle, 1, NULL); |
1704 | } |
1705 | if (deluser(handle)) { |
1706 | dprintf(idx, _("Deleted %s.\n"), handle); |
1707 | } else |
1708 | dprintf(idx, _("Failed.\n")); |
1709 | return(1); |
1710 | } |
1711 | |
1712 | static int cmd_pls_host(user_t *u, int idx, char *par) |
1713 | { |
1714 | char *handle, *host; |
1715 | user_t *u2; |
1716 | struct list_type *q; |
1717 | struct flag_record fr = {FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}; |
1718 | struct flag_record fr2 = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}, |
1719 | fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}; |
1720 | |
1721 | if (!par[0]) { |
1722 | dprintf(idx, "Usage: +host [handle] <newhostmask>\n"); |
1723 | return(0); |
1724 | } |
1725 | |
1726 | handle = newsplit(&par); |
1727 | |
1728 | if (par[0]) { |
1729 | host = newsplit(&par); |
1730 | u2 = get_user_by_handle(userlist, handle); |
1731 | } else { |
1732 | host = handle; |
1733 | handle = dcc[idx].nick; |
1734 | u2 = u; |
1735 | } |
1736 | if (!u2 || !u) { |
1737 | dprintf(idx, _("No such user.\n")); |
1738 | return(0); |
1739 | } |
1740 | get_user_flagrec(u, &fr, NULL); |
1741 | if (strcasecmp(handle, dcc[idx].nick)) { |
1742 | get_user_flagrec(u2, &fr2, NULL); |
1743 | if (!glob_master(fr) && !glob_bot(fr2) && !chan_master(fr)) { |
1744 | dprintf(idx, _("You can't add hostmasks to non-bots.\n")); |
1745 | return(0); |
1746 | } |
1747 | if ((glob_owner(fr2) || glob_master(fr2)) && !glob_owner(fr)) { |
1748 | dprintf(idx, _("You can't add hostmasks to the bot owner/master.\n")); |
1749 | return(0); |
1750 | } |
1751 | if ((chan_owner(fr2) || chan_master(fr2)) && !glob_master(fr) && |
1752 | !glob_owner(fr) && !chan_owner(fr)) { |
1753 | dprintf(idx, "You can't add hostmasks to a channel owner/master.\n"); |
1754 | return(0); |
1755 | } |
1756 | if (!glob_botmast(fr) && !glob_master(fr) && !chan_master(fr)) { |
1757 | dprintf(idx, "Permission denied.\n"); |
1758 | return(0); |
1759 | } |
1760 | } |
1761 | if (!glob_botmast(fr) && !chan_master(fr) && get_user_by_host(host)) { |
1762 | dprintf(idx, "You cannot add a host matching another user!\n"); |
1763 | return(0); |
1764 | } |
1765 | for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next) |
1766 | if (!strcasecmp(q->extra, host)) { |
1767 | dprintf(idx, _("That hostmask is already there.\n")); |
1768 | return(0); |
1769 | } |
1770 | addhost_by_handle(handle, host); |
1771 | dprintf(idx, "Added '%s' to %s.\n", host, handle); |
1772 | if ((me = module_find("irc", 0, 0))) { |
1773 | Function *func = me->funcs; |
1774 | |
1775 | (func[IRC_CHECK_THIS_USER]) (handle, 0, NULL); |
1776 | } |
1777 | return(1); |
1778 | } |
1779 | |
1780 | static int cmd_mns_host(user_t *u, int idx, char *par) |
1781 | { |
1782 | char *handle, *host; |
1783 | user_t *u2; |
1784 | struct flag_record fr2 = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}, |
1785 | fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}; |
1786 | module_entry *me; |
1787 | |
1788 | if (!par[0]) { |
1789 | dprintf(idx, "%s: -host [%s] <%s>\n", _("Usage"), _("handle"), |
1790 | _("hostmask")); |
1791 | return(0); |
1792 | } |
1793 | handle = newsplit(&par); |
1794 | if (par[0]) { |
1795 | host = newsplit(&par); |
1796 | u2 = get_user_by_handle(userlist, handle); |
1797 | } else { |
1798 | host = handle; |
1799 | handle = dcc[idx].nick; |
1800 | u2 = u; |
1801 | } |
1802 | if (!u2 || !u) { |
1803 | dprintf(idx, "%s\n", _("No such user.")); |
1804 | return(0); |
1805 | } |
1806 | |
1807 | get_user_flagrec(u, &fr, NULL); |
1808 | get_user_flagrec(u2, &fr2, NULL); |
1809 | if (strcasecmp(handle, dcc[idx].nick)) { |
1810 | if (!glob_master(fr) && !glob_bot(fr2) && !chan_master(fr)) { |
1811 | dprintf(idx, _("You can't remove hostmasks from non-bots.\n")); |
1812 | return(0); |
1813 | } |
1814 | if ((glob_owner(fr2) || glob_master(fr2)) && !glob_owner(fr)) { |
1815 | dprintf(idx, _("You can't remove hostmasks from a bot owner/master.\n")); |
1816 | return(0); |
1817 | } |
1818 | if ((chan_owner(fr2) || chan_master(fr2)) && !glob_master(fr) && |
1819 | !glob_owner(fr) && !chan_owner(fr)) { |
1820 | dprintf(idx, "You can't remove hostmasks from a channel owner/master.\n"); |
1821 | return(0); |
1822 | } |
1823 | if (!glob_botmast(fr) && !glob_master(fr) && !chan_master(fr)) { |
1824 | dprintf(idx, _("Permission denied.\n")); |
1825 | return(0); |
1826 | } |
1827 | } |
1828 | if (delhost_by_handle(handle, host)) { |
1829 | dprintf(idx, _("Removed '%1$s' from %2$s.\n"), host, handle); |
1830 | if ((me = module_find("irc", 0, 0))) { |
1831 | Function *func = me->funcs; |
1832 | |
1833 | (func[IRC_CHECK_THIS_USER]) (handle, 2, host); |
1834 | } |
1835 | } else |
1836 | dprintf(idx, _("Failed.\n")); |
1837 | return(1); |
1838 | } |
1839 | |
1840 | static int cmd_modules(user_t *u, int idx, char *par) |
1841 | { |
1842 | module_entry *me; |
1843 | |
1844 | dprintf(idx, _("Modules loaded:\n")); |
1845 | for (me = module_list; me; me = me->next) |
1846 | dprintf(idx, " Module: %s (v%d.%d)\n", me->name, me->major, me->minor); |
1847 | dprintf(idx, _("End of modules list.\n")); |
1848 | return(1); |
1849 | } |
1850 | |
1851 | static int cmd_traffic(user_t *u, int idx, char *par) |
1852 | { |
1853 | unsigned long itmp, itmp2; |
1854 | |
1855 | dprintf(idx, "Traffic since last restart\n"); |
1856 | dprintf(idx, "==========================\n"); |
1857 | if (traffic.out_total.irc > 0 || traffic.in_total.irc > 0 || traffic.out_today.irc > 0 || |
1858 | traffic.in_today.irc > 0) { |
1859 | dprintf(idx, "IRC:\n"); |
1860 | dprintf(idx, " out: %s", btos(traffic.out_total.irc + traffic.out_today.irc)); |
1861 | dprintf(idx, " (%s today)\n", btos(traffic.out_today.irc)); |
1862 | dprintf(idx, " in: %s", btos(traffic.in_total.irc + traffic.in_today.irc)); |
1863 | dprintf(idx, " (%s today)\n", btos(traffic.in_today.irc)); |
1864 | } |
1865 | if (traffic.out_total.dcc > 0 || traffic.in_total.dcc > 0 || traffic.out_today.dcc > 0 || |
1866 | traffic.in_today.dcc > 0) { |
1867 | dprintf(idx, "Partyline:\n"); |
1868 | itmp = traffic.out_total.dcc + traffic.out_today.dcc; |
1869 | itmp2 = traffic.out_today.dcc; |
1870 | dprintf(idx, " out: %s", btos(itmp)); |
1871 | dprintf(idx, " (%s today)\n", btos(itmp2)); |
1872 | dprintf(idx, " in: %s", btos(traffic.in_total.dcc + traffic.in_today.dcc)); |
1873 | dprintf(idx, " (%s today)\n", btos(traffic.in_today.dcc)); |
1874 | } |
1875 | if (traffic.out_total.unknown > 0 || traffic.out_today.unknown > 0) { |
1876 | dprintf(idx, "Misc:\n"); |
1877 | dprintf(idx, " out: %s", btos(traffic.out_total.unknown + traffic.out_today.unknown)); |
1878 | dprintf(idx, " (%s today)\n", btos(traffic.out_today.unknown)); |
1879 | dprintf(idx, " in: %s", btos(traffic.in_total.unknown + traffic.in_today.unknown)); |
1880 | dprintf(idx, " (%s today)\n", btos(traffic.in_today.unknown)); |
1881 | } |
1882 | dprintf(idx, "---\n"); |
1883 | dprintf(idx, "Total:\n"); |
1884 | itmp = traffic.out_total.irc + traffic.out_total.bn + traffic.out_total.dcc + |
1885 | traffic.out_total.unknown + traffic.out_today.irc + |
1886 | traffic.out_today.dcc + traffic.out_today.unknown; |
1887 | itmp2 = traffic.out_today.irc + traffic.out_today.dcc + |
1888 | traffic.out_today.unknown; |
1889 | dprintf(idx, " out: %s", btos(itmp)); |
1890 | dprintf(idx, " (%s today)\n", btos(itmp2)); |
1891 | dprintf(idx, " in: %s", btos(traffic.in_total.irc + traffic.in_total.dcc + |
1892 | traffic.in_total.unknown + traffic.in_today.irc + |
1893 | traffic.in_today.dcc + traffic.in_today.unknown)); |
1894 | dprintf(idx, " (%s today)\n", btos(traffic.in_today.irc + |
1895 | traffic.in_today.dcc + traffic.in_today.unknown)); |
1896 | return(1); |
1897 | } |
1898 | |
1899 | static char traffictxt[20]; |
1900 | static char *btos(unsigned long bytes) |
1901 | { |
1902 | char unit[10]; |
1903 | float xbytes; |
1904 | |
1905 | sprintf(unit, "Bytes"); |
1906 | xbytes = bytes; |
1907 | if (xbytes > 1024.0) { |
1908 | sprintf(unit, "KBytes"); |
1909 | xbytes = xbytes / 1024.0; |
1910 | } |
1911 | if (xbytes > 1024.0) { |
1912 | sprintf(unit, "MBytes"); |
1913 | xbytes = xbytes / 1024.0; |
1914 | } |
1915 | if (xbytes > 1024.0) { |
1916 | sprintf(unit, "GBytes"); |
1917 | xbytes = xbytes / 1024.0; |
1918 | } |
1919 | if (xbytes > 1024.0) { |
1920 | sprintf(unit, "TBytes"); |
1921 | xbytes = xbytes / 1024.0; |
1922 | } |
1923 | if (bytes > 1024) |
1924 | sprintf(traffictxt, "%.2f %s", xbytes, unit); |
1925 | else |
1926 | sprintf(traffictxt, "%lu Bytes", bytes); |
1927 | return traffictxt; |
1928 | } |
1929 | |
1930 | static int cmd_whoami(user_t *u, int idx, char *par) |
1931 | { |
1932 | dprintf(idx, _("You are %s@%s.\n"), dcc[idx].nick, myname); |
1933 | return(1); |
1934 | } |
1935 | |
1936 | static int cmd_quit(user_t *u, int idx, char *text) |
1937 | { |
1938 | dprintf(idx, _("*** Ja mata!\n")); |
1939 | flush_lines(idx, dcc[idx].u.chat); |
1940 | putlog(LOG_MISC, "*", _("DCC connection closed (%s!%s)"), dcc[idx].nick, |
1941 | dcc[idx].host); |
1942 | if (dcc[idx].u.chat->channel >= 0) { |
1943 | chanout_but(-1, dcc[idx].u.chat->channel, "*** %s left the party line%s%s\n", dcc[idx].nick, text[0] ? ": " : ".", text); |
1944 | } |
1945 | |
1946 | if (dcc[idx].u.chat->su_nick) { |
1947 | dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->su_nick); |
1948 | dcc[idx].type = &DCC_CHAT; |
1949 | dprintf(idx, _("Returning to real nick %s!\n"), dcc[idx].u.chat->su_nick); |
1950 | free_null(dcc[idx].u.chat->su_nick); |
1951 | dcc_chatter(idx); |
1952 | } else if ((dcc[idx].sock != STDOUT) || backgrd) { |
1953 | killsock(dcc[idx].sock); |
1954 | lostdcc(idx); |
1955 | } else { |
1956 | dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n"); |
1957 | dcc_chatter(idx); |
1958 | } |
1959 | return(1); |
1960 | } |
1961 | |
1962 | |
1963 | |
1964 | /* DCC CHAT COMMANDS |
1965 | */ |
1966 | /* Function call should be: |
1967 | * int cmd_whatever(idx,"parameters"); |
1968 | * As with msg commands, function is responsible for any logging. |
1969 | */ |
1970 | cmd_t C_dcc[] = |
1971 | { |
1972 | {"+bot", "t", (Function) cmd_pls_bot, NULL}, |
1973 | {"+host", "tm|m", (Function) cmd_pls_host, NULL}, |
1974 | {"+ignore", "m", (Function) cmd_pls_ignore, NULL}, |
1975 | {"+user", "m", (Function) cmd_pls_user, NULL}, |
1976 | {"-bot", "t", (Function) cmd_mns_user, NULL}, |
1977 | {"-host", "", (Function) cmd_mns_host, NULL}, |
1978 | {"-ignore", "m", (Function) cmd_mns_ignore, NULL}, |
1979 | {"-user", "m", (Function) cmd_mns_user, NULL}, |
1980 | {"away", "", (Function) cmd_away, NULL}, |
1981 | {"back", "", (Function) cmd_back, NULL}, |
1982 | {"backup", "m|m", (Function) cmd_backup, NULL}, |
1983 | {"boot", "t", (Function) cmd_boot, NULL}, |
1984 | {"botattr", "t", (Function) cmd_botattr, NULL}, |
1985 | {"chaddr", "t", (Function) cmd_chaddr, NULL}, |
1986 | {"chattr", "m|m", (Function) cmd_chattr, NULL}, |
1987 | {"chhandle", "t", (Function) cmd_chhandle, NULL}, |
1988 | {"chnick", "t", (Function) cmd_chhandle, NULL}, |
1989 | {"chpass", "t", (Function) cmd_chpass, NULL}, |
1990 | {"comment", "m", (Function) cmd_comment, NULL}, |
1991 | {"console", "to|o", (Function) cmd_console, NULL}, |
1992 | {"dccstat", "t", (Function) cmd_dccstat, NULL}, |
1993 | {"die", "n", (Function) cmd_die, NULL}, |
1994 | {"fixcodes", "", (Function) cmd_fixcodes, NULL}, |
1995 | {"help", "", (Function) cmd_help, NULL}, |
1996 | {"ignores", "m", (Function) cmd_ignores, NULL}, |
1997 | {"loadmod", "n", (Function) cmd_loadmod, NULL}, |
1998 | {"match", "to|o", (Function) cmd_match, NULL}, |
1999 | {"me", "", (Function) cmd_me, NULL}, |
2000 | {"module", "m", (Function) cmd_module, NULL}, |
2001 | {"modules", "n", (Function) cmd_modules, NULL}, |
2002 | {"motd", "", (Function) cmd_motd, NULL}, |
2003 | {"newpass", "", (Function) cmd_newpass, NULL}, |
2004 | {"handle", "", (Function) cmd_handle, NULL}, |
2005 | {"page", "", (Function) cmd_page, NULL}, |
2006 | {"quit", "", (Function) cmd_quit, NULL}, |
2007 | {"rehash", "m", (Function) cmd_rehash, NULL}, |
2008 | {"rehelp", "n", (Function) cmd_rehelp, NULL}, |
2009 | {"reload", "m|m", (Function) cmd_reload, NULL}, |
2010 | {"restart", "m", (Function) cmd_restart, NULL}, |
2011 | {"save", "m|m", (Function) cmd_save, NULL}, |
2012 | {"simul", "n", (Function) cmd_simul, NULL}, |
2013 | {"status", "m|m", (Function) cmd_status, NULL}, |
2014 | {"su", "", (Function) cmd_su, NULL}, |
2015 | {"unloadmod", "n", (Function) cmd_unloadmod, NULL}, |
2016 | {"uptime", "m|m", (Function) cmd_uptime, NULL}, |
2017 | {&qu |