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

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

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


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

1 simple 1.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