/[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.3 - (hide annotations) (download) (as text)
Wed Oct 20 01:00:03 1999 UTC (19 years, 11 months ago) by guppy
Branch: MAIN
Changes since 1.2: +6 -3 lines
File MIME type: text/x-chdr
more patches

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 guppy 1.3 if (party[i].chan >= 0)
343     check_tcl_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
344 segfault 1.1 remparty(bot, party[i].sock);
345     i--;
346     }
347     }
348    
349     /* remove every bot linked 'via' bot <x> */
350     void unvia(int idx, tand_t * who)
351     {
352     tand_t *bot, *bot2;
353    
354     if (!who)
355     return; /* safety */
356     rempartybot(who->bot);
357     bot = tandbot;
358     while (bot) {
359     if (bot->uplink == who) {
360     unvia(idx, bot);
361     bot2 = bot->next;
362     rembot(bot->bot);
363     bot = bot2;
364     } else
365     bot = bot->next;
366     }
367     #ifndef NO_OLD_BOTNET
368     /* every bot unvia's bots behind anyway, so why send msg's for
369     * EVERY one? - will this break things?! */
370     tandout_but(idx, "unlinked %s\n", who->bot);
371     #endif
372     }
373    
374     /* return index into dcc list of the bot that connects us to bot <x> */
375     int nextbot(char *who)
376     {
377     int j;
378     tand_t *bot = findbot(who);
379    
380     if (!bot)
381     return -1;
382    
383     for (j = 0; j < dcc_total; j++)
384     if (bot->via && !strcasecmp(bot->via->bot, dcc[j].nick) &&
385     (dcc[j].type == &DCC_BOT))
386     return j;
387     return -1; /* we're not connected to 'via' */
388     }
389    
390     /* return name of the bot that is directly connected to bot X */
391     char *lastbot(char *who)
392     {
393     tand_t *bot = findbot(who);
394    
395     if (!bot)
396     return "*";
397     else if (bot->uplink == (tand_t *) 1)
398     return botnetnick;
399     else
400     return bot->uplink->bot;
401     }
402    
403     /* modern version of 'whom' (use local data) */
404     void answer_local_whom(int idx, int chan)
405     {
406     char c, idle[40], spaces2[33] = " ";
407     int i, len, len2;
408    
409     context;
410     if (chan == (-1))
411     dprintf(idx, "%s (+: %s, *: %s)\n", BOT_BOTNETUSERS, BOT_PARTYLINE,
412     BOT_LOCALCHAN);
413     else if (chan > 0) {
414     simple_sprintf(idle, "assoc %d", chan);
415     if ((Tcl_Eval(interp, idle) != TCL_OK) || !interp->result[0])
416     dprintf(idx, "%s %s%d:\n", BOT_USERSONCHAN,
417     (chan < 100000) ? "" : "*", chan % 100000);
418     else
419     dprintf(idx, "%s '%s%s' (%s%d):\n", BOT_USERSONCHAN,
420     (chan < 100000) ? "" : "*", interp->result,
421     (chan < 100000) ? "" : "*", chan % 100000);
422     }
423     spaces[HANDLEN - 9] = 0;
424     dprintf(idx, " Nick %s Bot %s Host\n", spaces, spaces);
425     dprintf(idx, "----------%s ---------%s --------------------\n",
426     spaces, spaces);
427     spaces[HANDLEN - 9] = ' ';
428     for (i = 0; i < dcc_total; i++)
429     if (dcc[i].type == &DCC_CHAT) {
430     if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
431     c = geticon(i);
432     if (c == '-')
433     c = ' ';
434     if (now - dcc[i].timeval > 300) {
435     unsigned long days, hrs, mins;
436    
437     days = (now - dcc[i].timeval) / 86400;
438     hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
439     mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
440     if (days > 0)
441     sprintf(idle, " [idle %lud%luh]", days, hrs);
442     else if (hrs > 0)
443     sprintf(idle, " [idle %luh%lum]", hrs, mins);
444     else
445     sprintf(idle, " [idle %lum]", mins);
446     } else
447     idle[0] = 0;
448     spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
449     spaces2[len2 = HANDLEN - strlen(botnetnick)] = 0;
450     dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, dcc[i].nick, spaces,
451     (dcc[i].u.chat->channel == 0) && (chan == (-1)) ? '+' :
452     (dcc[i].u.chat->channel > 100000) &&
453     (chan == (-1)) ? '*' : ' ',
454     botnetnick, spaces2, dcc[i].host, idle);
455     spaces[len] = ' ';
456     spaces2[len2] = ' ';
457     if (dcc[i].u.chat->away != NULL)
458     dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
459     }
460     }
461     for (i = 0; i < parties; i++) {
462     if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
463     c = party[i].flag;
464     if (c == '-')
465     c = ' ';
466     if (party[i].timer == 0L)
467     strcpy(idle, " [idle?]");
468     else if (now - party[i].timer > 300) {
469     unsigned long days, hrs, mins;
470    
471     days = (now - party[i].timer) / 86400;
472     hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
473     mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
474     if (days > 0)
475     sprintf(idle, " [idle %lud%luh]", days, hrs);
476     else if (hrs > 0)
477     sprintf(idle, " [idle %luh%lum]", hrs, mins);
478     else
479     sprintf(idle, " [idle %lum]", mins);
480     } else
481     idle[0] = 0;
482     spaces[len = HANDLEN - strlen(party[i].nick)] = 0;
483     spaces2[len2 = HANDLEN - strlen(party[i].bot)] = 0;
484     dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, party[i].nick, spaces,
485     (party[i].chan == 0) && (chan == (-1)) ? '+' : ' ',
486     party[i].bot, spaces2, party[i].from, idle);
487     spaces[len] = ' ';
488     spaces2[len2] = ' ';
489     if (party[i].status & PLSTAT_AWAY)
490     dprintf(idx, " %s: %s\n", MISC_AWAY, safe_str(party[i].away));
491     }
492     }
493     }
494    
495     /* show z a list of all bots connected */
496     void tell_bots(int idx)
497     {
498     char s[512];
499     int i;
500     tand_t *bot;
501    
502     if (!tands) {
503     dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
504     return;
505     }
506     strcpy(s, botnetnick);
507     i = strlen(botnetnick);
508    
509     for (bot = tandbot; bot; bot = bot->next) {
510     if (i > (500 - HANDLEN)) {
511     dprintf(idx, "Bots: %s\n", s);
512     s[0] = 0;
513     i = 0;
514     }
515     if (i) {
516     s[i++] = ',';
517     s[i++] = ' ';
518     }
519     strcpy(s + i, bot->bot);
520     i += strlen(bot->bot);
521     }
522     if (s[0])
523     dprintf(idx, "Bots: %s\n", s);
524     dprintf(idx, "(%s: %d)\n", MISC_TOTAL, tands + 1);
525     }
526    
527     /* show a simpleton bot tree */
528     void tell_bottree(int idx, int showver)
529     {
530     char s[161];
531     tand_t *last[20], *this, *bot, *bot2 = NULL;
532     int lev = 0, more = 1, mark[20], ok, cnt, i, imark;
533     char work[1024];
534     int tothops = 0;
535    
536     if (tands == 0) {
537     dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
538     return;
539     }
540     s[0] = 0;
541     i = 0;
542    
543     for (bot = tandbot; bot; bot = bot->next)
544     if (!bot->uplink) {
545     if (i) {
546     s[i++] = ',';
547     s[i++] = ' ';
548     }
549     strcpy(s + i, bot->bot);
550     i += strlen(bot->bot);
551     }
552     if (s[0])
553     dprintf(idx, "(%s %s)\n", BOT_NOTRACEINFO, s);
554     if (showver)
555     dprintf(idx, "%s (%d.%d.%d.%d)\n", botnetnick,
556     egg_numver / 1000000,
557     egg_numver % 1000000 / 10000,
558     egg_numver % 10000 / 100,
559     egg_numver % 100);
560     else
561     dprintf(idx, "%s\n", botnetnick);
562     this = (tand_t *) 1;
563     work[0] = 0;
564     while (more) {
565     if (lev == 20) {
566     dprintf(idx, "\n%s\n", BOT_COMPLEXTREE);
567     return;
568     }
569     cnt = 0;
570     tothops += lev;
571     for (bot = tandbot; bot; bot = bot->next)
572     if (bot->uplink == this)
573     cnt++;
574     if (cnt) {
575     imark = 0;
576     for (i = 0; i < lev; i++) {
577     if (mark[i])
578     strcpy(work + imark, " | ");
579     else
580     strcpy(work + imark, " ");
581     imark += 5;
582     }
583     if (cnt > 1)
584     strcpy(work + imark, " |-");
585     else
586     strcpy(work + imark, " `-");
587     s[0] = 0;
588     bot = tandbot;
589     while (!s[0]) {
590     if (bot->uplink == this) {
591     if (bot->ver) {
592     i = sprintf(s, "%c%s", bot->share, bot->bot);
593     if (showver)
594     sprintf(s + i, " (%d.%d.%d.%d)",
595     bot->ver / 1000000,
596     bot->ver % 1000000 / 10000,
597     bot->ver % 10000 / 100,
598     bot->ver % 100);
599     } else {
600     sprintf(s, "-%s", bot->bot);
601     }
602     } else
603     bot = bot->next;
604     }
605     dprintf(idx, "%s%s\n", work, s);
606     if (cnt > 1)
607     mark[lev] = 1;
608     else
609     mark[lev] = 0;
610     work[0] = 0;
611     last[lev] = this;
612     this = bot;
613     lev++;
614     more = 1;
615     } else {
616     while (cnt == 0) {
617     /* no subtrees from here */
618     if (lev == 0) {
619     dprintf(idx, "(( tree error ))\n");
620     return;
621     }
622     ok = 0;
623     for (bot = tandbot; bot; bot = bot->next) {
624     if (bot->uplink == last[lev - 1]) {
625     if (this == bot)
626     ok = 1;
627     else if (ok) {
628     cnt++;
629     if (cnt == 1) {
630     bot2 = bot;
631     if (bot->ver) {
632     i = sprintf(s, "%c%s", bot->share, bot->bot);
633     if (showver)
634     sprintf(s + i, " (%d.%d.%d.%d)",
635     bot->ver / 1000000,
636     bot->ver % 1000000 / 10000,
637     bot->ver % 10000 / 100,
638     bot->ver % 100);
639     } else {
640     sprintf(s, "-%s", bot->bot);
641     }
642     }
643     }
644     }
645     }
646     if (cnt) {
647     imark = 0;
648     for (i = 1; i < lev; i++) {
649     if (mark[i - 1])
650     strcpy(work + imark, " | ");
651     else
652     strcpy(work + imark, " ");
653     imark += 5;
654     }
655     more = 1;
656     if (cnt > 1)
657     dprintf(idx, "%s |-%s\n", work, s);
658     else
659     dprintf(idx, "%s `-%s\n", work, s);
660     this = bot2;
661     work[0] = 0;
662     if (cnt > 1)
663     mark[lev - 1] = 1;
664     else
665     mark[lev - 1] = 0;
666     } else {
667     /* this was the last child */
668     lev--;
669     if (lev == 0) {
670     more = 0;
671     cnt = 999;
672     } else {
673     more = 1;
674     this = last[lev];
675     }
676     }
677     }
678     }
679     }
680     /* hop information: (9d) */
681     dprintf(idx, "Average hops: %3.1f, total bots: %d\n",
682     ((float) tothops) / ((float) tands), tands + 1);
683     }
684    
685     /* dump list of links to a new bot */
686     void dump_links(int z)
687     {
688     int i, l;
689     char x[1024];
690     tand_t *bot;
691    
692     context;
693     for (bot = tandbot; bot; bot = bot->next) {
694     char *p;
695    
696     if (bot->uplink == (tand_t *) 1)
697     p = botnetnick;
698     else
699     p = bot->uplink->bot;
700     #ifndef NO_OLD_BOTNET
701     if (b_numver(z) < NEAT_BOTNET)
702     l = simple_sprintf(x, "nlinked %s %s %c%d\n", bot->bot,
703     p, bot->share, bot->ver);
704     else
705     #endif
706     l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p,
707     bot->share, bot->ver);
708     tputs(dcc[z].sock, x, l);
709     }
710     context;
711     if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
712     /* dump party line members */
713     for (i = 0; i < dcc_total; i++) {
714     if (dcc[i].type == &DCC_CHAT) {
715     if ((dcc[i].u.chat->channel >= 0) &&
716     (dcc[i].u.chat->channel < 100000)) {
717     #ifndef NO_OLD_BOTNET
718     if (b_numver(z) < NEAT_BOTNET)
719     l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
720     botnetnick, dcc[i].nick,
721     dcc[i].u.chat->channel, geticon(i),
722     dcc[i].sock, dcc[i].host);
723     else
724     #endif
725     l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
726     botnetnick, dcc[i].nick,
727     dcc[i].u.chat->channel, geticon(i),
728     dcc[i].sock, dcc[i].host);
729     tputs(dcc[z].sock, x, l);
730     #ifndef NO_OLD_BOTNET
731     if (b_numver(z) < NEAT_BOTNET) {
732     if (dcc[i].u.chat->away) {
733     l = simple_sprintf(x, "away %s %d %s\n", botnetnick,
734     dcc[i].sock, dcc[i].u.chat->away);
735     tputs(dcc[z].sock, x, l);
736     }
737     l = simple_sprintf(x, "idle %s %d %d\n", botnetnick,
738     dcc[i].sock, now - dcc[i].timeval);
739     } else
740     #endif
741     l = simple_sprintf(x, "i %s %D %D %s\n", botnetnick,
742     dcc[i].sock, now - dcc[i].timeval,
743     dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
744     tputs(dcc[z].sock, x, l);
745     }
746     }
747     }
748     context;
749     for (i = 0; i < parties; i++) {
750     #ifndef NO_OLD_BOTNET
751     if (b_numver(z) < NEAT_BOTNET)
752     l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
753     party[i].bot, party[i].nick,
754     party[i].chan, party[i].flag,
755     party[i].sock, party[i].from);
756     else
757     #endif
758     l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
759     party[i].bot, party[i].nick,
760     party[i].chan, party[i].flag,
761     party[i].sock, party[i].from);
762     tputs(dcc[z].sock, x, l);
763     if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
764     #ifndef NO_OLD_BOTNET
765     if (b_numver(z) < NEAT_BOTNET) {
766     if (party[i].status & PLSTAT_AWAY) {
767     l = simple_sprintf(x, "away %s %d %s\n", party[i].bot,
768     party[i].sock, party[i].away);
769     tputs(dcc[z].sock, x, l);
770     }
771     l = simple_sprintf(x, "idle %s %d %d\n", party[i].bot,
772     party[i].sock, now - party[i].timer);
773     } else
774     #endif
775     l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
776     party[i].sock, now - party[i].timer,
777     party[i].away ? party[i].away : "");
778     tputs(dcc[z].sock, x, l);
779     }
780     }
781     }
782     context;
783     }
784    
785     int in_chain(char *who)
786     {
787     if (findbot(who))
788     return 1;
789     if (!strcasecmp(who, botnetnick))
790     return 1;
791     return 0;
792     }
793    
794     /* break link with a tandembot */
795     int botunlink(int idx, char *nick, char *reason)
796     {
797     char s[20];
798     int i;
799    
800     context;
801     if (nick[0] == '*')
802     dprintf(idx, "%s\n", BOT_UNLINKALL);
803     for (i = 0; i < dcc_total; i++) {
804     if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) {
805     if (dcc[i].type == &DCC_FORK_BOT) {
806     if (idx >= 0)
807     dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
808     dcc[i].nick, dcc[i].host);
809     putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
810     BOT_KILLLINKATTEMPT, dcc[i].nick,
811     dcc[i].host, dcc[i].port);
812     killsock(dcc[i].sock);
813     lostdcc(i);
814     if (nick[0] != '*')
815     return 1;
816     } else if (dcc[i].type == &DCC_BOT_NEW) {
817     if (idx >= 0)
818     dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT,
819     dcc[i].nick);
820     putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
821     "Stopped trying to link", dcc[i].nick,
822     dcc[i].host, dcc[i].port);
823     killsock(dcc[i].sock);
824     lostdcc(i);
825     if (nick[0] != '*')
826     return 1;
827     else
828     i--;
829     } else if (dcc[i].type == &DCC_BOT) {
830     char s[1024];
831    
832     context;
833    
834     if (idx >= 0)
835     dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
836     else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
837     return -1;
838     dprintf(i, "bye\n");
839     if (reason && reason[0]) {
840     simple_sprintf(s, "%s %s (%s)", BOT_UNLINKEDFROM,
841     dcc[i].nick, reason);
842     } else {
843     simple_sprintf(s, "%s %s", BOT_UNLINKEDFROM, dcc[i].nick);
844     }
845     chatout("*** %s\n", s);
846     botnet_send_unlinked(i, dcc[i].nick, s);
847     killsock(dcc[i].sock);
848     lostdcc(i);
849     if (nick[0] != '*')
850     return 1;
851     else
852     i--;
853     }
854     }
855     }
856     context;
857     if ((idx >= 0) && (nick[0] != '*'))
858     dprintf(idx, "%s\n", BOT_NOTCONNECTED);
859     if (nick[0] == '*') {
860     dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
861     while (tandbot)
862     rembot(tandbot->bot);
863     while (parties) {
864     parties--;
865 guppy 1.3 /* ASSERT? */
866     if (party[i].chan >= 0)
867     check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
868     party[i].chan);
869 segfault 1.1 }
870     strcpy(s, "killassoc &");
871     Tcl_Eval(interp, s);
872     }
873     return 0;
874     }
875    
876     /* link to another bot */
877     int botlink(char *linker, int idx, char *nick)
878     {
879     struct bot_addr *bi;
880     struct userrec *u;
881     int i;
882    
883     context;
884     u = get_user_by_handle(userlist, nick);
885     if (!u || !(u->flags & USER_BOT)) {
886     if (idx >= 0)
887     dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
888     } else if (!strcasecmp(nick, botnetnick)) {
889     if (idx >= 0)
890     dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
891     } else if (in_chain(nick) && (idx != -3)) {
892     if (idx >= 0)
893     dprintf(idx, "%s\n", BOT_ALREADYLINKED);
894     } else {
895     for (i = 0; i < dcc_total; i++)
896     if ((dcc[i].user == u) &&
897     ((dcc[i].type == &DCC_FORK_BOT) ||
898     (dcc[i].type == &DCC_BOT_NEW))) {
899     if (idx >= 0)
900     dprintf(idx, "%s\n", BOT_ALREADYLINKING);
901     return 0;
902     }
903     /* address to connect to is in 'info' */
904     bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
905 guppy 1.2 if (!bi || !strlen(bi->address) || !bi->telnet_port) {
906 segfault 1.1 if (idx >= 0) {
907     dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
908     dprintf(idx, "%s .chaddr %s %s\n",
909     MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
910     }
911     } else if (dcc_total == max_dcc) {
912     if (idx >= 0)
913     dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
914     } else {
915     context;
916     correct_handle(nick);
917     i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));
918    
919     dcc[i].port = bi->telnet_port;
920     strcpy(dcc[i].nick, nick);
921     strcpy(dcc[i].host, bi->address);
922     dcc[i].timeval = now;
923     strcpy(dcc[i].u.bot->linker, linker);
924     strcpy(dcc[i].u.bot->version, "(primitive bot)");
925     if (idx > -2)
926     putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
927     bi->address, bi->telnet_port);
928     dcc[i].u.bot->numver = idx;
929     dcc[i].timeval = now;
930     dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
931     dcc[i].sock = getsock(SOCK_STRONGCONN);
932     dcc[i].user = u;
933     if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) >= 0)
934     return 1;
935     failed_link(i);
936     }
937     }
938     return 0;
939     }
940    
941     static void failed_tandem_relay(int idx)
942     {
943     int uidx = (-1), i;
944    
945     context;
946     for (i = 0; i < dcc_total; i++)
947     if ((dcc[i].type == &DCC_PRE_RELAY) &&
948     (dcc[i].u.relay->sock == dcc[idx].sock))
949     uidx = i;
950     if (uidx < 0) {
951     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
952     dcc[idx].sock, dcc[idx].u.relay->sock);
953     killsock(dcc[idx].sock);
954     lostdcc(idx);
955     return;
956     }
957     if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
958     struct chat_info *ci = dcc[uidx].u.relay->chat;
959    
960     dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
961     nfree(dcc[uidx].u.relay);
962     dcc[uidx].u.chat = ci;
963     dcc[uidx].type = &DCC_CHAT;
964     dcc[uidx].status = dcc[uidx].u.relay->old_status;
965     killsock(dcc[idx].sock);
966     lostdcc(idx);
967     return;
968     }
969     killsock(dcc[idx].sock);
970     dcc[idx].sock = getsock(SOCK_STRONGCONN);
971     dcc[uidx].u.relay->sock = dcc[idx].sock;
972     dcc[idx].port++;
973     dcc[idx].timeval = now;
974     if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0)
975     failed_tandem_relay(idx);
976     }
977    
978     /* relay to another tandembot */
979     void tandem_relay(int idx, char *nick, int i)
980     {
981     struct chat_info *ci;
982     struct userrec *u;
983     struct bot_addr *bi;
984    
985     context;
986     u = get_user_by_handle(userlist, nick);
987     if (!u || !(u->flags & USER_BOT)) {
988     dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
989     return;
990     }
991     if (!strcasecmp(nick, botnetnick)) {
992     dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
993     return;
994     }
995     /* address to connect to is in 'info' */
996     bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
997     if (!bi) {
998     dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
999     dprintf(idx, "%s .chaddr %s %s\n",
1000     MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
1001    
1002     return;
1003     }
1004     if (dcc_total == max_dcc) {
1005     dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
1006     return;
1007     }
1008     i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
1009     dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
1010    
1011     dcc[i].port = bi->relay_port;
1012     dcc[i].u.relay->port = dcc[i].port;
1013     dcc[i].addr = 0L;
1014     strcpy(dcc[i].nick, nick);
1015     dcc[i].user = u;
1016     strcpy(dcc[i].host, bi->address);
1017     dcc[i].u.relay->chat->away = NULL;
1018     dcc[i].u.relay->old_status = dcc[i].status;
1019     dcc[i].status = 0;
1020     dcc[i].timeval = now;
1021     dcc[i].u.relay->chat->msgs_per_sec = 0;
1022     dcc[i].u.relay->chat->con_flags = 0;
1023     dcc[i].u.relay->chat->buffer = NULL;
1024     dcc[i].u.relay->chat->max_line = 0;
1025     dcc[i].u.relay->chat->line_count = 0;
1026     dcc[i].u.relay->chat->current_lines = 0;
1027     dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
1028     bi->address, bi->relay_port);
1029     dprintf(idx, "%s\n", BOT_BYEINFO1);
1030     ci = dcc[idx].u.chat;
1031     dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
1032    
1033     dcc[idx].u.relay->chat = ci;
1034     dcc[idx].type = &DCC_PRE_RELAY;
1035     dcc[i].sock = getsock(SOCK_STRONGCONN);
1036     dcc[idx].u.relay->sock = dcc[i].sock;
1037     dcc[i].u.relay->sock = dcc[idx].sock;
1038     dcc[i].timeval = now;
1039     if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
1040     failed_tandem_relay(i);
1041     }
1042    
1043     /* input from user before connect is ready */
1044     static void pre_relay(int idx, char *buf, int i)
1045     {
1046     int tidx = (-1);
1047    
1048     context;
1049     for (i = 0; i < dcc_total; i++)
1050     if ((dcc[i].type == &DCC_FORK_RELAY) &&
1051     (dcc[i].u.relay->sock == dcc[idx].sock))
1052     tidx = i;
1053     if (tidx < 0) {
1054     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1055     dcc[i].sock, dcc[i].u.relay->sock);
1056     killsock(dcc[i].sock);
1057     lostdcc(i);
1058     return;
1059     }
1060     context;
1061     if (!strcasecmp(buf, "*bye*")) {
1062     /* disconnect */
1063     struct chat_info *ci = dcc[idx].u.relay->chat;
1064    
1065     dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
1066     dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1067     putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
1068     dcc[tidx].nick);
1069     nfree(dcc[idx].u.relay);
1070     dcc[idx].u.chat = ci;
1071     dcc[idx].status = dcc[idx].u.relay->old_status;
1072     dcc[idx].type = &DCC_CHAT;
1073     killsock(dcc[tidx].sock);
1074     lostdcc(tidx);
1075     return;
1076     }
1077     context;
1078     }
1079    
1080     /* user disconnected before her relay had finished connecting */
1081     static void failed_pre_relay(int idx)
1082     {
1083     int tidx = (-1), i;
1084    
1085     context;
1086     for (i = 0; i < dcc_total; i++)
1087     if ((dcc[i].type == &DCC_FORK_RELAY) &&
1088     (dcc[i].u.relay->sock == dcc[idx].sock))
1089     tidx = i;
1090     if (tidx < 0) {
1091     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1092     dcc[i].sock, dcc[i].u.relay->sock);
1093     killsock(dcc[i].sock);
1094     lostdcc(i);
1095     return;
1096     }
1097     putlog(LOG_MISC, "*", "%s [%s]%s/%d",
1098     BOT_LOSTDCCUSER, dcc[idx].nick,
1099     dcc[idx].host, dcc[idx].port);
1100     putlog(LOG_MISC, "*", "(%s %s)",
1101     BOT_DROPPINGRELAY, dcc[tidx].nick);
1102     if ((dcc[tidx].sock != STDOUT) || backgrd) {
1103     if (idx > tidx) {
1104     int t = tidx;
1105    
1106     tidx = idx;
1107     idx = t;
1108     }
1109     killsock(dcc[tidx].sock);
1110     lostdcc(tidx);
1111     } else {
1112     fatal("Lost my terminal??!?!?!", 0);
1113     }
1114     killsock(dcc[idx].sock);
1115     lostdcc(idx);
1116     }
1117    
1118     static void cont_tandem_relay(int idx, char *buf, int i)
1119     {
1120     int uidx = (-1);
1121     struct relay_info *ri;
1122    
1123     context;
1124     for (i = 0; i < dcc_total; i++)
1125     if ((dcc[i].type == &DCC_PRE_RELAY) &&
1126     (dcc[i].u.relay->sock == dcc[idx].sock))
1127     uidx = i;
1128     if (uidx < 0) {
1129     putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1130     dcc[i].sock, dcc[i].u.relay->sock);
1131     killsock(dcc[i].sock);
1132     lostdcc(i);
1133     return;
1134     }
1135     dcc[idx].type = &DCC_RELAY;
1136     dcc[idx].u.relay->sock = dcc[uidx].sock;
1137     dcc[uidx].u.relay->sock = dcc[idx].sock;
1138     dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
1139     dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
1140     putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
1141     dcc[uidx].nick, dcc[idx].nick);
1142     ri = dcc[uidx].u.relay; /* YEAH */
1143     dcc[uidx].type = &DCC_CHAT;
1144     dcc[uidx].u.chat = ri->chat;
1145     if (dcc[uidx].u.chat->channel >= 0) {
1146     chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
1147     dcc[uidx].nick, BOT_PARTYLEFT);
1148     if (dcc[uidx].u.chat->channel < 100000)
1149     botnet_send_part_idx(uidx, NULL);
1150     check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
1151     dcc[uidx].u.chat->channel);
1152     }
1153     check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
1154     dcc[uidx].type = &DCC_RELAYING;
1155     dcc[uidx].u.relay = ri;
1156     }
1157    
1158     static void eof_dcc_relay(int idx)
1159     {
1160     int j;
1161     struct chat_info *ci;
1162    
1163     for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++);
1164     /* in case echo was off, turn it back on: */
1165     if (dcc[j].status & STAT_TELNET)
1166     dprintf(j, "\377\374\001\r\n");
1167     putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
1168     dcc[idx].nick);
1169     dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick);
1170     ci = dcc[j].u.relay->chat;
1171     nfree(dcc[j].u.relay);
1172     dcc[j].u.chat = ci;
1173     dcc[j].type = &DCC_CHAT;
1174     if (dcc[j].u.chat->channel >= 0) {
1175     chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
1176     dcc[j].nick, BOT_PARTYREJOINED);
1177     context;
1178     if (dcc[j].u.chat->channel < 100000)
1179     botnet_send_join_idx(j, -1);
1180     }
1181     dcc[j].status = dcc[j].u.relay->old_status;
1182     check_tcl_chon(dcc[j].nick, dcc[j].sock);
1183     check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
1184     geticon(j), dcc[j].sock, dcc[j].host);
1185     killsock(dcc[idx].sock);
1186     lostdcc(idx);
1187     }
1188    
1189     static void eof_dcc_relaying(int idx)
1190     {
1191     int j, x = dcc[idx].u.relay->sock;
1192    
1193     putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1194     dcc[idx].host, dcc[idx].port);
1195     killsock(dcc[idx].sock);
1196     lostdcc(idx);
1197     for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY) ||
1198     (dcc[j].type == &DCC_LOST); j++);
1199     putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
1200     killsock(dcc[j].sock);
1201     lostdcc(j); /* drop connection to the bot */
1202     }
1203    
1204     static void dcc_relay(int idx, char *buf, int j)
1205     {
1206     unsigned char *p = (unsigned char *) buf;
1207     int mark;
1208    
1209     for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1210     (dcc[j].type != &DCC_RELAYING); j++);
1211     /* if redirecting to a non-telnet user, swallow telnet codes */
1212     if (!(dcc[j].status & STAT_TELNET)) {
1213     while (*p != 0) {
1214     while ((*p != 255) && (*p != 0))
1215     p++; /* search for IAC */
1216     if (*p == 255) {
1217     mark = 2;
1218     if (!*(p + 1))
1219     mark = 1; /* bogus */
1220     if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
1221     mark = 3;
1222     if (!*(p + 2))
1223     mark = 2; /* bogus */
1224     }
1225     strcpy((char *) p, (char *) (p + mark));
1226     }
1227     }
1228     if (!buf[0])
1229     dprintf(-dcc[idx].u.relay->sock, " \n");
1230     else
1231     dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1232     return;
1233     }
1234     /* telnet user */
1235     if (!buf[0])
1236     dprintf(-dcc[idx].u.relay->sock, " \r\n");
1237     else
1238     dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
1239     }
1240    
1241     static void dcc_relaying(int idx, char *buf, int j)
1242     {
1243     struct chat_info *ci;
1244    
1245     if (strcasecmp(buf, "*bye*")) {
1246     dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1247     return;
1248     }
1249     for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1250     (dcc[j].type != &DCC_RELAY); j++);
1251     /* in case echo was off, turn it back on: */
1252     if (dcc[idx].status & STAT_TELNET)
1253     dprintf(idx, "\377\374\001\r\n");
1254     dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
1255     dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1256     putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
1257     dcc[idx].nick, dcc[j].nick);
1258     if (dcc[idx].u.relay->chat->channel >= 0) {
1259     chanout_but(-1, dcc[idx].u.relay->chat->channel,
1260     "*** %s joined the party line.\n", dcc[idx].nick);
1261     context;
1262     if (dcc[idx].u.relay->chat->channel < 100000)
1263     botnet_send_join_idx(idx, -1);
1264     }
1265     ci = dcc[idx].u.relay->chat;
1266     nfree(dcc[idx].u.relay);
1267     dcc[idx].u.chat = ci;
1268     dcc[idx].type = &DCC_CHAT;
1269     dcc[idx].status = dcc[idx].u.relay->old_status;
1270     check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1271     if (dcc[idx].u.chat->channel >= 0)
1272     check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1273     geticon(idx), dcc[idx].sock, dcc[idx].host);
1274     killsock(dcc[j].sock);
1275     lostdcc(j);
1276     }
1277    
1278     static void display_relay(int i, char *other)
1279     {
1280     sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
1281     }
1282    
1283     static void display_relaying(int i, char *other)
1284     {
1285     sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
1286     }
1287    
1288     static void display_tandem_relay(int i, char *other)
1289     {
1290     strcpy(other, "other rela");
1291     }
1292    
1293     static void display_pre_relay(int i, char *other)
1294     {
1295     strcpy(other, "other >rly");
1296     }
1297    
1298     static int expmem_relay(void *x)
1299     {
1300     register struct relay_info *p = (struct relay_info *) x;
1301     int tot = sizeof(struct relay_info);
1302    
1303     if (p->chat)
1304     tot += DCC_CHAT.expmem(p->chat);
1305     return tot;
1306     }
1307    
1308     static void kill_relay(int idx, void *x)
1309     {
1310     register struct relay_info *p = (struct relay_info *) x;
1311    
1312     if (p->chat)
1313     DCC_CHAT.kill(idx, p->chat);
1314     nfree(p);
1315     }
1316    
1317     struct dcc_table DCC_RELAY =
1318     {
1319     "RELAY",
1320     0, /* flags */
1321     eof_dcc_relay,
1322     dcc_relay,
1323     0,
1324     0,
1325     display_relay,
1326     expmem_relay,
1327     kill_relay,
1328     0
1329     };
1330    
1331     static void out_relay(int idx, char *buf, void *x)
1332     {
1333     register struct relay_info *p = (struct relay_info *) x;
1334    
1335     if (p && p->chat)
1336     DCC_CHAT.output(idx, buf, p->chat);
1337     else
1338     tputs(dcc[idx].sock, buf, strlen(buf));
1339     }
1340    
1341     struct dcc_table DCC_RELAYING =
1342     {
1343     "RELAYING",
1344     0, /* flags */
1345     eof_dcc_relaying,
1346     dcc_relaying,
1347     0,
1348     0,
1349     display_relaying,
1350     expmem_relay,
1351     kill_relay,
1352     out_relay
1353     };
1354    
1355     struct dcc_table DCC_FORK_RELAY =
1356     {
1357     "FORK_RELAY",
1358     0, /* flags */
1359     failed_tandem_relay,
1360     cont_tandem_relay,
1361     &connect_timeout,
1362     failed_tandem_relay,
1363     display_tandem_relay,
1364     expmem_relay,
1365     kill_relay,
1366     0
1367     };
1368    
1369     struct dcc_table DCC_PRE_RELAY =
1370     {
1371     "PRE_RELAY",
1372     0, /* flags */
1373     failed_pre_relay,
1374     pre_relay,
1375     0,
1376     0,
1377     display_pre_relay,
1378     expmem_relay,
1379     kill_relay,
1380     0
1381     };
1382    
1383     /* once a minute, send 'ping' to each bot -- no exceptions */
1384     void check_botnet_pings()
1385     {
1386     int i;
1387    
1388     context;
1389     for (i = 0; i < dcc_total; i++)
1390     if (dcc[i].type == &DCC_BOT)
1391     if (dcc[i].status & STAT_PINGED) {
1392     char s[1024];
1393    
1394     putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1395     simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1396     chatout("*** %s\n", s);
1397     botnet_send_unlinked(i, dcc[i].nick, s);
1398     killsock(dcc[i].sock);
1399     lostdcc(i);
1400     }
1401     context;
1402     for (i = 0; i < dcc_total; i++)
1403     if (dcc[i].type == &DCC_BOT) {
1404     botnet_send_ping(i);
1405     dcc[i].status |= STAT_PINGED;
1406     }
1407     context;
1408     for (i = 0; i < dcc_total; i++)
1409     if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
1410     tand_t *bot, *via = findbot(dcc[i].nick);
1411    
1412     for (bot = tandbot; bot; bot = bot->next) {
1413     if ((via == bot->via) && (bot != via)) {
1414     /* not leaflike behavior */
1415     if (dcc[i].status & STAT_WARNED) {
1416     char s[1024];
1417    
1418     putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
1419     dcc[i].nick, BOT_BOTNOTLEAFLIKE);
1420     dprintf(i, "bye\n");
1421     simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick,
1422     BOT_BOTNOTLEAFLIKE);
1423     chatout("*** %s\n", s);
1424     botnet_send_unlinked(i, dcc[i].nick, s);
1425     killsock(dcc[i].sock);
1426     lostdcc(i);
1427     } else {
1428     botnet_send_reject(i, botnetnick, NULL, bot->bot,
1429     NULL, NULL);
1430     dcc[i].status |= STAT_WARNED;
1431     }
1432     } else
1433     dcc[i].status &= ~STAT_WARNED;
1434     }
1435     }
1436     context;
1437     }
1438    
1439     void zapfbot(int idx)
1440     {
1441     char s[1024];
1442    
1443     simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick);
1444     chatout("*** %s\n", s);
1445     botnet_send_unlinked(idx, dcc[idx].nick, s);
1446     killsock(dcc[idx].sock);
1447     dcc[idx].sock = (long) dcc[idx].type;
1448     dcc[idx].type = &DCC_LOST;
1449     }
1450    
1451     void restart_chons()
1452     {
1453     int i;
1454    
1455     /* dump party line members */
1456     context;
1457     for (i = 0; i < dcc_total; i++) {
1458     if (dcc[i].type == &DCC_CHAT) {
1459     check_tcl_chon(dcc[i].nick, dcc[i].sock);
1460     check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
1461     geticon(i), dcc[i].sock, dcc[i].host);
1462     }
1463     }
1464     for (i = 0; i < parties; i++) {
1465     check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
1466     party[i].flag, party[i].sock, party[i].from);
1467     }
1468     context;
1469     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23