/[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.105 - (show annotations) (download) (as text)
Mon Jun 17 06:04:36 2002 UTC (17 years, 5 months ago) by guppy
Branch: MAIN
Changes since 1.104: +1 -43 lines
File MIME type: text/x-chdr
removed some legacy commands that are fairly non-useful and addhost which is just wrong.

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