/[cvs]/eggdrop1.9/src/cmds.c
ViewVC logotype

Contents of /eggdrop1.9/src/cmds.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


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