/[cvs]/eggdrop1.8/src/botcmd.c
ViewVC logotype

Contents of /eggdrop1.8/src/botcmd.c

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


Revision 1.1 - (show annotations) (download) (as text)
Mon Jul 26 21:11:06 2010 UTC (8 years, 10 months ago) by simple
Branch: MAIN
Branch point for: eggheads
File MIME type: text/x-chdr
Initial revision

1 /*
2 * botcmd.c -- handles:
3 * commands that comes across the botnet
4 * userfile transfer and update commands from sharebots
5 *
6 * $Id: botcmd.c,v 1.52 2010/02/18 09:52:29 pseudo Exp $
7 */
8 /*
9 * Copyright (C) 1997 Robey Pointer
10 * Copyright (C) 1999 - 2010 Eggheads Development Team
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 "users.h"
30 #include "chan.h"
31 #include "modules.h"
32
33 extern char botnetnick[], ver[], admin[], network[], motdfile[];
34 extern int dcc_total, remote_boots, noshare;
35 extern struct dcc_t *dcc;
36 extern struct chanset_t *chanset;
37 extern struct userrec *userlist;
38 extern Tcl_Interp *interp;
39 extern time_t now, online_since;
40 extern party_t *party;
41 extern module_entry *module_list;
42
43 static char TBUF[1024]; /* Static buffer for goofy bot stuff */
44
45 static char base64to[256] = {
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
49 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
50 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, 0, 63, 0, 0, 0, 26, 27, 28,
51 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
52 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
59 };
60
61
62 int base64_to_int(char *buf)
63 {
64 int i = 0;
65
66 while (*buf) {
67 i = i << 6;
68 i += base64to[(int) *buf];
69 buf++;
70 }
71 return i;
72 }
73
74 /* Used for 1.0 compatibility: if a join message arrives with no sock#,
75 * i'll just grab the next "fakesock" # (incrementing to assure uniqueness)
76 */
77 static int fakesock = 2300;
78
79 static void fake_alert(int idx, char *item, char *extra)
80 {
81 static unsigned long lastfake; /* The last time fake_alert was used */
82
83 if (now - lastfake > 10) {
84 #ifndef NO_OLD_BOTNET
85 if (b_numver(idx) < NEAT_BOTNET)
86 dprintf(idx, "chat %s NOTICE: %s (%s != %s).\n",
87 botnetnick, NET_FAKEREJECT, item, extra);
88 else
89 #endif
90 dprintf(idx, "ct %s NOTICE: %s (%s != %s).\n",
91 botnetnick, NET_FAKEREJECT, item, extra);
92 putlog(LOG_BOTS, "*", "%s %s (%s != %s).", dcc[idx].nick, NET_FAKEREJECT,
93 item, extra);
94 lastfake = now;
95 }
96 }
97
98 /* chan <from> <chan> <text>
99 */
100 static void bot_chan2(int idx, char *msg)
101 {
102 char *from, *p, *s;
103 int i, chan;
104
105 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
106 return;
107 from = newsplit(&msg);
108 p = newsplit(&msg);
109 #ifndef NO_OLD_BOTNET
110 if (b_numver(idx) < NEAT_BOTNET)
111 chan = atoi(p);
112 else
113 #endif
114 chan = base64_to_int(p);
115 /* Strip annoying control chars */
116 for (p = s = from; *s; s++)
117 if ((*s > 31) && (*s != 127))
118 *p++ = *s;
119 if (*p)
120 *p = 0;
121 p = strchr(from, '@');
122 if (p) {
123 snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg);
124 *p = 0;
125 if (!partyidle(p + 1, from)) {
126 *p = '@';
127 fake_alert(idx, "user", from);
128 return;
129 }
130 *p = '@';
131 p++;
132 } else {
133 sprintf(TBUF, "*** (%s) %s", from, msg);
134 p = from;
135 }
136 i = nextbot(p);
137 if (i != idx) {
138 fake_alert(idx, "direction", p);
139 } else {
140 chanout_but(-1, chan, "%s\n", TBUF);
141 /* Send to new version bots */
142 if (i >= 0)
143 botnet_send_chan(idx, from, NULL, chan, msg);
144 if (strchr(from, '@') != NULL)
145 check_tcl_chat(from, chan, msg);
146 else
147 check_tcl_bcst(from, chan, msg);
148 }
149 }
150
151 /* chat <from> <notice> -- only from bots
152 */
153 static void bot_chat(int idx, char *par)
154 {
155 char *from;
156 int i;
157
158 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
159 return;
160 from = newsplit(&par);
161 if (strchr(from, '@') != NULL) {
162 fake_alert(idx, "bot", from);
163 return;
164 }
165 /* Make sure the bot is valid */
166 i = nextbot(from);
167 if (i != idx) {
168 fake_alert(idx, "direction", from);
169 return;
170 }
171 chatout("*** (%s) %s\n", from, par);
172 botnet_send_chat(idx, from, par);
173 check_tcl_bcst(from, -1, par);
174 }
175
176 /* actchan <from> <chan> <text>
177 */
178 static void bot_actchan(int idx, char *par)
179 {
180 char *from, *p, *s;
181 int i, chan;
182
183 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
184 return;
185 from = newsplit(&par);
186 p = strchr(from, '@');
187 if (p == NULL) {
188 /* How can a bot do an action? */
189 fake_alert(idx, "user@bot", from);
190 return;
191 }
192 *p = 0;
193 if (!partyidle(p + 1, from)) {
194 *p = '@';
195 fake_alert(idx, "user", from);
196 return;
197 }
198 *p = '@';
199 p++;
200 i = nextbot(p);
201 if (i != idx) {
202 fake_alert(idx, "direction", p);
203 return;
204 }
205 p = newsplit(&par);
206 #ifndef NO_OLD_BOTNET
207 if (b_numver(idx) < NEAT_BOTNET)
208 chan = atoi(p);
209 else
210 #endif
211 chan = base64_to_int(p);
212 for (p = s = from; *s; s++)
213 if ((*s > 31) && (*s != 127))
214 *p++ = *s;
215 if (*p)
216 *p = 0;
217 chanout_but(-1, chan, "* %s %s\n", from, par);
218 botnet_send_act(idx, from, NULL, chan, par);
219 check_tcl_act(from, chan, par);
220 }
221
222 /* priv <from> <to> <message>
223 */
224 static void bot_priv(int idx, char *par)
225 {
226 char *from, *p, *to = TBUF, *tobot;
227 int i;
228
229 from = newsplit(&par);
230 tobot = newsplit(&par);
231 splitc(to, tobot, '@');
232 p = strchr(from, '@');
233 if (p != NULL)
234 p++;
235 else
236 p = from;
237 i = nextbot(p);
238 if (i != idx) {
239 fake_alert(idx, "direction", p);
240 return;
241 }
242 if (!to[0])
243 return; /* Silently ignore notes to '@bot' */
244 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
245 if (p == from)
246 add_note(to, from, par, -2, 0);
247 else {
248 i = add_note(to, from, par, -1, 0);
249 if (from[0] != '@')
250 switch (i) {
251 case NOTE_ERROR:
252 botnet_send_priv(idx, botnetnick, from, NULL,
253 "%s %s.", BOT_NOSUCHUSER, to);
254 break;
255 case NOTE_STORED:
256 botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOTESTORED2);
257 break;
258 case NOTE_FULL:
259 botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOTEBOXFULL);
260 break;
261 case NOTE_AWAY:
262 botnet_send_priv(idx, botnetnick, from, NULL,
263 "%s %s", to, BOT_NOTEISAWAY);
264 break;
265 case NOTE_FWD:
266 botnet_send_priv(idx, botnetnick, from, NULL,
267 "%s %s", "Not online; note forwarded to:", to);
268 break;
269 case NOTE_REJECT:
270 botnet_send_priv(idx, botnetnick, from, NULL,
271 "%s %s", to, "rejected your note.");
272 break;
273 case NOTE_TCL:
274 break; /* Do nothing */
275 case NOTE_OK:
276 botnet_send_priv(idx, botnetnick, from, NULL,
277 "%s %s.", BOT_NOTESENTTO, to);
278 break;
279 }
280 }
281 } else { /* Pass it on */
282 i = nextbot(tobot);
283 if (i >= 0)
284 botnet_send_priv(i, from, to, tobot, "%s", par);
285 }
286 }
287
288 static void bot_bye(int idx, char *par)
289 {
290 char s[1024];
291 int users, bots;
292
293 bots = bots_in_subtree(findbot(dcc[idx].nick));
294 users = users_in_subtree(findbot(dcc[idx].nick));
295 simple_sprintf(s, "%s %s. %s (lost %d bot%s and %d user%s)",
296 BOT_DISCONNECTED, dcc[idx].nick, par[0] ?
297 par : "No reason", bots, (bots != 1) ?
298 "s" : "", users, (users != 1) ? "s" : "");
299 putlog(LOG_BOTS, "*", "%s", s);
300 chatout("*** %s\n", s);
301 botnet_send_unlinked(idx, dcc[idx].nick, s);
302 dprintf(idx, "*bye\n");
303 killsock(dcc[idx].sock);
304 lostdcc(idx);
305 }
306
307 static void remote_tell_who(int idx, char *nick, int chan)
308 {
309 int i = 10, k, l, ok = 0;
310 char s[1024], *realnick;
311 struct chanset_t *c;
312
313 realnick = strchr(nick, ':');
314 if (realnick)
315 realnick++;
316 else
317 realnick = nick;
318 putlog(LOG_BOTS, "*", "#%s# who", realnick);
319 strcpy(s, "Channels: ");
320 for (c = chanset; c; c = c->next)
321 if (!channel_secret(c) && !channel_inactive(c)) {
322 l = strlen(c->dname);
323 if (i + l < 1021) {
324 if (i > 10)
325 sprintf(s, "%s, %s", s, c->dname);
326 else {
327 strcpy(s, c->dname);
328 i += (l + 2);
329 }
330 }
331 }
332 if (i > 10) {
333 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (%s)", s, ver);
334 } else
335 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (%s)", BOT_NOCHANNELS,
336 ver);
337 if (admin[0])
338 botnet_send_priv(idx, botnetnick, nick, NULL, "Admin: %s", admin);
339 if (chan == 0)
340 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (* = owner, + = master,"
341 " %% = botmaster, @ = op, ^ = halfop)", BOT_PARTYMEMBS);
342 else {
343 simple_sprintf(s, "assoc %d", chan);
344 if ((Tcl_Eval(interp, s) != TCL_OK) || tcl_resultempty())
345 botnet_send_priv(idx, botnetnick, nick, NULL, "%s %s%d: (* = owner, + ="
346 " master, %% = botmaster, @ = op, ^ = halfop)\n",
347 BOT_PEOPLEONCHAN, (chan < GLOBAL_CHANS) ? "" : "*",
348 chan % GLOBAL_CHANS);
349 else
350 botnet_send_priv(idx, botnetnick, nick, NULL, "%s '%s' (%s%d): (* = "
351 "owner, + = master, %% = botmaster, @ = op, ^ = halfop)\n",
352 BOT_PEOPLEONCHAN, tcl_resultstring(), (chan < GLOBAL_CHANS) ?
353 "" : "*", chan % GLOBAL_CHANS);
354 }
355 for (i = 0; i < dcc_total; i++)
356 if (dcc[i].type->flags & DCT_REMOTEWHO)
357 if (dcc[i].u.chat->channel == chan) {
358 k = sprintf(s, " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
359 dcc[i].nick, dcc[i].host);
360 if (now - dcc[i].timeval > 300) {
361 unsigned long days, hrs, mins;
362
363 days = (now - dcc[i].timeval) / 86400;
364 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
365 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
366 if (days > 0)
367 sprintf(s + k, " (%s %lud%luh)", MISC_IDLE, days, hrs);
368 else if (hrs > 0)
369 sprintf(s + k, " (%s %luh%lum)", MISC_IDLE, hrs, mins);
370 else
371 sprintf(s + k, " (%s %lum)", MISC_IDLE, mins);
372 }
373 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
374 if (dcc[i].u.chat->away != NULL)
375 botnet_send_priv(idx, botnetnick, nick, NULL, " %s: %s",
376 MISC_AWAY, dcc[i].u.chat->away);
377 }
378 for (i = 0; i < dcc_total; i++)
379 if (dcc[i].type == &DCC_BOT) {
380 if (!ok) {
381 ok = 1;
382 botnet_send_priv(idx, botnetnick, nick, NULL, "%s:", BOT_BOTSCONNECTED);
383 }
384 sprintf(s, " %s%c%-15s %s",
385 dcc[i].status & STAT_CALLED ? "<-" : "->",
386 dcc[i].status & STAT_SHARE ? '+' : ' ',
387 dcc[i].nick, dcc[i].u.bot->version);
388 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
389 }
390 ok = 0;
391 for (i = 0; i < dcc_total; i++)
392 if (dcc[i].type->flags & DCT_REMOTEWHO)
393 if (dcc[i].u.chat->channel != chan) {
394 if (!ok) {
395 ok = 1;
396 botnet_send_priv(idx, botnetnick, nick, NULL, "%s:", BOT_OTHERPEOPLE);
397 }
398 l = sprintf(s, " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
399 dcc[i].nick, dcc[i].host);
400 if (now - dcc[i].timeval > 300) {
401 k = (now - dcc[i].timeval) / 60;
402 if (k < 60)
403 sprintf(s + l, " (%s %dm)", MISC_IDLE, k);
404 else
405 sprintf(s + l, " (%s %dh%dm)", MISC_IDLE, k / 60, k % 60);
406 }
407 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
408 if (dcc[i].u.chat->away != NULL)
409 botnet_send_priv(idx, botnetnick, nick, NULL,
410 " %s: %s", MISC_AWAY, dcc[i].u.chat->away);
411 }
412 }
413
414 /* who <from@bot> <tobot> <chan#>
415 */
416 static void bot_who(int idx, char *par)
417 {
418 char *from, *to, *p;
419 int i, chan;
420
421 from = newsplit(&par);
422 p = strchr(from, '@');
423 if (!p) {
424 sprintf(TBUF, "%s@%s", from, dcc[idx].nick);
425 from = TBUF;
426 }
427 to = newsplit(&par);
428 if (!egg_strcasecmp(to, botnetnick))
429 to[0] = 0;
430 #ifndef NO_OLD_BOTNET
431 if (b_numver(idx) < NEAT_BOTNET)
432 chan = atoi(par);
433 else
434 #endif
435 chan = base64_to_int(par);
436 if (to[0]) {
437 i = nextbot(to);
438 if (i >= 0)
439 botnet_send_who(i, from, to, chan);
440 } else
441 remote_tell_who(idx, from, chan);
442 }
443
444 static void bot_endlink(int idx, char *par)
445 {
446 dcc[idx].status &= ~STAT_LINKING;
447 }
448
449 /* info? <from@bot> -> send priv
450 */
451 static void bot_infoq(int idx, char *par)
452 {
453 char s[200], s2[32], *realnick;
454 struct chanset_t *chan;
455 time_t now2;
456 int hr, min;
457
458 /* Strip the idx from user@bot */
459 realnick = strchr(par, ':');
460 if (realnick)
461 realnick++;
462 else
463 realnick = par;
464 putlog(LOG_BOTS, "*", "#%s# botinfo", realnick);
465
466 now2 = now - online_since;
467 s2[0] = 0;
468 if (now2 > 86400) {
469 int days = now2 / 86400;
470
471 /* Days */
472 sprintf(s2, "%d day", days);
473 if (days >= 2)
474 strcat(s2, "s");
475 strcat(s2, ", ");
476 now2 -= days * 86400;
477 }
478 hr = (time_t) ((int) now2 / 3600);
479 now2 -= (hr * 3600);
480 min = (time_t) ((int) now2 / 60);
481 sprintf(&s2[strlen(s2)], "%02d:%02d", (int) hr, (int) min);
482 if (module_find("server", 0, 0)) {
483 s[0] = 0;
484 for (chan = chanset; chan; chan = chan->next) {
485 if (!channel_secret(chan)) {
486 if ((strlen(s) + strlen(chan->dname) + strlen(network)
487 + strlen(botnetnick) + strlen(ver) + 1) >= 200) {
488 strcat(s, "++ ");
489 break; /* Yegads..! */
490 }
491 strcat(s, chan->dname);
492 strcat(s, ", ");
493 }
494 }
495 if (s[0]) {
496 s[strlen(s) - 2] = 0;
497 botnet_send_priv(idx, botnetnick, par, NULL,
498 "%s <%s> (%s) [UP %s]", ver, network, s, s2);
499 } else
500 botnet_send_priv(idx, botnetnick, par, NULL, "%s <%s> (%s) [UP %s]", ver,
501 network, BOT_NOCHANNELS, s2);
502 } else
503 botnet_send_priv(idx, botnetnick, par, NULL,
504 "%s <NO_IRC> [UP %s]", ver, s2);
505 botnet_send_infoq(idx, par);
506 }
507
508 static void bot_ping(int idx, char *par)
509 {
510 botnet_send_pong(idx);
511 }
512
513 static void bot_pong(int idx, char *par)
514 {
515 dcc[idx].status &= ~STAT_PINGED;
516 }
517
518 /* link <from@bot> <who> <to-whom>
519 */
520 static void bot_link(int idx, char *par)
521 {
522 char *from, *bot, *rfrom;
523 int i;
524
525 from = newsplit(&par);
526 bot = newsplit(&par);
527
528 if (!egg_strcasecmp(bot, botnetnick)) {
529 if ((rfrom = strchr(from, ':')))
530 rfrom++;
531 else
532 rfrom = from;
533 putlog(LOG_CMDS, "*", "#%s# link %s", rfrom, par);
534 if (botlink(from, -1, par))
535 botnet_send_priv(idx, botnetnick, from, NULL, "%s %s ...",
536 BOT_LINKATTEMPT, par);
537 else
538 botnet_send_priv(idx, botnetnick, from, NULL, "%s.", BOT_CANTLINKTHERE);
539 } else {
540 i = nextbot(bot);
541 if (i >= 0)
542 botnet_send_link(i, from, bot, par);
543 }
544 }
545
546 /* unlink <from@bot> <linking-bot> <undesired-bot> <reason>
547 */
548 static void bot_unlink(int idx, char *par)
549 {
550 char *from, *bot, *rfrom, *p, *undes;
551 int i;
552
553 from = newsplit(&par);
554 bot = newsplit(&par);
555 undes = newsplit(&par);
556 if (!egg_strcasecmp(bot, botnetnick)) {
557 if ((rfrom = strchr(from, ':')))
558 rfrom++;
559 else
560 rfrom = from;
561 putlog(LOG_CMDS, "*", "#%s# unlink %s (%s)", rfrom, undes, par[0] ? par :
562 "No reason");
563 i = botunlink(-3, undes, par[0] ? par : NULL, rfrom);
564 if (i == 1) {
565 p = strchr(from, '@');
566 if (p) {
567 /* idx will change after unlink -- get new idx
568 *
569 * TODO: This has changed with the new lostdcc() behaviour. Check
570 * if we can optimise the situation.
571 */
572 i = nextbot(p + 1);
573 if (i >= 0)
574 botnet_send_priv(i, botnetnick, from, NULL,
575 "Unlinked from %s.", undes);
576 }
577 } else if (i == 0) {
578 botnet_send_unlinked(-1, undes, "");
579 p = strchr(from, '@');
580 if (p) {
581 /* Ditto above, about idx */
582 i = nextbot(p + 1);
583 if (i >= 0)
584 botnet_send_priv(i, botnetnick, from, NULL,
585 "%s %s.", BOT_CANTUNLINK, undes);
586 }
587 } else {
588 p = strchr(from, '@');
589 if (p) {
590 i = nextbot(p + 1);
591 if (i >= 0)
592 botnet_send_priv(i, botnetnick, from, NULL,
593 "Can't remotely unlink sharebots.");
594 }
595 }
596 } else {
597 i = nextbot(bot);
598 if (i >= 0)
599 botnet_send_unlink(i, from, bot, undes, par);
600 }
601 }
602
603 /* Bot next share?
604 */
605 static void bot_update(int idx, char *par)
606 {
607 char *bot, x;
608 int vnum;
609
610 bot = newsplit(&par);
611 x = par[0];
612 if (x)
613 par++;
614 #ifndef NO_OLD_BOTNET
615 if (b_numver(idx) < NEAT_BOTNET)
616 vnum = atoi(par);
617 else
618 #endif
619 vnum = base64_to_int(par);
620 if (in_chain(bot))
621 updatebot(idx, bot, x, vnum);
622 }
623
624 /* Newbot next share?
625 */
626 static void bot_nlinked(int idx, char *par)
627 {
628 char *newbot, *next, *p, s[1024], x;
629 int bogus = 0, i;
630 struct userrec *u;
631
632 newbot = newsplit(&par);
633 next = newsplit(&par);
634 s[0] = 0;
635 if (!next[0]) {
636 putlog(LOG_BOTS, "*", "Invalid eggnet protocol from %s (zapfing)",
637 dcc[idx].nick);
638 simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick,
639 MISC_INVALIDBOT);
640 dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n");
641 } else if ((in_chain(newbot)) || (!egg_strcasecmp(newbot, botnetnick))) {
642 /* Loop! */
643 putlog(LOG_BOTS, "*", "%s %s (mutual: %s)",
644 BOT_LOOPDETECT, dcc[idx].nick, newbot);
645 simple_sprintf(s, "%s %s: disconnecting %s", MISC_LOOP, newbot,
646 dcc[idx].nick);
647 dprintf(idx, "error Loop (%s)\n", newbot);
648 }
649 if (!s[0]) {
650 for (p = newbot; *p; p++)
651 if ((*p < 32) || (*p == 127) || ((p - newbot) >= HANDLEN))
652 bogus = 1;
653 i = nextbot(next);
654 if (i != idx)
655 bogus = 1;
656 }
657 if (bogus) {
658 putlog(LOG_BOTS, "*", "%s %s! (%s -> %s)", BOT_BOGUSLINK, dcc[idx].nick,
659 next, newbot);
660 simple_sprintf(s, "%s: %s %s", BOT_BOGUSLINK, dcc[idx].nick,
661 MISC_DISCONNECTED);
662 dprintf(idx, "error %s (%s -> %s)\n", BOT_BOGUSLINK, next, newbot);
663 }
664 if (bot_flags(dcc[idx].user) & BOT_LEAF) {
665 putlog(LOG_BOTS, "*", "%s %s (%s %s)",
666 BOT_DISCONNLEAF, dcc[idx].nick, newbot, BOT_LINKEDTO);
667 simple_sprintf(s, "%s %s (to %s): %s",
668 BOT_ILLEGALLINK, dcc[idx].nick, newbot, MISC_DISCONNECTED);
669 dprintf(idx, "error %s\n", BOT_YOUREALEAF);
670 }
671 if (s[0]) {
672 chatout("*** %s\n", s);
673 botnet_send_unlinked(idx, dcc[idx].nick, s);
674 dprintf(idx, "bye %s\n", BOT_ILLEGALLINK);
675 killsock(dcc[idx].sock);
676 lostdcc(idx);
677 return;
678 }
679 x = par[0];
680 if (x)
681 par++;
682 else
683 x = '-';
684 #ifndef NO_OLD_BOTNET
685 if (b_numver(idx) < NEAT_BOTNET)
686 i = atoi(par);
687 else
688 #endif
689 i = base64_to_int(par);
690 botnet_send_nlinked(idx, newbot, next, x, i);
691 if (x == '!') {
692 chatout("*** (%s) %s %s.\n", next, NET_LINKEDTO, newbot);
693 x = '-';
694 }
695 addbot(newbot, dcc[idx].nick, next, x, i);
696 check_tcl_link(newbot, next);
697 u = get_user_by_handle(userlist, newbot);
698 if (bot_flags(u) & BOT_REJECT) {
699 botnet_send_reject(idx, botnetnick, NULL, newbot, NULL, NULL);
700 putlog(LOG_BOTS, "*", "%s %s %s %s", BOT_REJECTING,
701 newbot, MISC_FROM, dcc[idx].nick);
702 }
703 }
704
705 #ifndef NO_OLD_BOTNET
706 static void bot_linked(int idx, char *par)
707 {
708 char s[1024];
709 int bots, users;
710
711 bots = bots_in_subtree(findbot(dcc[idx].nick));
712 users = users_in_subtree(findbot(dcc[idx].nick));
713 putlog(LOG_BOTS, "*", "%s", BOT_OLDBOT);
714 simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s",
715 MISC_DISCONNECTED, dcc[idx].nick, MISC_OUTDATED,
716 bots, (bots != 1) ? "s" : "", users, (users != 1) ? "s" : "");
717 chatout("*** %s\n", s);
718 botnet_send_unlinked(idx, dcc[idx].nick, s);
719 killsock(dcc[idx].sock);
720 lostdcc(idx);
721 }
722 #endif /* !NO_OLD_BOTNET */
723
724 static void bot_unlinked(int idx, char *par)
725 {
726 int i;
727 char *bot;
728
729 bot = newsplit(&par);
730 i = nextbot(bot);
731 if ((i >= 0) && (i != idx)) /* Bot is NOT downstream along idx, so
732 * BOGUS! */
733 fake_alert(idx, "direction", bot);
734 else if (i >= 0) { /* Valid bot downstream of idx */
735 if (par[0])
736 chatout("*** (%s) %s\n", lastbot(bot), par);
737 botnet_send_unlinked(idx, bot, par);
738 unvia(idx, findbot(bot));
739 rembot(bot);
740 }
741 /* Otherwise it's not even a valid bot, so just ignore! */
742 }
743
744 /* trace <from@bot> <dest> <chain:chain..>
745 */
746 static void bot_trace(int idx, char *par)
747 {
748 char *from, *dest;
749 int i;
750
751 from = newsplit(&par);
752 dest = newsplit(&par);
753 simple_sprintf(TBUF, "%s:%s", par, botnetnick);
754 botnet_send_traced(idx, from, TBUF);
755 if (egg_strcasecmp(dest, botnetnick) && ((i = nextbot(dest)) > 0))
756 botnet_send_trace(i, from, dest, par);
757 }
758
759 /* traced <to@bot> <chain:chain..>
760 */
761 static void bot_traced(int idx, char *par)
762 {
763 char *to, *p;
764 int i, sock;
765
766 to = newsplit(&par);
767 p = strchr(to, '@');
768 if (p == NULL)
769 p = to;
770 else {
771 *p = 0;
772 p++;
773 }
774 if (!egg_strcasecmp(p, botnetnick)) {
775 time_t t = 0;
776 char *p = par, *ss = TBUF;
777
778 splitc(ss, to, ':');
779 if (ss[0])
780 sock = atoi(ss);
781 else
782 sock = -1;
783 if (par[0] == ':') {
784 t = atoi(par + 1);
785 p = strchr(par + 1, ':');
786 if (p)
787 p++;
788 else
789 p = par + 1;
790 }
791 for (i = 0; i < dcc_total; i++)
792 if ((dcc[i].type->flags & DCT_CHAT) &&
793 (!egg_strcasecmp(dcc[i].nick, to)) &&
794 ((sock == -1) || (sock == dcc[i].sock))) {
795 if (t) {
796 int j = 0;
797
798 {
799 register char *c = p;
800
801 for (; *c != '\0'; c++)
802 if (*c == ':')
803 j++;
804 }
805 dprintf(i, "%s -> %s (%lu secs, %d hop%s)\n", BOT_TRACERESULT, p,
806 now - t, j, (j != 1) ? "s" : "");
807 } else
808 dprintf(i, "%s -> %s\n", BOT_TRACERESULT, p);
809 }
810 } else {
811 i = nextbot(p);
812 if (p != to)
813 *--p = '@';
814 if (i >= 0)
815 botnet_send_traced(i, to, par);
816 }
817 }
818
819 /* reject <from> <bot>
820 */
821 static void bot_reject(int idx, char *par)
822 {
823 char *from, *who, *destbot, *frombot;
824 struct userrec *u;
825 int i;
826
827 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
828 return;
829 from = newsplit(&par);
830 frombot = strchr(from, '@');
831 if (frombot)
832 frombot++;
833 else
834 frombot = from;
835 i = nextbot(frombot);
836 if (i != idx) {
837 fake_alert(idx, "direction", frombot);
838 return;
839 }
840 who = newsplit(&par);
841 if (!(destbot = strchr(who, '@'))) {
842 /* Rejecting a bot */
843 i = nextbot(who);
844 if (i < 0) {
845 botnet_send_priv(idx, botnetnick, from, NULL, "%s %s (%s)",
846 BOT_CANTUNLINK, who, BOT_DOESNTEXIST);
847 } else if (!egg_strcasecmp(dcc[i].nick, who)) {
848 char s[1024];
849
850 /* I'm the connection to the rejected bot */
851 putlog(LOG_BOTS, "*", "%s %s %s", from, MISC_REJECTED, dcc[i].nick);
852 dprintf(i, "bye %s\n", par[0] ? par : MISC_REJECTED);
853 simple_sprintf(s, "%s %s (%s: %s)",
854 MISC_DISCONNECTED, dcc[i].nick, from,
855 par[0] ? par : MISC_REJECTED);
856 chatout("*** %s\n", s);
857 botnet_send_unlinked(i, dcc[i].nick, s);
858 killsock(dcc[i].sock);
859 lostdcc(i);
860 } else {
861 if (i >= 0)
862 botnet_send_reject(i, from, NULL, who, NULL, par);
863 }
864 } else { /* Rejecting user */
865 *destbot++ = 0;
866 if (!egg_strcasecmp(destbot, botnetnick)) {
867 /* Kick someone here! */
868 int ok = 0;
869
870 if (remote_boots == 1) {
871 frombot = strchr(from, '@');
872 if (frombot == NULL)
873 frombot = from;
874 else
875 frombot++;
876 u = get_user_by_handle(userlist, frombot);
877 if (!(bot_flags(u) & BOT_SHARE)) {
878 add_note(from, botnetnick, "No non sharebot boots.", -1, 0);
879 ok = 1;
880 }
881 } else if (remote_boots == 0) {
882 botnet_send_priv(idx, botnetnick, from, NULL, "%s", BOT_NOREMOTEBOOT);
883 ok = 1;
884 }
885 for (i = 0; (i < dcc_total) && (!ok); i++)
886 if ((!egg_strcasecmp(who, dcc[i].nick)) &&
887 (dcc[i].type->flags & DCT_CHAT)) {
888 u = get_user_by_handle(userlist, dcc[i].nick);
889 if (u && (u->flags & USER_OWNER)) {
890 add_note(from, botnetnick, BOT_NOOWNERBOOT, -1, 0);
891 return;
892 }
893 do_boot(i, from, par);
894 ok = 1;
895 putlog(LOG_CMDS, "*", "#%s# boot %s (%s)", from, who,
896 par[0] ? par : "No reason");
897 }
898 } else {
899 i = nextbot(destbot);
900 *--destbot = '@';
901 if (i >= 0)
902 botnet_send_reject(i, from, NULL, who, NULL, par);
903 }
904 }
905 }
906
907 static void bot_thisbot(int idx, char *par)
908 {
909 if (egg_strcasecmp(par, dcc[idx].nick)) {
910 char s[1024];
911
912 putlog(LOG_BOTS, "*", NET_WRONGBOT, dcc[idx].nick, par);
913 dprintf(idx, "bye %s\n", MISC_IMPOSTER);
914 simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick,
915 MISC_IMPOSTER);
916 chatout("*** %s\n", s);
917 botnet_send_unlinked(idx, dcc[idx].nick, s);
918 unvia(idx, findbot(dcc[idx].nick));
919 killsock(dcc[idx].sock);
920 lostdcc(idx);
921 return;
922 }
923 if (bot_flags(dcc[idx].user) & BOT_LEAF)
924 dcc[idx].status |= STAT_LEAF;
925 /* Set capitalization the way they want it */
926 noshare = 1;
927 change_handle(dcc[idx].user, par);
928 noshare = 0;
929 strcpy(dcc[idx].nick, par);
930 }
931
932 static void bot_handshake(int idx, char *par)
933 {
934 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
935
936 /* We *don't* want botnet passwords migrating */
937 noshare = 1;
938 set_user(&USERENTRY_PASS, u, par);
939 noshare = 0;
940 }
941
942 /* Used to send a direct msg from Tcl on one bot to Tcl on another
943 * zapf <frombot> <tobot> <code [param]>
944 */
945 static void bot_zapf(int idx, char *par)
946 {
947 char *from, *to;
948 int i;
949
950 from = newsplit(&par);
951 to = newsplit(&par);
952 i = nextbot(from);
953 if (i != idx) {
954 fake_alert(idx, "direction", from);
955 return;
956 }
957 if (!egg_strcasecmp(to, botnetnick)) {
958 /* For me! */
959 char *opcode;
960
961 opcode = newsplit(&par);
962 check_tcl_bot(from, opcode, par);
963 return;
964 }
965 i = nextbot(to);
966 if (i >= 0)
967 botnet_send_zapf(i, from, to, par);
968 }
969
970 /* Used to send a global msg from Tcl on one bot to every other bot
971 * zapf-broad <frombot> <code [param]>
972 */
973 static void bot_zapfbroad(int idx, char *par)
974 {
975 char *from, *opcode;
976 int i;
977
978 from = newsplit(&par);
979 opcode = newsplit(&par);
980
981 i = nextbot(from);
982 if (i != idx) {
983 fake_alert(idx, "direction", from);
984 return;
985 }
986 check_tcl_bot(from, opcode, par);
987 botnet_send_zapf_broad(idx, from, opcode, par);
988 }
989
990 /* Show motd to someone
991 */
992 static void bot_motd(int idx, char *par)
993 {
994 FILE *vv;
995 char *s = TBUF, *who, *p;
996 int i;
997 struct flag_record fr = { FR_BOT, USER_BOT, 0, 0, 0, 0 };
998
999 who = newsplit(&par);
1000 if (!par[0] || !egg_strcasecmp(par, botnetnick)) {
1001 int irc = 0;
1002
1003 p = strchr(who, ':');
1004 if (p)
1005 p++;
1006 else
1007 p = who;
1008 if (who[0] == '!') {
1009 irc = HELP_IRC;
1010 fr.global |=USER_HIGHLITE;
1011
1012 who++;
1013 } else if (who[0] == '#') {
1014 fr.global |=USER_HIGHLITE;
1015
1016 who++;
1017 }
1018 putlog(LOG_CMDS, "*", "#%s# motd", p);
1019 vv = fopen(motdfile, "r");
1020 if (vv != NULL) {
1021 botnet_send_priv(idx, botnetnick, who, NULL, "--- %s\n", MISC_MOTDFILE);
1022 help_subst(NULL, NULL, 0, irc, NULL);
1023 while (!feof(vv)) {
1024 fgets(s, 120, vv);
1025 if (!feof(vv)) {
1026 if (s[strlen(s) - 1] == '\n')
1027 s[strlen(s) - 1] = 0;
1028 if (!s[0])
1029 strcpy(s, " ");
1030 help_subst(s, who, &fr, HELP_DCC, dcc[idx].nick);
1031 if (s[0])
1032 botnet_send_priv(idx, botnetnick, who, NULL, "%s", s);
1033 }
1034 }
1035 fclose(vv);
1036 } else
1037 botnet_send_priv(idx, botnetnick, who, NULL, "%s :(", MISC_NOMOTDFILE);
1038 } else {
1039 /* Pass it on */
1040 i = nextbot(par);
1041 if (i >= 0)
1042 botnet_send_motd(i, who, par);
1043 }
1044 }
1045
1046 /* These are still here, so that they will pass the relevant
1047 * requests through even if no filesys is loaded.
1048 *
1049 * filereject <bot:filepath> <sock:nick@bot> <reason...>
1050 */
1051 static void bot_filereject(int idx, char *par)
1052 {
1053 char *path, *to, *tobot, *p;
1054 int i;
1055
1056 path = newsplit(&par);
1057 to = newsplit(&par);
1058 if ((tobot = strchr(to, '@')))
1059 tobot++;
1060 else
1061 tobot = to; /* Bot wants a file?! :) */
1062 if (egg_strcasecmp(tobot, botnetnick)) { /* for me! */
1063 p = strchr(to, ':');
1064 if (p != NULL) {
1065 *p = 0;
1066 for (i = 0; i < dcc_total; i++) {
1067 if (dcc[i].sock == atoi(to))
1068 dprintf(i, "%s (%s): %s\n", BOT_XFERREJECTED, path, par);
1069 }
1070 *p = ':';
1071 }
1072 /* No ':'? malformed */
1073 putlog(LOG_FILES, "*", "%s %s: %s", path, MISC_REJECTED, par);
1074 } else { /* Pass it on */
1075 i = nextbot(tobot);
1076 if (i >= 0)
1077 botnet_send_filereject(i, path, to, par);
1078 }
1079 }
1080
1081 /* filereq <sock:nick@bot> <bot:file>
1082 */
1083 static void bot_filereq(int idx, char *tobot)
1084 {
1085 char *from, *path;
1086 int i;
1087
1088 from = newsplit(&tobot);
1089 if ((path = strchr(tobot, ':'))) {
1090 *path++ = 0;
1091
1092 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
1093 /* Process this */
1094 module_entry *fs = module_find("filesys", 0, 0);
1095
1096 if (fs == NULL)
1097 botnet_send_priv(idx, botnetnick, from, NULL, MOD_NOFILESYSMOD);
1098 else {
1099 Function f = fs->funcs[FILESYS_REMOTE_REQ];
1100
1101 f(idx, from, path);
1102 }
1103 } else { /* Pass it on */
1104 i = nextbot(tobot);
1105 if (i >= 0)
1106 botnet_send_filereq(i, from, tobot, path);
1107 }
1108 }
1109 }
1110
1111 /* filesend <bot:path> <sock:nick@bot> <IP#> <port> <size>
1112 */
1113 static void bot_filesend(int idx, char *par)
1114 {
1115 char *botpath, *to, *tobot, *nick;
1116 int i;
1117 char *nfn;
1118
1119 botpath = newsplit(&par);
1120 to = newsplit(&par);
1121 if ((tobot = strchr(to, '@'))) {
1122 *tobot = 0;
1123 tobot++;
1124 } else
1125 tobot = to;
1126 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
1127 nfn = strrchr(botpath, '/');
1128 if (nfn == NULL) {
1129 nfn = strrchr(botpath, ':');
1130 if (nfn == NULL)
1131 nfn = botpath; /* That's odd. */
1132 else
1133 nfn++;
1134 } else
1135 nfn++;
1136 if ((nick = strchr(to, ':')))
1137 nick++;
1138 else
1139 nick = to;
1140 /* Send it to 'nick' as if it's from me */
1141 dprintf(DP_SERVER, "PRIVMSG %s :\001DCC SEND %s %s\001\n", nick, nfn, par);
1142 } else {
1143 i = nextbot(tobot);
1144 if (i >= 0) {
1145 *--tobot = '@';
1146 botnet_send_filesend(i, botpath, to, par);
1147 }
1148 }
1149 }
1150
1151 static void bot_error(int idx, char *par)
1152 {
1153 putlog(LOG_MISC | LOG_BOTS, "*", "%s: %s", dcc[idx].nick, par);
1154 }
1155
1156 /* nc <bot> <sock> <newnick>
1157 */
1158 static void bot_nickchange(int idx, char *par)
1159 {
1160 char *bot, *ssock, *newnick;
1161 int sock, i;
1162
1163 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1164 return;
1165 bot = newsplit(&par);
1166 #ifndef NO_OLD_BOTNET
1167 if (b_numver(idx) < NEAT_BOTNET) {
1168 fake_alert(idx, "botversion", "NEAT_BOTNET");
1169 return;
1170 }
1171 #endif
1172 i = nextbot(bot);
1173 if (i != idx) {
1174 fake_alert(idx, "direction", bot);
1175 return;
1176 }
1177 ssock = newsplit(&par);
1178 sock = base64_to_int(ssock);
1179 newnick = newsplit(&par);
1180 i = partynick(bot, sock, newnick);
1181 if (i < 0) {
1182 fake_alert(idx, "sock#", ssock);
1183 return;
1184 }
1185 chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n",
1186 bot, newnick, party[i].nick);
1187 botnet_send_nkch_part(idx, i, newnick);
1188 }
1189
1190 /* join <bot> <nick> <chan> <flag><sock> <from>
1191 */
1192 static void bot_join(int idx, char *par)
1193 {
1194 char *bot, *nick, *x, *y;
1195 struct userrec *u;
1196 int i, sock, chan, i2, linking = 0;
1197
1198 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1199 return;
1200 bot = newsplit(&par);
1201 #ifndef NO_OLD_BOTNET
1202 if (b_numver(idx) >= NEAT_BOTNET)
1203 #endif
1204 if (bot[0] == '!') {
1205 linking = 1;
1206 bot++;
1207 }
1208 if (b_status(idx) & STAT_LINKING) {
1209 linking = 1;
1210 }
1211 nick = newsplit(&par);
1212 x = newsplit(&par);
1213 #ifndef NO_OLD_BOTNET
1214 if (b_numver(idx) < NEAT_BOTNET)
1215 chan = atoi(x);
1216 else
1217 #endif
1218 chan = base64_to_int(x);
1219 y = newsplit(&par);
1220 if ((chan < 0) || !y[0])
1221 return; /* Woops! pre 1.2.1's send .chat off'ers
1222 * too!! */
1223 if (!y[0]) {
1224 y[0] = '-';
1225 sock = 0;
1226 } else {
1227 #ifndef NO_OLD_BOTNET
1228 if (b_numver(idx) < NEAT_BOTNET)
1229 sock = atoi(y + 1);
1230 else
1231 #endif
1232 sock = base64_to_int(y + 1);
1233 }
1234 /* 1.1 bots always send a sock#, even on a channel change
1235 * so if sock# is 0, this is from an old bot and we must tread softly
1236 * grab old sock# if there is one, otherwise make up one.
1237 */
1238 if (sock == 0)
1239 sock = partysock(bot, nick);
1240 if (sock == 0)
1241 sock = fakesock++;
1242 i = nextbot(bot);
1243 if (i != idx) { /* Ok, garbage from a 1.0g (who uses that
1244 * now?) OR raistlin being evil :) */
1245 fake_alert(idx, "direction", bot);
1246 return;
1247 }
1248 u = get_user_by_handle(userlist, nick);
1249 if (u) {
1250 sprintf(TBUF, "@%s", bot);
1251 touch_laston(u, TBUF, now);
1252 }
1253 i = addparty(bot, nick, chan, y[0], sock, par, &i2);
1254 botnet_send_join_party(idx, linking, i2, i);
1255 if (i != chan) {
1256 if (i >= 0) {
1257 if (b_numver(idx) >= NEAT_BOTNET)
1258 chanout_but(-1, i, "*** (%s) %s %s %s.\n", bot, nick, NET_LEFTTHE,
1259 i ? "channel" : "party line");
1260 check_tcl_chpt(bot, nick, sock, i);
1261 }
1262 if ((b_numver(idx) >= NEAT_BOTNET) && !linking)
1263 chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick, NET_JOINEDTHE,
1264 chan ? "channel" : "party line");
1265 check_tcl_chjn(bot, nick, chan, y[0], sock, par);
1266 }
1267 }
1268
1269 /* part <bot> <nick> <sock> [etc..]
1270 */
1271 static void bot_part(int idx, char *par)
1272 {
1273 char *bot, *nick, *etc;
1274 struct userrec *u;
1275 int sock, partyidx;
1276 int silent = 0;
1277
1278 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1279 return;
1280 bot = newsplit(&par);
1281 if (bot[0] == '!') {
1282 silent = 1;
1283 bot++;
1284 }
1285 nick = newsplit(&par);
1286 etc = newsplit(&par);
1287 #ifndef NO_OLD_BOTNET
1288 if (b_numver(idx) < NEAT_BOTNET) {
1289 sock = atoi(etc);
1290 silent = 1;
1291 } else
1292 #endif
1293 sock = base64_to_int(etc);
1294 if (sock == 0)
1295 sock = partysock(bot, nick);
1296 u = get_user_by_handle(userlist, nick);
1297 if (u) {
1298 sprintf(TBUF, "@%s", bot);
1299 touch_laston(u, TBUF, now);
1300 }
1301 if ((partyidx = getparty(bot, sock)) != -1) {
1302 if (party[partyidx].chan >= 0)
1303 check_tcl_chpt(bot, nick, sock, party[partyidx].chan);
1304 if ((b_numver(idx) >= NEAT_BOTNET) && !silent) {
1305 register int chan = party[partyidx].chan;
1306
1307 if (par[0])
1308 chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", bot, nick,
1309 NET_LEFTTHE, chan ? "channel" : "party line", par);
1310 else
1311 chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick,
1312 NET_LEFTTHE, chan ? "channel" : "party line");
1313 }
1314 botnet_send_part_party(idx, partyidx, par, silent);
1315 remparty(bot, sock);
1316 }
1317 }
1318
1319 /* away <bot> <sock> <message>
1320 * null message = unaway
1321 */
1322 static void bot_away(int idx, char *par)
1323 {
1324 char *bot, *etc;
1325 int sock, partyidx, linking = 0;
1326
1327 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1328 return;
1329 bot = newsplit(&par);
1330 #ifndef NO_OLD_BOTNET
1331 if (b_numver(idx) >= NEAT_BOTNET)
1332 #endif
1333 if (bot[0] == '!') {
1334 linking = 1;
1335 bot++;
1336 }
1337 if (b_status(idx) & STAT_LINKING) {
1338 linking = 1;
1339 }
1340 etc = newsplit(&par);
1341 #ifndef NO_OLD_BOTNET
1342 if (b_numver(idx) < NEAT_BOTNET)
1343 sock = atoi(etc);
1344 else
1345 #endif
1346 sock = base64_to_int(etc);
1347 if (sock == 0)
1348 sock = partysock(bot, etc);
1349 check_tcl_away(bot, sock, par);
1350 if (par[0]) {
1351 partystat(bot, sock, PLSTAT_AWAY, 0);
1352 partyaway(bot, sock, par);
1353 } else
1354 partystat(bot, sock, 0, PLSTAT_AWAY);
1355 partyidx = getparty(bot, sock);
1356 if ((b_numver(idx) >= NEAT_BOTNET) && !linking) {
1357 if (par[0])
1358 chanout_but(-1, party[partyidx].chan,
1359 "*** (%s) %s %s: %s.\n", bot,
1360 party[partyidx].nick, NET_AWAY, par);
1361 else
1362 chanout_but(-1, party[partyidx].chan,
1363 "*** (%s) %s %s.\n", bot, party[partyidx].nick, NET_UNAWAY);
1364 }
1365 botnet_send_away(idx, bot, sock, par, linking);
1366 }
1367
1368 /* (a courtesy info to help during connect bursts)
1369 * idle <bot> <sock> <#secs> [away msg]
1370 */
1371 static void bot_idle(int idx, char *par)
1372 {
1373 char *bot, *work;
1374 int sock, idle;
1375
1376 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1377 return;
1378 bot = newsplit(&par);
1379 work = newsplit(&par);
1380 #ifndef NO_OLD_BOTNET
1381 if (b_numver(idx) < NEAT_BOTNET)
1382 sock = atoi(work);
1383 else
1384 #endif
1385 sock = base64_to_int(work);
1386 if (sock == 0)
1387 sock = partysock(bot, work);
1388 work = newsplit(&par);
1389 #ifndef NO_OLD_BOTNET
1390 if (b_numver(idx) < NEAT_BOTNET)
1391 idle = atoi(work);
1392 else
1393 #endif
1394 idle = base64_to_int(work);
1395 partysetidle(bot, sock, idle);
1396 if (par[0]) {
1397 partystat(bot, sock, PLSTAT_AWAY, 0);
1398 partyaway(bot, sock, par);
1399 }
1400 botnet_send_idle(idx, bot, sock, idle, par);
1401 }
1402
1403 #ifndef NO_OLD_BOTNET
1404
1405 static void bot_ufno(int idx, char *par)
1406 {
1407 putlog(LOG_BOTS, "*", "%s %s: %s", USERF_REJECTED, dcc[idx].nick, par);
1408 dcc[idx].status &= ~STAT_OFFERED;
1409 if (!(dcc[idx].status & STAT_GETTING))
1410 dcc[idx].status &= ~STAT_SHARE;
1411 }
1412
1413 static void bot_old_userfile(int idx, char *par)
1414 {
1415 putlog(LOG_BOTS, "*", "%s %s", USERF_OLDSHARE, dcc[idx].nick);
1416 dprintf(idx, "uf-no %s\n", USERF_ANTIQUESHARE);
1417 }
1418
1419 #endif /* !NO_OLD_BOTNET */
1420
1421 void bot_share(int idx, char *par)
1422 {
1423 sharein(idx, par);
1424 }
1425
1426 /* v <frombot> <tobot> <idx:nick>
1427 */
1428 static void bot_versions(int sock, char *par)
1429 {
1430 char *frombot = newsplit(&par), *tobot, *from;
1431 module_entry *me;
1432
1433 if (nextbot(frombot) != sock)
1434 fake_alert(sock, "versions-direction", frombot);
1435 else if (egg_strcasecmp(tobot = newsplit(&par), botnetnick)) {
1436 if ((sock = nextbot(tobot)) >= 0)
1437 dprintf(sock, "v %s %s %s\n", frombot, tobot, par);
1438 } else {
1439 from = newsplit(&par);
1440 botnet_send_priv(sock, botnetnick, from, frombot, "Modules loaded:\n");
1441 for (me = module_list; me; me = me->next)
1442 botnet_send_priv(sock, botnetnick, from, frombot,
1443 " Module: %s (v%d.%d)\n", me->name, me->major,
1444 me->minor);
1445 botnet_send_priv(sock, botnetnick, from, frombot, "End of module list.\n");
1446 }
1447 }
1448
1449 /* BOT COMMANDS
1450 *
1451 * function call should be:
1452 * int bot_whatever(idx,"parameters");
1453 *
1454 * SORT these, dcc_bot uses a shortcut which requires them sorted
1455 *
1456 * yup, those are tokens there to allow a more efficient botnet as
1457 * time goes on (death to slowly upgrading llama's)
1458 */
1459 botcmd_t C_bot[] =
1460 {
1461 {"a", (IntFunc) bot_actchan},
1462 #ifndef NO_OLD_BOTNET
1463 {"actchan", (IntFunc) bot_actchan},
1464 #endif
1465 {"aw", (IntFunc) bot_away},
1466 {"away", (IntFunc) bot_away},
1467 {"bye", (IntFunc) bot_bye},
1468 {"c", (IntFunc) bot_chan2},
1469 #ifndef NO_OLD_BOTNET
1470 {"chan", (IntFunc) bot_chan2},
1471 {"chat", (IntFunc) bot_chat},
1472 #endif
1473 {"ct", (IntFunc) bot_chat},
1474 {"e", (IntFunc) bot_error},
1475 {"el", (IntFunc) bot_endlink},
1476 #ifndef NO_OLD_BOTNET
1477 {"error", (IntFunc) bot_error},
1478 #endif
1479 {"f!", (IntFunc) bot_filereject},
1480 #ifndef NO_OLD_BOTNET
1481 {"filereject", (IntFunc) bot_filereject},
1482 {"filereq", (IntFunc) bot_filereq},
1483 {"filesend", (IntFunc) bot_filesend},
1484 #endif
1485 {"fr", (IntFunc) bot_filereq},
1486 {"fs", (IntFunc) bot_filesend},
1487 {"h", (IntFunc) bot_handshake},
1488 #ifndef NO_OLD_BOTNET
1489 {"handshake", (IntFunc) bot_handshake},
1490 #endif
1491 {"i", (IntFunc) bot_idle},
1492 {"i?", (IntFunc) bot_infoq},
1493 #ifndef NO_OLD_BOTNET
1494 {"idle", (IntFunc) bot_idle},
1495 {"info?", (IntFunc) bot_infoq},
1496 #endif
1497 {"j", (IntFunc) bot_join},
1498 #ifndef NO_OLD_BOTNET
1499 {"join", (IntFunc) bot_join},
1500 #endif
1501 {"l", (IntFunc) bot_link},
1502 #ifndef NO_OLD_BOTNET
1503 {"link", (IntFunc) bot_link},
1504 {"linked", (IntFunc) bot_linked},
1505 #endif
1506 {"m", (IntFunc) bot_motd},
1507 #ifndef NO_OLD_BOTNET
1508 {"motd", (IntFunc) bot_motd},
1509 #endif
1510 {"n", (IntFunc) bot_nlinked},
1511 {"nc", (IntFunc) bot_nickchange},
1512 #ifndef NO_OLD_BOTNET
1513 {"nlinked", (IntFunc) bot_nlinked},
1514 #endif
1515 {"p", (IntFunc) bot_priv},
1516 #ifndef NO_OLD_BOTNET
1517 {"part", (IntFunc) bot_part},
1518 #endif
1519 {"pi", (IntFunc) bot_ping},
1520 #ifndef NO_OLD_BOTNET
1521 {"ping", (IntFunc) bot_ping},
1522 #endif
1523 {"po", (IntFunc) bot_pong},
1524 #ifndef NO_OLD_BOTNET
1525 {"pong", (IntFunc) bot_pong},
1526 {"priv", (IntFunc) bot_priv},
1527 #endif
1528 {"pt", (IntFunc) bot_part},
1529 {"r", (IntFunc) bot_reject},
1530 #ifndef NO_OLD_BOTNET
1531 {"reject", (IntFunc) bot_reject},
1532 #endif
1533 {"s", (IntFunc) bot_share},
1534 {"t", (IntFunc) bot_trace},
1535 {"tb", (IntFunc) bot_thisbot},
1536 {"td", (IntFunc) bot_traced},
1537 #ifndef NO_OLD_BOTNET
1538 {"thisbot", (IntFunc) bot_thisbot},
1539 {"trace", (IntFunc) bot_trace},
1540 {"traced", (IntFunc) bot_traced},
1541 #endif
1542 {"u", (IntFunc) bot_update},
1543 #ifndef NO_OLD_BOTNET
1544 {"uf-no", (IntFunc) bot_ufno},
1545 #endif
1546 {"ul", (IntFunc) bot_unlink},
1547 {"un", (IntFunc) bot_unlinked},
1548 #ifndef NO_OLD_BOTNET
1549 {"unaway", (IntFunc) bot_away},
1550 {"unlink", (IntFunc) bot_unlink},
1551 {"unlinked", (IntFunc) bot_unlinked},
1552 {"update", (IntFunc) bot_update},
1553 {"userfile?", (IntFunc) bot_old_userfile},
1554 #endif
1555 {"v", (IntFunc) bot_versions},
1556 {"w", (IntFunc) bot_who},
1557 #ifndef NO_OLD_BOTNET
1558 {"who", (IntFunc) bot_who},
1559 #endif
1560 {"z", (IntFunc) bot_zapf},
1561 #ifndef NO_OLD_BOTNET
1562 {"zapf", (IntFunc) bot_zapf},
1563 {"zapf-broad", (IntFunc) bot_zapfbroad},
1564 #endif
1565 {"zb", (IntFunc) bot_zapfbroad},
1566 {NULL, NULL}
1567 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23