/[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.30 - (show annotations) (download) (as text)
Sat Jun 3 12:14:40 2000 UTC (19 years, 6 months ago) by fabian
Branch: MAIN
Changes since 1.29: +4 -9 lines
File MIME type: text/x-chdr
channame2dname patch

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