/[cvs]/eggdrop1.4/src/botnet.c
ViewVC logotype

Annotation of /eggdrop1.4/src/botnet.c

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


Revision 1.2 - (hide annotations) (download) (as text)
Sat Oct 9 22:24:15 1999 UTC (20 years, 2 months ago) by guppy
Branch: MAIN
Changes since 1.1: +1 -1 lines
File MIME type: text/x-chdr
blah ... I need a drink

1 segfault 1.1 /*
2     * botnet.c -- handles:
3     * keeping track of which bot's connected where in the chain
4     * dumping a list of bots or a bot tree to a user
5     * channel name associations on the party line
6     * rejecting a bot
7     * linking, unlinking, and relaying to another bot
8     * pinging the bots periodically and checking leaf status
9     * dprintf'ized, 28nov1995
10     */
11     /*
12     * This file is part of the eggdrop source code
13     * copyright (c) 1997 Robey Pointer
14     * and is distributed according to the GNU general public license.
15     * For full details, read the top of 'main.c' or the file called
16     * COPYING that was distributed with this code.
17     */
18    
19     #include "main.h"
20     #include "tandem.h"
21    
22     extern int dcc_total, backgrd;
23     extern struct dcc_t *dcc;
24     extern int connect_timeout;
25     extern int max_dcc;
26     extern time_t now;
27     extern int egg_numver;
28     extern struct userrec *userlist;
29     extern Tcl_Interp *interp;
30     extern char spaces[];
31     extern char spaces2[];
32    
33     tand_t *tandbot; /* keep track of tandem bots on the botnet */
34     party_t *party; /* keep track of people on the botnet */
35     static int maxparty = 50; /* maximum space for party line members
36     * currently */
37     int tands = 0; /* number of bots on the botnet */
38     int parties = 0; /* number of people on the botnet */
39     char botnetnick[HANDLEN + 1] = ""; /* botnet nickname */
40     int share_unlinks = 0; /* allow remote unlinks of my sharebots ? */
41    
42     int expmem_botnet()
43     {
44     int size = 0, i;
45     tand_t *bot;
46    
47     for (bot = tandbot; bot; bot = bot->next)
48     size += sizeof(tand_t);
49     context;
50     size += (maxparty * sizeof(party_t));
51     for (i = 0; i < parties; i++) {
52     if (party[i].away)
53     size += strlen(party[i].away) + 1;
54     if (party[i].from)
55     size += strlen(party[i].from) + 1;
56     }
57     return size;
58     }
59    
60     void init_bots()
61     {
62     tandbot = NULL;
63     /* grab space for 50 bots for now -- expand later as needed */
64     maxparty = 50;
65     party = (party_t *) nmalloc(maxparty * sizeof(party_t));
66     }
67    
68     tand_t *findbot(char *who)
69     {
70     tand_t *ptr = tandbot;
71    
72     while (ptr) {
73     if (!strcasecmp(ptr->bot, who))
74     return ptr;
75     ptr = ptr->next;
76     }
77     return NULL;
78     }
79    
80     /* add a tandem bot to our chain list */
81     void addbot(char *who, char *from, char *next, char flag, int vernum)
82     {
83     tand_t **ptr = &tandbot, *ptr2;
84    
85     context;
86     while (*ptr) {
87     if (!strcasecmp((*ptr)->bot, who))
88     putlog(LOG_BOTS, "*", "!!! Duplicate botnet bot entry!!");
89     ptr = &((*ptr)->next);
90     }
91     ptr2 = nmalloc(sizeof(tand_t));
92     strncpy(ptr2->bot, who, HANDLEN);
93     ptr2->bot[HANDLEN] = 0;
94     ptr2->share = flag;
95     ptr2->ver = vernum;
96     ptr2->next = *ptr;
97     *ptr = ptr2;
98     /* may be via itself */
99     ptr2->via = findbot(from);
100     if (!strcasecmp(next, botnetnick))
101     ptr2->uplink = (tand_t *) 1;
102     else
103     ptr2->uplink = findbot(next);
104     tands++;
105     }
106    
107     void updatebot(int idx, char *who, char share, int vernum)
108     {
109     tand_t *ptr = findbot(who);
110    
111     context;
112     if (ptr) {
113     if (share)
114     ptr->share = share;
115     if (vernum)
116     ptr->ver = vernum;
117     botnet_send_update(idx, ptr);
118     }
119     }
120    
121     /* for backward 1.0 compatibility: */
122     /* grab the (first) sock# for a user on another bot */
123     int partysock(char *bot, char *nick)
124     {
125     int i;
126    
127     for (i = 0; i < parties; i++) {
128     if ((!strcasecmp(party[i].bot, bot)) &&
129     (!strcasecmp(party[i].nick, nick)))
130     return party[i].sock;
131     }
132     return 0;
133     }
134    
135     /* new botnet member */
136     int addparty(char *bot, char *nick, int chan, char flag, int sock,
137     char *from, int *idx)
138     {
139     int i;
140    
141     context;
142     for (i = 0; i < parties; i++) {
143     /* just changing the channel of someone already on? */
144     if (!strcasecmp(party[i].bot, bot) &&
145     (party[i].sock == sock)) {
146     int oldchan = party[i].chan;
147    
148     party[i].chan = chan;
149     party[i].timer = now;
150     if (from[0]) {
151     if (flag == ' ')
152     flag = '-';
153     party[i].flag = flag;
154     if (party[i].from)
155     nfree(party[i].from);
156     party[i].from = nmalloc(strlen(from) + 1);
157     strcpy(party[i].from, from);
158     }
159     *idx = i;
160     return oldchan;
161     }
162     }
163     /* new member */
164     if (parties == maxparty) {
165     maxparty += 50;
166     party = (party_t *) nrealloc((void *) party, maxparty * sizeof(party_t));
167     }
168     strncpy(party[parties].nick, nick, HANDLEN);
169     party[parties].nick[HANDLEN] = 0;
170     strncpy(party[parties].bot, bot, HANDLEN);
171     party[parties].bot[HANDLEN] = 0;
172     party[parties].chan = chan;
173     party[parties].sock = sock;
174     party[parties].status = 0;
175     party[parties].away = 0;
176     party[parties].timer = now; /* cope. */
177     if (from[0]) {
178     if (flag == ' ')
179     flag = '-';
180     party[parties].flag = flag;
181     party[parties].from = nmalloc(strlen(from) + 1);
182     strcpy(party[parties].from, from);
183     } else {
184     party[parties].flag = ' ';
185     party[parties].from = nmalloc(10);
186     strcpy(party[parties].from, "(unknown)");
187     }
188     *idx = parties;
189     parties++;
190     return -1;
191     }
192    
193     /* alter status flags for remote party-line user */
194     void partystat(char *bot, int sock, int add, int rem)
195     {
196     int i;
197    
198     for (i = 0; i < parties; i++) {
199     if ((!strcasecmp(party[i].bot, bot)) &&
200     (party[i].sock == sock)) {
201     party[i].status |= add;
202     party[i].status &= ~rem;
203     }
204     }
205     }
206    
207     /* other bot is sharing idle info */
208     void partysetidle(char *bot, int sock, int secs)
209     {
210     int i;
211    
212     for (i = 0; i < parties; i++) {
213     if ((!strcasecmp(party[i].bot, bot)) &&
214     (party[i].sock == sock)) {
215     party[i].timer = (now - (time_t) secs);
216     }
217     }
218     }
219    
220     /* return someone's chat channel */
221     int getparty(char *bot, int sock)
222     {
223     int i;
224    
225     for (i = 0; i < parties; i++) {
226     if (!strcasecmp(party[i].bot, bot) &&
227     (party[i].sock == sock)) {
228     return i;
229     }
230     }
231     return -1;
232     }
233    
234     /* un-idle someone */
235     int partyidle(char *bot, char *nick)
236     {
237     int i, ok = 0;
238    
239     for (i = 0; i < parties; i++) {
240     if ((!strcasecmp(party[i].bot, bot)) &&
241     (!strcasecmp(party[i].nick, nick))) {
242     party[i].timer = now;
243     ok = 1;
244     }
245     }
246     return ok;
247     }
248    
249     /* change someone's nick */
250     int partynick(char *bot, int sock, char *nick)
251     {
252     char work[HANDLEN + 1];
253     int i;
254    
255     for (i = 0; i < parties; i++) {
256     if (!strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
257     strcpy(work, party[i].nick);
258     strncpy(party[i].nick, nick, HANDLEN);
259     party[i].nick[HANDLEN] = 0;
260     strcpy(nick, work);
261     return i;
262     }
263     }
264     return -1;
265     }
266    
267     /* set away message */
268     void partyaway(char *bot, int sock, char *msg)
269     {
270     int i;
271    
272     for (i = 0; i < parties; i++) {
273     if ((!strcasecmp(party[i].bot, bot)) &&
274     (party[i].sock == sock)) {
275     if (party[i].away)
276     nfree(party[i].away);
277     if (msg[0]) {
278     party[i].away = nmalloc(strlen(msg) + 1);
279     strcpy(party[i].away, msg);
280     } else
281     party[i].away = 0;
282     }
283     }
284     }
285    
286     /* remove a tandem bot from the chain list */
287     void rembot(char *who)
288     {
289     tand_t **ptr = &tandbot, *ptr2;
290    
291     context;
292     while (*ptr) {
293     if (!strcasecmp((*ptr)->bot, who))
294     break;
295     ptr = &((*ptr)->next);
296     }
297     if (!*ptr)
298     /* may have just .unlink *'d */
299     return;
300     check_tcl_disc(who);
301    
302     ptr2 = *ptr;
303     *ptr = ptr2->next;
304     nfree(ptr2);
305     tands--;
306     }
307    
308     void remparty(char *bot, int sock)
309     {
310     int i;
311    
312     context;
313     for (i = 0; i < parties; i++)
314     if ((!strcasecmp(party[i].bot, bot)) &&
315     (party[i].sock == sock)) {
316     parties--;
317     if (party[i].from)
318     nfree(party[i].from);
319     if (party[i].away)
320     nfree(party[i].away);
321     if (i < parties) {
322     strcpy(party[i].bot, party[parties].bot);
323     strcpy(party[i].nick, party[parties].nick);
324     party[i].chan = party[parties].chan;
325     party[i].sock = party[parties].sock;
326     party[i].flag = party[parties].flag;
327     party[i].status = party[parties].status;
328     party[i].timer = party[parties].timer;
329     party[i].from = party[parties].from;
330     party[i].away = party[parties].away;
331     }
332     }
333     }
334    
335     /* cancel every user that was on a certain bot */
336     void rempartybot(char *bot)
337     {
338     int i;
339    
340     for (i = 0; i < parties; i++)
341     if (!strcasecmp(party[i].bot, bot)) {
342     check_tcl_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
343     remparty(bot, party[i].sock);
344     i--;
345     }
346     }
347    
348     /* remove every bot linked 'via' bot <x> */
349     void unvia(int idx, tand_t * who)
350     {
351     tand_t *bot, *bot2;
352    
353     if (!who)
354     return; /* safety */
355     rempartybot(who->bot);
356     bot = tandbot;
357     while (bot) {
358     if (bot->uplink == who) {
359     unvia(idx, bot);
360     bot2 = bot->next;
361     rembot(bot->bot);
362     bot = bot2;
363     } else
364     bot = bot->next;
365     }
366     #ifndef NO_OLD_BOTNET
367     /* every bot unvia's bots behind anyway, so why send msg's for
368     * EVERY one? - will this break things?! */
369     tandout_but(idx, "unlinked %s\n", who->bot);
370     #endif
371     }
372    
373     /* return index into dcc list of the bot that connects us to bot <x> */
374     int nextbot(char *who)
375     {
376     int j;
377     tand_t *bot = findbot(who);
378    
379     if (!bot)
380     return -1;
381    
382     for (j = 0; j < dcc_total; j++)
383     if (bot->via && !strcasecmp(bot->via->bot, dcc[j].nick) &&
384     (dcc[j].type == &DCC_BOT))
385     return j;
386     return -1; /* we're not connected to 'via' */
387     }
388    
389     /* return name of the bot that is directly connected to bot X */
390     char *lastbot(char *who)
391     {
392     tand_t *bot = findbot(who);
393    
394     if (!bot)
395     return "*";
396     else if (bot->uplink == (tand_t *) 1)
397     return botnetnick;
398     else
399     return bot->uplink->bot;
400     }
401    
402     /* modern version of 'whom' (use local data) */
403     void answer_local_whom(int idx, int chan)
404     {
405     char c, idle[40], spaces2[33] = " ";
406     int i, len, len2;
407    
408     context;
409     if (chan == (-1))
410     dprintf(idx, "%s (+: %s, *: %s)\n", BOT_BOTNETUSERS, BOT_PARTYLINE,
411     BOT_LOCALCHAN);
412     else if (chan > 0) {
413     simple_sprintf(idle, "assoc %d", chan);
414     if ((Tcl_Eval(interp, idle) != TCL_OK) || !interp->result[0])
415     dprintf(idx, "%s %s%d:\n", BOT_USERSONCHAN,
416     (chan < 100000) ? "" : "*", chan % 100000);
417     else
418     dprintf(idx, "%s '%s%s' (%s%d):\n", BOT_USERSONCHAN,
419     (chan < 100000) ? "" : "*", interp->result,
420     (chan < 100000) ? "" : "*", chan % 100000);
421     }
422     spaces[HANDLEN - 9] = 0;
423     dprintf(idx, " Nick %s Bot %s Host\n", spaces, spaces);
424     dprintf(idx, "----------%s ---------%s --------------------\n",
425     spaces, spaces);
426     spaces[HANDLEN - 9] = ' ';
427     for (i = 0; i < dcc_total; i++)
428     if (dcc[i].type == &DCC_CHAT) {
429     if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
430     c = geticon(i);
431     if (c == '-')
432     c = ' ';
433     if (now - dcc[i].timeval > 300) {
434     unsigned long days, hrs, mins;
435    
436     days = (now - dcc[i].timeval) / 86400;
437     hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
438     mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
439     if (days > 0)
440     sprintf(idle, " [idle %lud%luh]", days, hrs);
441     else if (hrs > 0)
442     sprintf(idle, " [idle %luh%lum]", hrs, mins);
443     else
444     sprintf(idle, " [idle %lum]", mins);
445     } else
446     idle[0] = 0;
447     spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
448     spaces2[len2 = HANDLEN - strlen(botnetnick)] = 0;
449     dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, dcc[i].nick, spaces,
450     (dcc[i].u.chat->channel == 0) && (chan == (-1)) ? '+' :
451     (dcc[i].u.chat->channel > 100000) &&
452     (chan == (-1)) ? '*' : ' ',
453     botnetnick, spaces2, dcc[i].host, idle);
454     spaces[len] = ' ';
455     spaces2[len2] = ' ';
456     if (dcc[i].u.chat->away != NULL)
457     dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
458     }
459     }
460     for (i = 0; i < parties; i++) {
461     if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
462     c = party[i].flag;
463     if (c == '-')
464     c = ' ';
465     if (party[i].timer == 0L)
466     strcpy(idle, " [idle?]");
467     else if (now - party[i].timer > 300) {
468     unsigned long days, hrs, mins;
469    
470     days = (now - party[i].timer) / 86400;
471     hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
472     mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
473     if (days > 0)
474     sprintf(idle, " [idle %lud%luh]", days, hrs);
475     else if (hrs > 0)
476     sprintf(idle, " [idle %luh%lum]", hrs, mins);
477     else
478     sprintf(idle, " [idle %lum]", mins);
479     } else
480     idle[0] = 0;
481     spaces[len = HANDLEN - strlen(party[i].nick)] = 0;
482     spaces2[len2 = HANDLEN - strlen(party[i].bot)] = 0;
483     dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, party[i].nick, spaces,
484     (party[i].chan == 0) && (chan == (-1)) ? '+' : ' ',
485     party[i].bot, spaces2, party[i].from, idle);
486     spaces[len] = ' ';
487     spaces2[len2] = ' ';
488     if (party[i].status & PLSTAT_AWAY)
489     dprintf(idx, " %s: %s\n", MISC_AWAY, safe_str(party[i].away));
490     }
491     }
492     }
493    
494     /* show z a list of all bots connected */
495     void tell_bots(int idx)
496     {
497     char s[512];
498     int i;
499     tand_t *bot;
500    
501     if (!tands) {
502     dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
503     return;
504     }
505     strcpy(s, botnetnick);
506     i = strlen(botnetnick);
507    
508     for (bot = tandbot; bot; bot = bot->next) {
509     if (i > (500 - HANDLEN)) {
510     dprintf(idx, "Bots: %s\n", s);
511     s[0] = 0;
512     i = 0;
513     }
514     if (i) {
515     s[i++] = ',';
516     s[i++] = ' ';
517     }
518     strcpy(s + i, bot->bot);
519     i += strlen(bot->bot);
520     }
521     if (s[0])
522     dprintf(idx, "Bots: %s\n", s);
523     dprintf(idx, "(%s: %d)\n", MISC_TOTAL, tands + 1);
524     }
525    
526     /* show a simpleton bot tree */
527     void tell_bottree(int idx, int showver)
528     {
529     char s[161];
530     tand_t *last[20], *this, *bot, *bot2 = NULL;
531     int lev = 0, more = 1, mark[20], ok, cnt, i, imark;
532     char work[1024];
533     int tothops = 0;
534    
535     if (tands == 0) {
536     dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
537     return;
538     }
539     s[0] = 0;
540     i = 0;
541    
542     for (bot = tandbot; bot; bot = bot->next)
543     if (!bot->uplink) {
544     if (i) {
545     s[i++] = ',';
546     s[i++] = ' ';
547     }
548     strcpy(s + i, bot->bot);
549     i += strlen(bot->bot);
550     }
551     if (s[0])
552     dprintf(idx, "(%s %s)\n", BOT_NOTRACEINFO, s);
553     if (showver)
554     dprintf(idx, "%s (%d.%d.%d.%d)\n", botnetnick,
555     egg_numver / 1000000,
556     egg_numver % 1000000 / 10000,
557     egg_numver % 10000 / 100,
558     egg_numver % 100);
559     else
560     dprintf(idx, "%s\n", botnetnick);
561     this = (tand_t *) 1;
562     work[0] = 0;
563     while (more) {
564     if (lev == 20) {
565     dprintf(idx, "\n%s\n", BOT_COMPLEXTREE);
566     return;
567     }
568     cnt = 0;
569     tothops += lev;
570     for (bot = tandbot; bot; bot = bot->next)
571     if (bot->uplink == this)
572     cnt++;
573     if (cnt) {
574     imark = 0;
575     for (i = 0; i < lev; i++) {
576     if (mark[i])
577     strcpy(work + imark, " | ");
578     else
579     strcpy(work + imark, " ");
580     imark += 5;
581     }
582     if (cnt > 1)
583     strcpy(work + imark, " |-");
584     else
585     strcpy(work + imark, " `-");
586     s[0] = 0;
587     bot = tandbot;
588     while (!s[0]) {
589     if (bot->uplink == this) {
590     if (bot->ver) {
591     i = sprintf(s, "%c%s", bot->share, bot->bot);
592     if (showver)
593     sprintf(s + i, " (%d.%d.%d.%d)",
594     bot->ver / 1000000,
595     bot->ver % 1000000 / 10000,
596     bot->ver % 10000 / 100,
597     bot->ver % 100);
598     } else {
599     sprintf(s, "-%s", bot->bot);
600     }
601     } else
602     bot = bot->next;
603     }
604     dprintf(idx, "%s%s\n", work, s);
605     if (cnt > 1)
606     mark[lev] = 1;
607     else
608     mark[lev] = 0;
609     work[0] = 0;
610     last[lev] = this;
611     this = bot;
612     lev++;
613     more = 1;
614     } else {
615     while (cnt == 0) {
616     /* no subtrees from here */
617     if (lev == 0) {
618     dprintf(idx, "(( tree error ))\n");
619     return;
620     }
621     ok = 0;
622     for (bot = tandbot; bot; bot = bot->next) {
623     if (bot->uplink == last[lev - 1]) {
624     if (this == bot)
625     ok = 1;
626     else if (ok) {
627     cnt++;
628     if (cnt == 1) {
629     bot2 = bot;
630     if (bot->ver) {
631     i = sprintf(s, "%c%s", bot->share, bot->bot);
632     if (showver)
633     sprintf(s + i, " (%d.%d.%d.%d)",
634     bot->ver / 1000000,
635     bot->ver % 1000000 / 10000,
636     bot->ver % 10000 / 100,
637     bot->ver % 100);
638     } else {
639     sprintf(s, "-%s", bot->bot);
640     }
641     }
642     }
643     }
644     }
645     if (cnt) {
646     imark = 0;
647     for (i = 1; i < lev; i++) {
648     if (mark[i - 1])
649     strcpy(work + imark, " | ");
650     else
651     strcpy(work + imark, " ");
652     imark += 5;
653     }
654     more = 1;
655     if (cnt > 1)
656     dprintf(idx, "%s |-%s\n", work, s);
657     else
658     dprintf(idx, "%s `-%s\n", work, s);
659     this = bot2;
660     work[0] = 0;
661     if (cnt > 1)
662     mark[lev - 1] = 1;
663     else
664     mark[lev - 1] = 0;
665     } else {
666     /* this was the last child */
667     lev--;
668     if (lev == 0) {
669     more = 0;
670     cnt = 999;
671     } else {
672     more = 1;
673     this = last[lev];
674     }
675     }
676     }
677     }
678     }
679     /* hop information: (9d) */
680     dprintf(idx, "Average hops: %3.1f, total bots: %d\n",
681     ((float) tothops) / ((float) tands), tands + 1);
682     }
683    
684     /* dump list of links to a new bot */
685     void dump_links(int z)
686     {
687     int i, l;
688     char x[1024];
689     tand_t *bot;
690    
691     context;
692     for (bot = tandbot; bot; bot = bot->next) {
693     char *p;
694    
695     if (bot->uplink == (tand_t *) 1)
696     p = botnetnick;
697     else
698     p = bot->uplink->bot;
699     #ifndef NO_OLD_BOTNET
700     if (b_numver(z) < NEAT_BOTNET)
701     l = simple_sprintf(x, "nlinked %s %s %c%d\n", bot->bot,
702     p, bot->share, bot->ver);
703     else
704     #endif
705     l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p,
706     bot->share, bot->ver);
707     tputs(dcc[z].sock, x, l);
708     }
709     context;
710     if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
711     /* dump party line members */
712     for (i = 0; i < dcc_total; i++) {
713     if (dcc[i].type == &DCC_CHAT) {
714     if ((dcc[i].u.chat->channel >= 0) &&
715     (dcc[i].u.chat->channel < 100000)) {
716     #ifndef NO_OLD_BOTNET
717     if (b_numver(z) < NEAT_BOTNET)
718     l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
719     botnetnick, dcc[i].nick,
720     dcc[i].u.chat->channel, geticon(i),
721     dcc[i].sock, dcc[i].host);
722     else
723     #endif
724     l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
725     botnetnick, dcc[i].nick,
726     dcc[i].u.chat->channel, geticon(i),
727     dcc[i].sock, dcc[i].host);
728     tputs(dcc[z].sock, x, l);
729     #ifndef NO_OLD_BOTNET
730     if (b_numver(z) < NEAT_BOTNET) {
731     if (dcc[i].u.chat->away) {
732     l = simple_sprintf(x, "away %s %d %s\n", botnetnick,
733     dcc[i].sock, dcc[i].u.chat->away);
734     tputs(dcc[z].sock, x, l);
735     }
736     l = simple_sprintf(x, "idle %s %d %d\n", botnetnick,
737     dcc[i].sock, now - dcc[i].timeval);
738     } else
739     #endif
740     l = simple_sprintf(x, "i %s %D %D %s\n", botnetnick,
741     dcc[i].sock, now - dcc[i].timeval,
742     dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
743     tputs(dcc[z].sock, x, l);
744     }
745     }
746     }
747     context;
748     for (i = 0; i < parties; i++) {
749     #ifndef NO_OLD_BOTNET
750     if (b_numver(z) < NEAT_BOTNET)
751     l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
752     party[i].bot, party[i].nick,
753     party[i].chan, party[i].flag,
754     party[i].sock, party[i].from);
755     else
756     #endif
757     l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
758     party[i].bot, party[i].nick,
759     party[i].chan, party[i].flag,
760     party[i].sock, party[i].from);
761     tputs(dcc[z].sock, x, l);
762     if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
763     #ifndef NO_OLD_BOTNET
764     if (b_numver(z) < NEAT_BOTNET) {
765     if (party[i].status & PLSTAT_AWAY) {
766     l = simple_sprintf(x, "away %s %d %s\n", party[i].bot,
767     party[i].sock, party[i].away);
768     tputs(dcc[z].sock, x, l);
769     }
770     l = simple_sprintf(x, "idle %s %d %d\n", party[i].bot,
771     party[i].sock, now - party[i].timer);
772     } else
773     #endif
774     l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
775     party[i].sock, now - party[i].timer,
776     party[i].away ? party[i].away : "");
777     tputs(dcc[z].sock, x, l);
778     }
779     }
780     }
781     context;
782     }
783    
784     int in_chain(char *who)
785     {
786     if (findbot(who))
787     return 1;
788     if (!strcasecmp(who, botnetnick))
789     return 1;
790     return 0;
791     }
792    
793     /* break link with a tandembot */
794     int botunlink(int idx, char *nick, char *reason)
795     {
796     char s[20];
797     int i;
798    
799     context;
800     if (nick[0] == '*')
801     dprintf(idx, "%s\n", BOT_UNLINKALL);
802     for (i = 0; i < dcc_total; i++) {
803     if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) {
804     if (dcc[i].type == &DCC_FORK_BOT) {
805     if (idx >= 0)
806     dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
807     dcc[i].nick, dcc[i].host);
808     putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
809     BOT_KILLLINKATTEMPT, dcc[i].nick,
810     dcc[i].host, dcc[i].port);
811     killsock(dcc[i].sock);
812     lostdcc(i);
813     if (nick[0] != '*')
814     return 1;
815     } else if (dcc[i].type == &DCC_BOT_NEW) {
816     if (idx >= 0)
817     dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT,
818     dcc[i].nick);
819     putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
820     "Stopped trying to link", dcc[i].nick,
821     dcc[i].host, dcc[i].port);
822     killsock(dcc[i].sock);
823     lostdcc(i);
824     if (nick[0] != '*')
825     return 1;
826     else
827     i--;
828     } else if (dcc[i].type == &DCC_BOT) {
829     char s[1024];
830    
831     context;
832    
833     if (idx >= 0)
834     dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
835     else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
836     return -1;
837     dprintf(i, "bye\n");
838     if (reason && reason[0]) {
839     simple_sprintf(s, "%s %s (%s)", BOT_UNLINKEDFROM,
840     dcc[i].nick, reason);
841     } else {
842     simple_sprintf(s, "%s %s", BOT_UNLINKEDFROM, dcc[i].nick);
843     }
844     chatout("*** %s\n", s);
845     botnet_send_unlinked(i, dcc[i].nick, s);
846     killsock(dcc[i].sock);
847     lostdcc(i);
848     if (nick[0] != '*')
849     return 1;
850     else
851     i--;
852     }
853     }
854     }
855     context;
856     if ((idx >= 0) && (nick[0] != '*'))
857     dprintf(idx, "%s\n", BOT_NOTCONNECTED);
858     if (nick[0] == '*') {
859     dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
860     while (tandbot)
861     rembot(tandbot->bot);
862     while (parties) {
863     parties--;
864     check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
865     party[i].chan);
866     }
867     strcpy(s, "killassoc &");
868     Tcl_Eval(interp, s);
869     }
870     return 0;
871     }
872    
873     /* link to another bot */
874     int botlink(char *linker, int idx, char *nick)
875     {
876     struct bot_addr *bi;
877     struct userrec *u;
878     int i;
879    
880     context;
881     u = get_user_by_handle(userlist, nick);
882     if (!u || !(u->flags & USER_BOT)) {
883     if (idx >= 0)
884     dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
885     } else if (!strcasecmp(nick, botnetnick)) {
886     if (idx >= 0)
887     dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
888     } else if (in_chain(nick) && (idx != -3)) {
889     if (idx >= 0)
890     dprintf(idx, "%s\n", BOT_ALREADYLINKED);
891     } else {
892     for (i = 0; i < dcc_total; i++)
893     if ((dcc[i].user == u) &&
894     ((dcc[i].type == &DCC_FORK_BOT) ||
895     (dcc[i].type == &DCC_BOT_NEW))) {
896     if (idx >= 0)
897     dprintf(idx, "%s\n", BOT_ALREADYLINKING);
898     return 0;
899     }
900     /* address to connect to is in 'info' */
901     bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
902 guppy 1.2 if (!bi || !strlen(bi->address) || !bi->telnet_port) {
903 segfault 1.1 if (idx >= 0) {
904     dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
905     dprintf(idx, "%s .chaddr %s %s\n",
906     MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
907     }
908     } else if (dcc_total == max_dcc) {
909     if (idx >= 0)
910     dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
911     } else {
912     context;
913     correct_handle(nick);
914     i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));
915    
916     dcc[i].port = bi->telnet_port;
917     strcpy(dcc[i].nick, nick);
918     strcpy(dcc[i].host, bi->address);
919     dcc[i].timeval = now;
920     strcpy(dcc[i].u.bot->linker, linker);
921     strcpy(dcc[i].u.bot->version, "(primitive bot)");
922     if (idx > -2)
923     putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
924     bi->address, bi->telnet_port);
925     dcc[i].u.bot->numver = idx;
926     dcc[i].timeval = now;
927     dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
928     dcc[i].sock = getsock(SOCK_STRONGCONN);
929     dcc[i].user = u;
930     if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) >= 0)
931     return 1;
932     failed_link(i);
933     }
934     }
935     return 0;
936     }
937    
938     static void failed_tandem_relay(int idx)
939     {
940     int uidx = (-1), i;
941    
942     context;
943     for (i = 0; i < dcc_total; i++)
944     if ((dcc[i].type == &DCC_PRE_RELAY) &&
945     (dcc[i].u.relay->sock == dcc[idx].sock))
946     uidx = i;
947     if (uidx < 0) {
948     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
949     dcc[idx].sock, dcc[idx].u.relay->sock);
950     killsock(dcc[idx].sock);
951     lostdcc(idx);
952     return;
953     }
954     if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
955     struct chat_info *ci = dcc[uidx].u.relay->chat;
956    
957     dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
958     nfree(dcc[uidx].u.relay);
959     dcc[uidx].u.chat = ci;
960     dcc[uidx].type = &DCC_CHAT;
961     dcc[uidx].status = dcc[uidx].u.relay->old_status;
962     killsock(dcc[idx].sock);
963     lostdcc(idx);
964     return;
965     }
966     killsock(dcc[idx].sock);
967     dcc[idx].sock = getsock(SOCK_STRONGCONN);
968     dcc[uidx].u.relay->sock = dcc[idx].sock;
969     dcc[idx].port++;
970     dcc[idx].timeval = now;
971     if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0)
972     failed_tandem_relay(idx);
973     }
974    
975     /* relay to another tandembot */
976     void tandem_relay(int idx, char *nick, int i)
977     {
978     struct chat_info *ci;
979     struct userrec *u;
980     struct bot_addr *bi;
981    
982     context;
983     u = get_user_by_handle(userlist, nick);
984     if (!u || !(u->flags & USER_BOT)) {
985     dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
986     return;
987     }
988     if (!strcasecmp(nick, botnetnick)) {
989     dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
990     return;
991     }
992     /* address to connect to is in 'info' */
993     bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
994     if (!bi) {
995     dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
996     dprintf(idx, "%s .chaddr %s %s\n",
997     MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
998    
999     return;
1000     }
1001     if (dcc_total == max_dcc) {
1002     dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
1003     return;
1004     }
1005     i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
1006     dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
1007    
1008     dcc[i].port = bi->relay_port;
1009     dcc[i].u.relay->port = dcc[i].port;
1010     dcc[i].addr = 0L;
1011     strcpy(dcc[i].nick, nick);
1012     dcc[i].user = u;
1013     strcpy(dcc[i].host, bi->address);
1014     dcc[i].u.relay->chat->away = NULL;
1015     dcc[i].u.relay->old_status = dcc[i].status;
1016     dcc[i].status = 0;
1017     dcc[i].timeval = now;
1018     dcc[i].u.relay->chat->msgs_per_sec = 0;
1019     dcc[i].u.relay->chat->con_flags = 0;
1020     dcc[i].u.relay->chat->buffer = NULL;
1021     dcc[i].u.relay->chat->max_line = 0;
1022     dcc[i].u.relay->chat->line_count = 0;
1023     dcc[i].u.relay->chat->current_lines = 0;
1024     dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
1025     bi->address, bi->relay_port);
1026     dprintf(idx, "%s\n", BOT_BYEINFO1);
1027     ci = dcc[idx].u.chat;
1028     dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
1029    
1030     dcc[idx].u.relay->chat = ci;
1031     dcc[idx].type = &DCC_PRE_RELAY;
1032     dcc[i].sock = getsock(SOCK_STRONGCONN);
1033     dcc[idx].u.relay->sock = dcc[i].sock;
1034     dcc[i].u.relay->sock = dcc[idx].sock;
1035     dcc[i].timeval = now;
1036     if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
1037     failed_tandem_relay(i);
1038     }
1039    
1040     /* input from user before connect is ready */
1041     static void pre_relay(int idx, char *buf, int i)
1042     {
1043     int tidx = (-1);
1044    
1045     context;
1046     for (i = 0; i < dcc_total; i++)
1047     if ((dcc[i].type == &DCC_FORK_RELAY) &&
1048     (dcc[i].u.relay->sock == dcc[idx].sock))
1049     tidx = i;
1050     if (tidx < 0) {
1051     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1052     dcc[i].sock, dcc[i].u.relay->sock);
1053     killsock(dcc[i].sock);
1054     lostdcc(i);
1055     return;
1056     }
1057     context;
1058     if (!strcasecmp(buf, "*bye*")) {
1059     /* disconnect */
1060     struct chat_info *ci = dcc[idx].u.relay->chat;
1061    
1062     dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
1063     dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1064     putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
1065     dcc[tidx].nick);
1066     nfree(dcc[idx].u.relay);
1067     dcc[idx].u.chat = ci;
1068     dcc[idx].status = dcc[idx].u.relay->old_status;
1069     dcc[idx].type = &DCC_CHAT;
1070     killsock(dcc[tidx].sock);
1071     lostdcc(tidx);
1072     return;
1073     }
1074     context;
1075     }
1076    
1077     /* user disconnected before her relay had finished connecting */
1078     static void failed_pre_relay(int idx)
1079     {
1080     int tidx = (-1), i;
1081    
1082     context;
1083     for (i = 0; i < dcc_total; i++)
1084     if ((dcc[i].type == &DCC_FORK_RELAY) &&
1085     (dcc[i].u.relay->sock == dcc[idx].sock))
1086     tidx = i;
1087     if (tidx < 0) {
1088     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1089     dcc[i].sock, dcc[i].u.relay->sock);
1090     killsock(dcc[i].sock);
1091     lostdcc(i);
1092     return;
1093     }
1094     putlog(LOG_MISC, "*", "%s [%s]%s/%d",
1095     BOT_LOSTDCCUSER, dcc[idx].nick,
1096     dcc[idx].host, dcc[idx].port);
1097     putlog(LOG_MISC, "*", "(%s %s)",
1098     BOT_DROPPINGRELAY, dcc[tidx].nick);
1099     if ((dcc[tidx].sock != STDOUT) || backgrd) {
1100     if (idx > tidx) {
1101     int t = tidx;
1102    
1103     tidx = idx;
1104     idx = t;
1105     }
1106     killsock(dcc[tidx].sock);
1107     lostdcc(tidx);
1108     } else {
1109     fatal("Lost my terminal??!?!?!", 0);
1110     }
1111     killsock(dcc[idx].sock);
1112     lostdcc(idx);
1113     }
1114    
1115     static void cont_tandem_relay(int idx, char *buf, int i)
1116     {
1117     int uidx = (-1);
1118     struct relay_info *ri;
1119    
1120     context;
1121     for (i = 0; i < dcc_total; i++)
1122     if ((dcc[i].type == &DCC_PRE_RELAY) &&
1123     (dcc[i].u.relay->sock == dcc[idx].sock))
1124     uidx = i;
1125     if (uidx < 0) {
1126     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1127     dcc[i].sock, dcc[i].u.relay->sock);
1128     killsock(dcc[i].sock);
1129     lostdcc(i);
1130     return;
1131     }
1132     dcc[idx].type = &DCC_RELAY;
1133     dcc[idx].u.relay->sock = dcc[uidx].sock;
1134     dcc[uidx].u.relay->sock = dcc[idx].sock;
1135     dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
1136     dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
1137     putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
1138     dcc[uidx].nick, dcc[idx].nick);
1139     ri = dcc[uidx].u.relay; /* YEAH */
1140     dcc[uidx].type = &DCC_CHAT;
1141     dcc[uidx].u.chat = ri->chat;
1142     if (dcc[uidx].u.chat->channel >= 0) {
1143     chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
1144     dcc[uidx].nick, BOT_PARTYLEFT);
1145     if (dcc[uidx].u.chat->channel < 100000)
1146     botnet_send_part_idx(uidx, NULL);
1147     check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
1148     dcc[uidx].u.chat->channel);
1149     }
1150     check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
1151     dcc[uidx].type = &DCC_RELAYING;
1152     dcc[uidx].u.relay = ri;
1153     }
1154    
1155     static void eof_dcc_relay(int idx)
1156     {
1157     int j;
1158     struct chat_info *ci;
1159    
1160     for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++);
1161     /* in case echo was off, turn it back on: */
1162     if (dcc[j].status & STAT_TELNET)
1163     dprintf(j, "\377\374\001\r\n");
1164     putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
1165     dcc[idx].nick);
1166     dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick);
1167     ci = dcc[j].u.relay->chat;
1168     nfree(dcc[j].u.relay);
1169     dcc[j].u.chat = ci;
1170     dcc[j].type = &DCC_CHAT;
1171     if (dcc[j].u.chat->channel >= 0) {
1172     chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
1173     dcc[j].nick, BOT_PARTYREJOINED);
1174     context;
1175     if (dcc[j].u.chat->channel < 100000)
1176     botnet_send_join_idx(j, -1);
1177     }
1178     dcc[j].status = dcc[j].u.relay->old_status;
1179     check_tcl_chon(dcc[j].nick, dcc[j].sock);
1180     check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
1181     geticon(j), dcc[j].sock, dcc[j].host);
1182     killsock(dcc[idx].sock);
1183     lostdcc(idx);
1184     }
1185    
1186     static void eof_dcc_relaying(int idx)
1187     {
1188     int j, x = dcc[idx].u.relay->sock;
1189    
1190     putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1191     dcc[idx].host, dcc[idx].port);
1192     killsock(dcc[idx].sock);
1193     lostdcc(idx);
1194     for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY) ||
1195     (dcc[j].type == &DCC_LOST); j++);
1196     putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
1197     killsock(dcc[j].sock);
1198     lostdcc(j); /* drop connection to the bot */
1199     }
1200    
1201     static void dcc_relay(int idx, char *buf, int j)
1202     {
1203     unsigned char *p = (unsigned char *) buf;
1204     int mark;
1205    
1206     for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1207     (dcc[j].type != &DCC_RELAYING); j++);
1208     /* if redirecting to a non-telnet user, swallow telnet codes */
1209     if (!(dcc[j].status & STAT_TELNET)) {
1210     while (*p != 0) {
1211     while ((*p != 255) && (*p != 0))
1212     p++; /* search for IAC */
1213     if (*p == 255) {
1214     mark = 2;
1215     if (!*(p + 1))
1216     mark = 1; /* bogus */
1217     if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
1218     mark = 3;
1219     if (!*(p + 2))
1220     mark = 2; /* bogus */
1221     }
1222     strcpy((char *) p, (char *) (p + mark));
1223     }
1224     }
1225     if (!buf[0])
1226     dprintf(-dcc[idx].u.relay->sock, " \n");
1227     else
1228     dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1229     return;
1230     }
1231     /* telnet user */
1232     if (!buf[0])
1233     dprintf(-dcc[idx].u.relay->sock, " \r\n");
1234     else
1235     dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
1236     }
1237    
1238     static void dcc_relaying(int idx, char *buf, int j)
1239     {
1240     struct chat_info *ci;
1241    
1242     if (strcasecmp(buf, "*bye*")) {
1243     dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1244     return;
1245     }
1246     for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1247     (dcc[j].type != &DCC_RELAY); j++);
1248     /* in case echo was off, turn it back on: */
1249     if (dcc[idx].status & STAT_TELNET)
1250     dprintf(idx, "\377\374\001\r\n");
1251     dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
1252     dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1253     putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
1254     dcc[idx].nick, dcc[j].nick);
1255     if (dcc[idx].u.relay->chat->channel >= 0) {
1256     chanout_but(-1, dcc[idx].u.relay->chat->channel,
1257     "*** %s joined the party line.\n", dcc[idx].nick);
1258     context;
1259     if (dcc[idx].u.relay->chat->channel < 100000)
1260     botnet_send_join_idx(idx, -1);
1261     }
1262     ci = dcc[idx].u.relay->chat;
1263     nfree(dcc[idx].u.relay);
1264     dcc[idx].u.chat = ci;
1265     dcc[idx].type = &DCC_CHAT;
1266     dcc[idx].status = dcc[idx].u.relay->old_status;
1267     check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1268     if (dcc[idx].u.chat->channel >= 0)
1269     check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1270     geticon(idx), dcc[idx].sock, dcc[idx].host);
1271     killsock(dcc[j].sock);
1272     lostdcc(j);
1273     }
1274    
1275     static void display_relay(int i, char *other)
1276     {
1277     sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
1278     }
1279    
1280     static void display_relaying(int i, char *other)
1281     {
1282     sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
1283     }
1284    
1285     static void display_tandem_relay(int i, char *other)
1286     {
1287     strcpy(other, "other rela");
1288     }
1289    
1290     static void display_pre_relay(int i, char *other)
1291     {
1292     strcpy(other, "other >rly");
1293     }
1294    
1295     static int expmem_relay(void *x)
1296     {
1297     register struct relay_info *p = (struct relay_info *) x;
1298     int tot = sizeof(struct relay_info);
1299    
1300     if (p->chat)
1301     tot += DCC_CHAT.expmem(p->chat);
1302     return tot;
1303     }
1304    
1305     static void kill_relay(int idx, void *x)
1306     {
1307     register struct relay_info *p = (struct relay_info *) x;
1308    
1309     if (p->chat)
1310     DCC_CHAT.kill(idx, p->chat);
1311     nfree(p);
1312     }
1313    
1314     struct dcc_table DCC_RELAY =
1315     {
1316     "RELAY",
1317     0, /* flags */
1318     eof_dcc_relay,
1319     dcc_relay,
1320     0,
1321     0,
1322     display_relay,
1323     expmem_relay,
1324     kill_relay,
1325     0
1326     };
1327    
1328     static void out_relay(int idx, char *buf, void *x)
1329     {
1330     register struct relay_info *p = (struct relay_info *) x;
1331    
1332     if (p && p->chat)
1333     DCC_CHAT.output(idx, buf, p->chat);
1334     else
1335     tputs(dcc[idx].sock, buf, strlen(buf));
1336     }
1337    
1338     struct dcc_table DCC_RELAYING =
1339     {
1340     "RELAYING",
1341     0, /* flags */
1342     eof_dcc_relaying,
1343     dcc_relaying,
1344     0,
1345     0,
1346     display_relaying,
1347     expmem_relay,
1348     kill_relay,
1349     out_relay
1350     };
1351    
1352     struct dcc_table DCC_FORK_RELAY =
1353     {
1354     "FORK_RELAY",
1355     0, /* flags */
1356     failed_tandem_relay,
1357     cont_tandem_relay,
1358     &connect_timeout,
1359     failed_tandem_relay,
1360     display_tandem_relay,
1361     expmem_relay,
1362     kill_relay,
1363     0
1364     };
1365    
1366     struct dcc_table DCC_PRE_RELAY =
1367     {
1368     "PRE_RELAY",
1369     0, /* flags */
1370     failed_pre_relay,
1371     pre_relay,
1372     0,
1373     0,
1374     display_pre_relay,
1375     expmem_relay,
1376     kill_relay,
1377     0
1378     };
1379    
1380     /* once a minute, send 'ping' to each bot -- no exceptions */
1381     void check_botnet_pings()
1382     {
1383     int i;
1384    
1385     context;
1386     for (i = 0; i < dcc_total; i++)
1387     if (dcc[i].type == &DCC_BOT)
1388     if (dcc[i].status & STAT_PINGED) {
1389     char s[1024];
1390    
1391     putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1392     simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1393     chatout("*** %s\n", s);
1394     botnet_send_unlinked(i, dcc[i].nick, s);
1395     killsock(dcc[i].sock);
1396     lostdcc(i);
1397     }
1398     context;
1399     for (i = 0; i < dcc_total; i++)
1400     if (dcc[i].type == &DCC_BOT) {
1401     botnet_send_ping(i);
1402     dcc[i].status |= STAT_PINGED;
1403     }
1404     context;
1405     for (i = 0; i < dcc_total; i++)
1406     if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
1407     tand_t *bot, *via = findbot(dcc[i].nick);
1408    
1409     for (bot = tandbot; bot; bot = bot->next) {
1410     if ((via == bot->via) && (bot != via)) {
1411     /* not leaflike behavior */
1412     if (dcc[i].status & STAT_WARNED) {
1413     char s[1024];
1414    
1415     putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
1416     dcc[i].nick, BOT_BOTNOTLEAFLIKE);
1417     dprintf(i, "bye\n");
1418     simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick,
1419     BOT_BOTNOTLEAFLIKE);
1420     chatout("*** %s\n", s);
1421     botnet_send_unlinked(i, dcc[i].nick, s);
1422     killsock(dcc[i].sock);
1423     lostdcc(i);
1424     } else {
1425     botnet_send_reject(i, botnetnick, NULL, bot->bot,
1426     NULL, NULL);
1427     dcc[i].status |= STAT_WARNED;
1428     }
1429     } else
1430     dcc[i].status &= ~STAT_WARNED;
1431     }
1432     }
1433     context;
1434     }
1435    
1436     void zapfbot(int idx)
1437     {
1438     char s[1024];
1439    
1440     simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick);
1441     chatout("*** %s\n", s);
1442     botnet_send_unlinked(idx, dcc[idx].nick, s);
1443     killsock(dcc[idx].sock);
1444     dcc[idx].sock = (long) dcc[idx].type;
1445     dcc[idx].type = &DCC_LOST;
1446     }
1447    
1448     void restart_chons()
1449     {
1450     int i;
1451    
1452     /* dump party line members */
1453     context;
1454     for (i = 0; i < dcc_total; i++) {
1455     if (dcc[i].type == &DCC_CHAT) {
1456     check_tcl_chon(dcc[i].nick, dcc[i].sock);
1457     check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
1458     geticon(i), dcc[i].sock, dcc[i].host);
1459     }
1460     }
1461     for (i = 0; i < parties; i++) {
1462     check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
1463     party[i].flag, party[i].sock, party[i].from);
1464     }
1465     context;
1466     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23