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

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

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


Revision 1.56 - (hide annotations) (download) (as text)
Sun Mar 3 20:17:54 2002 UTC (17 years, 8 months ago) by stdarg
Branch: MAIN
Changes since 1.55: +1 -2 lines
File MIME type: text/x-chdr
* Moved .tcl command to the tcl module

1 guppy 1.33 /*
2 segfault 1.1 * botnet.c -- handles:
3 fabian 1.11 * 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     * rejecting a bot
6     * linking, unlinking, and relaying to another bot
7     * pinging the bots periodically and checking leaf status
8 guppy 1.33 *
9 stdarg 1.56 * $Id: botnet.c,v 1.55 2002/03/03 19:03:46 stdarg Exp $
10 segfault 1.1 */
11 guppy 1.33 /*
12     * Copyright (C) 1997 Robey Pointer
13 wcc 1.53 * Copyright (C) 1999, 2000, 2001, 2002 Eggheads Development Team
14 guppy 1.33 *
15 fabian 1.11 * This program is free software; you can redistribute it and/or
16     * modify it under the terms of the GNU General Public License
17     * as published by the Free Software Foundation; either version 2
18     * of the License, or (at your option) any later version.
19 guppy 1.33 *
20 fabian 1.11 * This program is distributed in the hope that it will be useful,
21     * but WITHOUT ANY WARRANTY; without even the implied warranty of
22     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23     * GNU General Public License for more details.
24 guppy 1.33 *
25 fabian 1.11 * You should have received a copy of the GNU General Public License
26     * along with this program; if not, write to the Free Software
27     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 segfault 1.1 */
29    
30     #include "main.h"
31     #include "tandem.h"
32 stdarg 1.43 #include "modules.h"
33 ite 1.50 #include "logfile.h"
34     #include "misc.h"
35     #include "dns.h"
36 segfault 1.1
37 fabian 1.18 extern char spaces[], spaces2[];
38     extern int dcc_total, backgrd, connect_timeout, max_dcc,
39     egg_numver;
40     extern struct userrec *userlist;
41     extern struct dcc_t *dcc;
42     extern time_t now;
43    
44     tand_t *tandbot; /* Keep track of tandem bots on the
45     botnet */
46     party_t *party; /* Keep track of people on the botnet */
47     static int maxparty = 50; /* Maximum space for party line members
48     currently */
49     int tands = 0; /* Number of bots on the botnet */
50     int parties = 0; /* Number of people on the botnet */
51     char botnetnick[HANDLEN + 1] = ""; /* Botnet nickname */
52     int share_unlinks = 0; /* Allow remote unlinks of my
53     sharebots? */
54    
55 stdarg 1.43 /* From main.c */
56     extern int die_on_sigterm;
57     extern int die_on_sighup;
58    
59     static void botnet_sigterm(char *);
60     static void botnet_sighup(char *);
61 stdarg 1.39
62 stdarg 1.43 /* We want to listen to the sigterm event. */
63     static cmd_t botnet_events[] = {
64     {"botnet_sigterm", "", (Function) botnet_sigterm, NULL},
65     {"botnet_sighup", "", (Function) botnet_sighup, NULL},
66 tothwolf 1.47 {0}
67 stdarg 1.43 };
68 segfault 1.1
69 stdarg 1.39 static void init_bots();
70    
71     void botnet_init()
72     {
73 stdarg 1.43 bind_table_t *BT_event;
74    
75 stdarg 1.39 init_bots();
76 stdarg 1.43
77     /* Add our event handlers */
78     add_hook(HOOK_5MINUTELY, (Function) check_botnet_pings);
79     BT_event = find_bind_table2("event");
80     if (BT_event) add_builtins2(BT_event, botnet_events);
81     }
82    
83     /* Handle TERM signal */
84     static void botnet_sigterm(char *event)
85     {
86     if (die_on_sigterm) botnet_send_chat(-1, botnetnick, "ACK, I've been terminated! (SIGTERM)");
87     }
88    
89     static void botnet_sighup(char *event)
90     {
91     if (die_on_sighup) botnet_send_chat(-1, botnetnick, "ACK, I've been terminated! (SIGHUP)");
92 stdarg 1.39 }
93    
94     static void init_bots()
95 segfault 1.1 {
96     tandbot = NULL;
97 fabian 1.18 /* Grab space for 50 bots for now -- expand later as needed */
98 segfault 1.1 maxparty = 50;
99 tothwolf 1.41 party = (party_t *) malloc(maxparty * sizeof(party_t));
100 segfault 1.1 }
101    
102     tand_t *findbot(char *who)
103     {
104 guppy 1.35 tand_t *ptr;
105 segfault 1.1
106 guppy 1.35 for (ptr = tandbot; ptr; ptr = ptr->next)
107 tothwolf 1.45 if (!strcasecmp(ptr->bot, who))
108 segfault 1.1 return ptr;
109     return NULL;
110     }
111    
112 fabian 1.18 /* Add a tandem bot to our chain list
113     */
114 segfault 1.1 void addbot(char *who, char *from, char *next, char flag, int vernum)
115     {
116     tand_t **ptr = &tandbot, *ptr2;
117    
118     while (*ptr) {
119 tothwolf 1.45 if (!strcasecmp((*ptr)->bot, who))
120 segfault 1.1 putlog(LOG_BOTS, "*", "!!! Duplicate botnet bot entry!!");
121     ptr = &((*ptr)->next);
122     }
123 tothwolf 1.41 ptr2 = malloc(sizeof(tand_t));
124 segfault 1.1 strncpy(ptr2->bot, who, HANDLEN);
125     ptr2->bot[HANDLEN] = 0;
126     ptr2->share = flag;
127     ptr2->ver = vernum;
128     ptr2->next = *ptr;
129     *ptr = ptr2;
130 fabian 1.18 /* May be via itself */
131 segfault 1.1 ptr2->via = findbot(from);
132 tothwolf 1.45 if (!strcasecmp(next, botnetnick))
133 segfault 1.1 ptr2->uplink = (tand_t *) 1;
134     else
135     ptr2->uplink = findbot(next);
136     tands++;
137     }
138    
139     void updatebot(int idx, char *who, char share, int vernum)
140     {
141     tand_t *ptr = findbot(who);
142    
143     if (ptr) {
144     if (share)
145     ptr->share = share;
146     if (vernum)
147     ptr->ver = vernum;
148     botnet_send_update(idx, ptr);
149     }
150     }
151    
152 fabian 1.18 /* For backward 1.0 compatibility:
153     * grab the (first) sock# for a user on another bot
154     */
155 segfault 1.1 int partysock(char *bot, char *nick)
156     {
157     int i;
158    
159     for (i = 0; i < parties; i++) {
160 tothwolf 1.45 if ((!strcasecmp(party[i].bot, bot)) &&
161     (!strcasecmp(party[i].nick, nick)))
162 segfault 1.1 return party[i].sock;
163     }
164     return 0;
165     }
166    
167 fabian 1.18 /* New botnet member
168     */
169 segfault 1.1 int addparty(char *bot, char *nick, int chan, char flag, int sock,
170     char *from, int *idx)
171     {
172     int i;
173    
174     for (i = 0; i < parties; i++) {
175 fabian 1.18 /* Just changing the channel of someone already on? */
176 tothwolf 1.45 if (!strcasecmp(party[i].bot, bot) &&
177 segfault 1.1 (party[i].sock == sock)) {
178     int oldchan = party[i].chan;
179    
180     party[i].chan = chan;
181     party[i].timer = now;
182     if (from[0]) {
183     if (flag == ' ')
184     flag = '-';
185     party[i].flag = flag;
186     if (party[i].from)
187 tothwolf 1.41 free(party[i].from);
188 ite 1.49 party[i].from = strdup(from);
189 segfault 1.1 }
190     *idx = i;
191     return oldchan;
192     }
193     }
194 fabian 1.18 /* New member */
195 segfault 1.1 if (parties == maxparty) {
196     maxparty += 50;
197 tothwolf 1.41 party = (party_t *) realloc((void *) party, maxparty * sizeof(party_t));
198 segfault 1.1 }
199     strncpy(party[parties].nick, nick, HANDLEN);
200     party[parties].nick[HANDLEN] = 0;
201     strncpy(party[parties].bot, bot, HANDLEN);
202     party[parties].bot[HANDLEN] = 0;
203     party[parties].chan = chan;
204     party[parties].sock = sock;
205     party[parties].status = 0;
206     party[parties].away = 0;
207     party[parties].timer = now; /* cope. */
208     if (from[0]) {
209     if (flag == ' ')
210     flag = '-';
211     party[parties].flag = flag;
212 ite 1.49 party[parties].from = strdup(from);
213 segfault 1.1 } else {
214     party[parties].flag = ' ';
215 ite 1.49 party[parties].from = strdup("(unknown)");
216 segfault 1.1 }
217     *idx = parties;
218     parties++;
219     return -1;
220     }
221    
222 fabian 1.18 /* Alter status flags for remote party-line user.
223     */
224 segfault 1.1 void partystat(char *bot, int sock, int add, int rem)
225     {
226     int i;
227    
228     for (i = 0; i < parties; i++) {
229 tothwolf 1.45 if ((!strcasecmp(party[i].bot, bot)) &&
230 segfault 1.1 (party[i].sock == sock)) {
231     party[i].status |= add;
232     party[i].status &= ~rem;
233     }
234     }
235     }
236    
237 fabian 1.18 /* Other bot is sharing idle info.
238     */
239 segfault 1.1 void partysetidle(char *bot, int sock, int secs)
240     {
241     int i;
242    
243     for (i = 0; i < parties; i++) {
244 tothwolf 1.45 if ((!strcasecmp(party[i].bot, bot)) &&
245 segfault 1.1 (party[i].sock == sock)) {
246     party[i].timer = (now - (time_t) secs);
247     }
248     }
249     }
250    
251 fabian 1.18 /* Return someone's chat channel.
252     */
253 segfault 1.1 int getparty(char *bot, int sock)
254     {
255     int i;
256    
257     for (i = 0; i < parties; i++) {
258 tothwolf 1.45 if (!strcasecmp(party[i].bot, bot) &&
259 segfault 1.1 (party[i].sock == sock)) {
260     return i;
261     }
262     }
263     return -1;
264     }
265    
266 fabian 1.18 /* Un-idle someone
267     */
268 segfault 1.1 int partyidle(char *bot, char *nick)
269     {
270     int i, ok = 0;
271    
272     for (i = 0; i < parties; i++) {
273 tothwolf 1.45 if ((!strcasecmp(party[i].bot, bot)) &&
274     (!strcasecmp(party[i].nick, nick))) {
275 segfault 1.1 party[i].timer = now;
276     ok = 1;
277     }
278     }
279     return ok;
280     }
281    
282 fabian 1.18 /* Change someone's nick
283     */
284 segfault 1.1 int partynick(char *bot, int sock, char *nick)
285     {
286     char work[HANDLEN + 1];
287     int i;
288    
289     for (i = 0; i < parties; i++) {
290 tothwolf 1.45 if (!strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
291 segfault 1.1 strcpy(work, party[i].nick);
292     strncpy(party[i].nick, nick, HANDLEN);
293     party[i].nick[HANDLEN] = 0;
294     strcpy(nick, work);
295     return i;
296     }
297     }
298     return -1;
299     }
300    
301 fabian 1.18 /* Set away message
302     */
303 segfault 1.1 void partyaway(char *bot, int sock, char *msg)
304     {
305     int i;
306    
307     for (i = 0; i < parties; i++) {
308 tothwolf 1.45 if ((!strcasecmp(party[i].bot, bot)) &&
309 segfault 1.1 (party[i].sock == sock)) {
310     if (party[i].away)
311 tothwolf 1.41 free(party[i].away);
312     if (msg[0])
313 ite 1.49 party[i].away = strdup(msg);
314 tothwolf 1.41 else
315 segfault 1.1 party[i].away = 0;
316     }
317     }
318     }
319    
320 fabian 1.18 /* Remove a tandem bot from the chain list
321     */
322 segfault 1.1 void rembot(char *who)
323     {
324     tand_t **ptr = &tandbot, *ptr2;
325 guppy 1.54 struct userrec *u;
326 segfault 1.1
327     while (*ptr) {
328 tothwolf 1.45 if (!strcasecmp((*ptr)->bot, who))
329 segfault 1.1 break;
330     ptr = &((*ptr)->next);
331     }
332     if (!*ptr)
333 fabian 1.18 /* May have just .unlink *'d */
334 segfault 1.1 return;
335     check_tcl_disc(who);
336 guppy 1.54
337     u = get_user_by_handle(userlist, who);
338     if (u != NULL)
339     touch_laston(u, "unlinked", now);
340 segfault 1.1
341     ptr2 = *ptr;
342     *ptr = ptr2->next;
343 tothwolf 1.41 free(ptr2);
344 segfault 1.1 tands--;
345 fabian 1.7
346     dupwait_notify(who);
347 segfault 1.1 }
348    
349     void remparty(char *bot, int sock)
350     {
351     int i;
352    
353     for (i = 0; i < parties; i++)
354 tothwolf 1.45 if ((!strcasecmp(party[i].bot, bot)) &&
355 segfault 1.1 (party[i].sock == sock)) {
356     parties--;
357     if (party[i].from)
358 tothwolf 1.41 free(party[i].from);
359 segfault 1.1 if (party[i].away)
360 tothwolf 1.41 free(party[i].away);
361 segfault 1.1 if (i < parties) {
362     strcpy(party[i].bot, party[parties].bot);
363     strcpy(party[i].nick, party[parties].nick);
364     party[i].chan = party[parties].chan;
365     party[i].sock = party[parties].sock;
366     party[i].flag = party[parties].flag;
367     party[i].status = party[parties].status;
368     party[i].timer = party[parties].timer;
369     party[i].from = party[parties].from;
370     party[i].away = party[parties].away;
371     }
372     }
373     }
374    
375 fabian 1.18 /* Cancel every user that was on a certain bot
376     */
377 segfault 1.1 void rempartybot(char *bot)
378     {
379     int i;
380    
381     for (i = 0; i < parties; i++)
382 tothwolf 1.45 if (!strcasecmp(party[i].bot, bot)) {
383 stdarg 1.39 if (party[i].chan >= 0) {
384 fabian 1.5 check_tcl_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
385 stdarg 1.39 }
386 segfault 1.1 remparty(bot, party[i].sock);
387     i--;
388     }
389     }
390    
391 fabian 1.18 /* Remove every bot linked 'via' bot <x>
392     */
393 segfault 1.1 void unvia(int idx, tand_t * who)
394     {
395     tand_t *bot, *bot2;
396    
397     if (!who)
398 fabian 1.18 return; /* Safety */
399 segfault 1.1 rempartybot(who->bot);
400     bot = tandbot;
401     while (bot) {
402     if (bot->uplink == who) {
403     unvia(idx, bot);
404     bot2 = bot->next;
405     rembot(bot->bot);
406     bot = bot2;
407     } else
408     bot = bot->next;
409     }
410     #ifndef NO_OLD_BOTNET
411 guppy 1.33 /* Every bot unvia's bots behind anyway, so why send msg's for
412 fabian 1.18 * EVERY one? - will this break things?!
413     */
414 segfault 1.1 tandout_but(idx, "unlinked %s\n", who->bot);
415     #endif
416     }
417    
418 fabian 1.18 /* Return index into dcc list of the bot that connects us to bot <x>
419     */
420 segfault 1.1 int nextbot(char *who)
421     {
422     int j;
423     tand_t *bot = findbot(who);
424    
425     if (!bot)
426     return -1;
427    
428     for (j = 0; j < dcc_total; j++)
429 tothwolf 1.45 if (bot->via && !strcasecmp(bot->via->bot, dcc[j].nick) &&
430 segfault 1.1 (dcc[j].type == &DCC_BOT))
431     return j;
432 fabian 1.18 return -1; /* We're not connected to 'via' */
433 segfault 1.1 }
434    
435 fabian 1.18 /* Return name of the bot that is directly connected to bot X
436     */
437 segfault 1.1 char *lastbot(char *who)
438     {
439     tand_t *bot = findbot(who);
440    
441     if (!bot)
442     return "*";
443     else if (bot->uplink == (tand_t *) 1)
444     return botnetnick;
445     else
446     return bot->uplink->bot;
447     }
448    
449 fabian 1.18 /* Modern version of 'whom' (use local data)
450     */
451 segfault 1.1 void answer_local_whom(int idx, int chan)
452     {
453     char c, idle[40], spaces2[33] = " ";
454 guppy 1.48 int i, len, len2, t, nicklen, botnicklen, total = 0;
455 segfault 1.1
456     if (chan == (-1))
457 ite 1.38 dprintf(idx, "%s (+: %s, *: %s)\n", _("Users across the botnet"), _("Party line"),
458     _("Local channel"));
459 segfault 1.1 else if (chan > 0) {
460 stdarg 1.55 dprintf(idx, "%s %s%d:\n", _("Users on channel"),
461 segfault 1.1 (chan < 100000) ? "" : "*", chan % 100000);
462     }
463 poptix 1.37 /* Find longest nick and botnick */
464     nicklen = botnicklen = 0;
465     for (i = 0; i < dcc_total; i++)
466     if (dcc[i].type == &DCC_CHAT) {
467     if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
468     t = strlen(dcc[i].nick); if(t > nicklen) nicklen = t;
469     t = strlen(botnetnick); if(t > botnicklen) botnicklen = t;
470     }
471     }
472     for (i = 0; i < parties; i++) {
473     if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
474     t = strlen(party[i].nick); if(t > nicklen) nicklen = t;
475     t = strlen(party[i].bot); if(t > botnicklen) botnicklen = t;
476     }
477     }
478     if(nicklen < 9) nicklen = 9;
479     if(botnicklen < 9) botnicklen = 9;
480    
481     spaces[nicklen - 9] = 0;
482     spaces2[botnicklen - 9] = 0;
483     dprintf(idx, " Nick %s Bot %s Host\n", spaces, spaces2);
484 segfault 1.1 dprintf(idx, "----------%s ---------%s --------------------\n",
485 poptix 1.37 spaces, spaces2);
486     spaces[nicklen - 9] = ' ';
487     spaces2[botnicklen - 9] = ' ';
488 segfault 1.1 for (i = 0; i < dcc_total; i++)
489     if (dcc[i].type == &DCC_CHAT) {
490     if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
491 ite 1.51 c = geticon(dcc[i].user);
492 segfault 1.1 if (c == '-')
493     c = ' ';
494     if (now - dcc[i].timeval > 300) {
495     unsigned long days, hrs, mins;
496    
497     days = (now - dcc[i].timeval) / 86400;
498     hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
499     mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
500     if (days > 0)
501     sprintf(idle, " [idle %lud%luh]", days, hrs);
502     else if (hrs > 0)
503     sprintf(idle, " [idle %luh%lum]", hrs, mins);
504     else
505     sprintf(idle, " [idle %lum]", mins);
506     } else
507     idle[0] = 0;
508 poptix 1.37 spaces[len = nicklen - strlen(dcc[i].nick)] = 0;
509     spaces2[len2 = botnicklen - strlen(botnetnick)] = 0;
510 guppy 1.48 total++;
511 segfault 1.1 dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, dcc[i].nick, spaces,
512     (dcc[i].u.chat->channel == 0) && (chan == (-1)) ? '+' :
513     (dcc[i].u.chat->channel > 100000) &&
514     (chan == (-1)) ? '*' : ' ',
515     botnetnick, spaces2, dcc[i].host, idle);
516     spaces[len] = ' ';
517     spaces2[len2] = ' ';
518     if (dcc[i].u.chat->away != NULL)
519     dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
520     }
521     }
522     for (i = 0; i < parties; i++) {
523     if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
524     c = party[i].flag;
525     if (c == '-')
526     c = ' ';
527     if (party[i].timer == 0L)
528     strcpy(idle, " [idle?]");
529     else if (now - party[i].timer > 300) {
530     unsigned long days, hrs, mins;
531    
532     days = (now - party[i].timer) / 86400;
533     hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
534     mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
535     if (days > 0)
536     sprintf(idle, " [idle %lud%luh]", days, hrs);
537     else if (hrs > 0)
538     sprintf(idle, " [idle %luh%lum]", hrs, mins);
539     else
540     sprintf(idle, " [idle %lum]", mins);
541     } else
542     idle[0] = 0;
543 poptix 1.37 spaces[len = nicklen - strlen(party[i].nick)] = 0;
544     spaces2[len2 = botnicklen - strlen(party[i].bot)] = 0;
545 guppy 1.48 total++;
546 segfault 1.1 dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, party[i].nick, spaces,
547     (party[i].chan == 0) && (chan == (-1)) ? '+' : ' ',
548     party[i].bot, spaces2, party[i].from, idle);
549     spaces[len] = ' ';
550     spaces2[len2] = ' ';
551     if (party[i].status & PLSTAT_AWAY)
552 ite 1.38 dprintf(idx, " %s: %s\n", _("AWAY"),
553 fabian 1.28 party[i].away ? party[i].away : "");
554 segfault 1.1 }
555     }
556 guppy 1.48 dprintf(idx, "Total users: %d\n", total);
557 segfault 1.1 }
558    
559 fabian 1.18 /* Show z a list of all bots connected
560     */
561 segfault 1.1 void tell_bots(int idx)
562     {
563     char s[512];
564     int i;
565     tand_t *bot;
566    
567     if (!tands) {
568 ite 1.38 dprintf(idx, "%s\n", _("No bots linked."));
569 segfault 1.1 return;
570     }
571     strcpy(s, botnetnick);
572     i = strlen(botnetnick);
573    
574     for (bot = tandbot; bot; bot = bot->next) {
575     if (i > (500 - HANDLEN)) {
576     dprintf(idx, "Bots: %s\n", s);
577     s[0] = 0;
578     i = 0;
579     }
580     if (i) {
581     s[i++] = ',';
582     s[i++] = ' ';
583     }
584     strcpy(s + i, bot->bot);
585     i += strlen(bot->bot);
586     }
587     if (s[0])
588     dprintf(idx, "Bots: %s\n", s);
589 ite 1.38 dprintf(idx, "(%s: %d)\n", _("total"), tands + 1);
590 segfault 1.1 }
591    
592 fabian 1.18 /* Show a simpleton bot tree
593     */
594 segfault 1.1 void tell_bottree(int idx, int showver)
595     {
596     char s[161];
597     tand_t *last[20], *this, *bot, *bot2 = NULL;
598     int lev = 0, more = 1, mark[20], ok, cnt, i, imark;
599     char work[1024];
600     int tothops = 0;
601    
602     if (tands == 0) {
603 ite 1.38 dprintf(idx, "%s\n", _("No bots linked."));
604 segfault 1.1 return;
605     }
606     s[0] = 0;
607     i = 0;
608    
609     for (bot = tandbot; bot; bot = bot->next)
610     if (!bot->uplink) {
611     if (i) {
612     s[i++] = ',';
613     s[i++] = ' ';
614     }
615     strcpy(s + i, bot->bot);
616     i += strlen(bot->bot);
617     }
618     if (s[0])
619 ite 1.38 dprintf(idx, "(%s %s)\n", _("No trace info for:"), s);
620 segfault 1.1 if (showver)
621     dprintf(idx, "%s (%d.%d.%d.%d)\n", botnetnick,
622     egg_numver / 1000000,
623     egg_numver % 1000000 / 10000,
624     egg_numver % 10000 / 100,
625     egg_numver % 100);
626     else
627     dprintf(idx, "%s\n", botnetnick);
628     this = (tand_t *) 1;
629     work[0] = 0;
630     while (more) {
631     if (lev == 20) {
632 ite 1.38 dprintf(idx, "\n%s\n", _("Tree too complex!"));
633 segfault 1.1 return;
634     }
635     cnt = 0;
636     tothops += lev;
637     for (bot = tandbot; bot; bot = bot->next)
638     if (bot->uplink == this)
639     cnt++;
640     if (cnt) {
641     imark = 0;
642     for (i = 0; i < lev; i++) {
643     if (mark[i])
644     strcpy(work + imark, " | ");
645     else
646     strcpy(work + imark, " ");
647     imark += 5;
648     }
649     if (cnt > 1)
650     strcpy(work + imark, " |-");
651     else
652     strcpy(work + imark, " `-");
653     s[0] = 0;
654     bot = tandbot;
655     while (!s[0]) {
656     if (bot->uplink == this) {
657     if (bot->ver) {
658     i = sprintf(s, "%c%s", bot->share, bot->bot);
659     if (showver)
660     sprintf(s + i, " (%d.%d.%d.%d)",
661     bot->ver / 1000000,
662     bot->ver % 1000000 / 10000,
663     bot->ver % 10000 / 100,
664     bot->ver % 100);
665     } else {
666     sprintf(s, "-%s", bot->bot);
667     }
668     } else
669     bot = bot->next;
670     }
671     dprintf(idx, "%s%s\n", work, s);
672     if (cnt > 1)
673     mark[lev] = 1;
674     else
675     mark[lev] = 0;
676     work[0] = 0;
677     last[lev] = this;
678     this = bot;
679     lev++;
680     more = 1;
681     } else {
682     while (cnt == 0) {
683 fabian 1.18 /* No subtrees from here */
684 segfault 1.1 if (lev == 0) {
685     dprintf(idx, "(( tree error ))\n");
686     return;
687     }
688     ok = 0;
689     for (bot = tandbot; bot; bot = bot->next) {
690     if (bot->uplink == last[lev - 1]) {
691     if (this == bot)
692     ok = 1;
693     else if (ok) {
694     cnt++;
695     if (cnt == 1) {
696     bot2 = bot;
697     if (bot->ver) {
698     i = sprintf(s, "%c%s", bot->share, bot->bot);
699     if (showver)
700     sprintf(s + i, " (%d.%d.%d.%d)",
701     bot->ver / 1000000,
702     bot->ver % 1000000 / 10000,
703     bot->ver % 10000 / 100,
704     bot->ver % 100);
705     } else {
706     sprintf(s, "-%s", bot->bot);
707     }
708     }
709     }
710     }
711     }
712     if (cnt) {
713     imark = 0;
714     for (i = 1; i < lev; i++) {
715     if (mark[i - 1])
716     strcpy(work + imark, " | ");
717     else
718     strcpy(work + imark, " ");
719     imark += 5;
720     }
721     more = 1;
722     if (cnt > 1)
723     dprintf(idx, "%s |-%s\n", work, s);
724     else
725     dprintf(idx, "%s `-%s\n", work, s);
726     this = bot2;
727     work[0] = 0;
728     if (cnt > 1)
729     mark[lev - 1] = 1;
730     else
731     mark[lev - 1] = 0;
732     } else {
733 fabian 1.18 /* This was the last child */
734 segfault 1.1 lev--;
735     if (lev == 0) {
736     more = 0;
737     cnt = 999;
738     } else {
739     more = 1;
740     this = last[lev];
741     }
742     }
743     }
744     }
745     }
746 fabian 1.18 /* Hop information: (9d) */
747 segfault 1.1 dprintf(idx, "Average hops: %3.1f, total bots: %d\n",
748     ((float) tothops) / ((float) tands), tands + 1);
749     }
750    
751 fabian 1.18 /* Dump list of links to a new bot
752     */
753 segfault 1.1 void dump_links(int z)
754     {
755 fabian 1.14 register int i, l;
756 segfault 1.1 char x[1024];
757     tand_t *bot;
758    
759     for (bot = tandbot; bot; bot = bot->next) {
760     char *p;
761    
762     if (bot->uplink == (tand_t *) 1)
763     p = botnetnick;
764     else
765     p = bot->uplink->bot;
766     #ifndef NO_OLD_BOTNET
767     if (b_numver(z) < NEAT_BOTNET)
768     l = simple_sprintf(x, "nlinked %s %s %c%d\n", bot->bot,
769     p, bot->share, bot->ver);
770     else
771     #endif
772     l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p,
773     bot->share, bot->ver);
774     tputs(dcc[z].sock, x, l);
775     }
776     if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
777 fabian 1.18 /* Dump party line members */
778 segfault 1.1 for (i = 0; i < dcc_total; i++) {
779     if (dcc[i].type == &DCC_CHAT) {
780     if ((dcc[i].u.chat->channel >= 0) &&
781     (dcc[i].u.chat->channel < 100000)) {
782     #ifndef NO_OLD_BOTNET
783     if (b_numver(z) < NEAT_BOTNET)
784     l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
785     botnetnick, dcc[i].nick,
786 ite 1.51 dcc[i].u.chat->channel, geticon(dcc[i].user),
787 segfault 1.1 dcc[i].sock, dcc[i].host);
788     else
789     #endif
790     l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
791     botnetnick, dcc[i].nick,
792 ite 1.51 dcc[i].u.chat->channel, geticon(dcc[i].user),
793 segfault 1.1 dcc[i].sock, dcc[i].host);
794     tputs(dcc[z].sock, x, l);
795     #ifndef NO_OLD_BOTNET
796     if (b_numver(z) < NEAT_BOTNET) {
797     if (dcc[i].u.chat->away) {
798     l = simple_sprintf(x, "away %s %d %s\n", botnetnick,
799     dcc[i].sock, dcc[i].u.chat->away);
800     tputs(dcc[z].sock, x, l);
801     }
802     l = simple_sprintf(x, "idle %s %d %d\n", botnetnick,
803     dcc[i].sock, now - dcc[i].timeval);
804     } else
805     #endif
806     l = simple_sprintf(x, "i %s %D %D %s\n", botnetnick,
807     dcc[i].sock, now - dcc[i].timeval,
808     dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
809     tputs(dcc[z].sock, x, l);
810     }
811     }
812     }
813     for (i = 0; i < parties; i++) {
814     #ifndef NO_OLD_BOTNET
815     if (b_numver(z) < NEAT_BOTNET)
816     l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
817     party[i].bot, party[i].nick,
818     party[i].chan, party[i].flag,
819     party[i].sock, party[i].from);
820     else
821     #endif
822     l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
823     party[i].bot, party[i].nick,
824     party[i].chan, party[i].flag,
825     party[i].sock, party[i].from);
826     tputs(dcc[z].sock, x, l);
827     if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
828     #ifndef NO_OLD_BOTNET
829     if (b_numver(z) < NEAT_BOTNET) {
830     if (party[i].status & PLSTAT_AWAY) {
831     l = simple_sprintf(x, "away %s %d %s\n", party[i].bot,
832     party[i].sock, party[i].away);
833     tputs(dcc[z].sock, x, l);
834     }
835     l = simple_sprintf(x, "idle %s %d %d\n", party[i].bot,
836     party[i].sock, now - party[i].timer);
837     } else
838     #endif
839     l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
840     party[i].sock, now - party[i].timer,
841     party[i].away ? party[i].away : "");
842     tputs(dcc[z].sock, x, l);
843     }
844     }
845     }
846     }
847    
848     int in_chain(char *who)
849     {
850     if (findbot(who))
851     return 1;
852 tothwolf 1.45 if (!strcasecmp(who, botnetnick))
853 segfault 1.1 return 1;
854     return 0;
855     }
856    
857 fabian 1.19 int bots_in_subtree(tand_t *bot)
858     {
859     int nr = 1;
860     tand_t *b;
861    
862     if (!bot)
863     return 0;
864     for (b = tandbot; b; b = b->next) {
865     if (b->bot && (b->uplink == bot)) {
866     nr += bots_in_subtree(b);
867     }
868     }
869     return nr;
870     }
871    
872     int users_in_subtree(tand_t *bot)
873     {
874     int i, nr;
875     tand_t *b;
876    
877     nr = 0;
878     if (!bot)
879     return 0;
880 fabian 1.22 for (i = 0; i < parties; i++)
881 tothwolf 1.45 if (!strcasecmp(party[i].bot, bot->bot))
882 fabian 1.19 nr++;
883 fabian 1.22 for (b = tandbot; b; b = b->next)
884     if (b->bot && (b->uplink == bot))
885 fabian 1.19 nr += users_in_subtree(b);
886     return nr;
887     }
888    
889 fabian 1.18 /* Break link with a tandembot
890     */
891 segfault 1.1 int botunlink(int idx, char *nick, char *reason)
892     {
893 fabian 1.14 register int i;
894 fabian 1.19 int bots, users;
895     tand_t *bot;
896 segfault 1.1
897     if (nick[0] == '*')
898 ite 1.38 dprintf(idx, "%s\n", _("Unlinking all bots..."));
899 segfault 1.1 for (i = 0; i < dcc_total; i++) {
900 tothwolf 1.45 if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) {
901 segfault 1.1 if (dcc[i].type == &DCC_FORK_BOT) {
902     if (idx >= 0)
903 ite 1.38 dprintf(idx, "%s: %s -> %s.\n", _("Killed link attempt to"),
904 segfault 1.1 dcc[i].nick, dcc[i].host);
905     putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
906 ite 1.38 _("Killed link attempt to"), dcc[i].nick,
907 segfault 1.1 dcc[i].host, dcc[i].port);
908     killsock(dcc[i].sock);
909     lostdcc(i);
910     if (nick[0] != '*')
911     return 1;
912     } else if (dcc[i].type == &DCC_BOT_NEW) {
913     if (idx >= 0)
914 ite 1.38 dprintf(idx, "%s %s.\n", _("No longer trying to link:"),
915 segfault 1.1 dcc[i].nick);
916     putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
917     "Stopped trying to link", dcc[i].nick,
918     dcc[i].host, dcc[i].port);
919     killsock(dcc[i].sock);
920     lostdcc(i);
921     if (nick[0] != '*')
922     return 1;
923     } else if (dcc[i].type == &DCC_BOT) {
924     char s[1024];
925    
926     if (idx >= 0)
927 ite 1.38 dprintf(idx, "%s %s.\n", _("Breaking link with"), dcc[i].nick);
928 segfault 1.1 else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
929     return -1;
930 fabian 1.19 bot = findbot(dcc[i].nick);
931     bots = bots_in_subtree(bot);
932     users = users_in_subtree(bot);
933 segfault 1.1 if (reason && reason[0]) {
934 ite 1.52 /* FIXME PLURAL: handle this correctly with gettext */
935 fabian 1.19 simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s)",
936 ite 1.38 _("Unlinked from:"), dcc[i].nick, reason, bots,
937 ite 1.52 (bots != 1) ? "s" : "", users, (users != 1) ?
938 fabian 1.19 "s" : "");
939 fabian 1.17 dprintf(i, "bye %s\n", reason);
940 segfault 1.1 } else {
941 ite 1.52 /* FIXME PLURAL: handle this correctly with gettext */
942 fabian 1.19 simple_sprintf(s, "%s %s (lost %d bot%s and %d user%s)",
943 ite 1.38 _("Unlinked from:"), dcc[i].nick, bots, (bots > 1) ?
944 ite 1.52 "s" : "", users, (users != 1) ? "s" : "");
945 fabian 1.17 dprintf(i, "bye No reason\n");
946 segfault 1.1 }
947     chatout("*** %s\n", s);
948     botnet_send_unlinked(i, dcc[i].nick, s);
949     killsock(dcc[i].sock);
950     lostdcc(i);
951     if (nick[0] != '*')
952     return 1;
953     }
954     }
955     }
956 fabian 1.27 if (idx >= 0 && nick[0] != '*')
957 ite 1.38 dprintf(idx, "%s\n", _("Not connected to that bot."));
958 fabian 1.27 if (nick[0] != '*') {
959 fabian 1.24 bot = findbot(nick);
960     if (bot) {
961 fabian 1.27 /* The internal bot list is desynched from the dcc list
962     sometimes. While we still search for the bug, provide
963     an easy way to clear out those `ghost'-bots.
964     Fabian (2000-08-02) */
965     char *ghost = "BUG!!: Found bot `%s' in internal bot list, but it\n"
966     " shouldn't have been there! Removing.\n"
967     " This is a known bug we haven't fixed yet. If this\n"
968     " bot is the newest eggdrop version available and you\n"
969     " know a *reliable* way to reproduce the bug, please\n"
970     " contact us - we need your help!\n";
971     if (idx >= 0)
972     dprintf(idx, ghost, nick);
973     else
974     putlog(LOG_MISC, "*", ghost, nick);
975 fabian 1.24 rembot(bot->bot);
976 fabian 1.27 return 1;
977 fabian 1.24 }
978     }
979 segfault 1.1 if (nick[0] == '*') {
980 stdarg 1.55 dprintf(idx, "%s\n", _("Smooshing bot tables..."));
981 segfault 1.1 while (tandbot)
982     rembot(tandbot->bot);
983     while (parties) {
984     parties--;
985 tothwolf 1.44 /* assert? */
986 stdarg 1.39 if (party[i].chan >= 0) {
987 fabian 1.5 check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
988     party[i].chan);
989 stdarg 1.39 }
990 segfault 1.1 }
991     }
992     return 0;
993     }
994    
995 fabian 1.2 static void botlink_resolve_success(int);
996     static void botlink_resolve_failure(int);
997    
998 fabian 1.18 /* Link to another bot
999     */
1000 segfault 1.1 int botlink(char *linker, int idx, char *nick)
1001     {
1002     struct bot_addr *bi;
1003     struct userrec *u;
1004 fabian 1.14 register int i;
1005 segfault 1.1
1006     u = get_user_by_handle(userlist, nick);
1007     if (!u || !(u->flags & USER_BOT)) {
1008     if (idx >= 0)
1009 ite 1.38 dprintf(idx, _("%s is not a known bot.\n"), nick);
1010 tothwolf 1.45 } else if (!strcasecmp(nick, botnetnick)) {
1011 segfault 1.1 if (idx >= 0)
1012 ite 1.38 dprintf(idx, _("Link to myself? Oh boy, Freud would have a field day.\n"));
1013 segfault 1.1 } else if (in_chain(nick) && (idx != -3)) {
1014     if (idx >= 0)
1015 ite 1.38 dprintf(idx, _("That bot is already connected up.\n"));
1016 segfault 1.1 } else {
1017     for (i = 0; i < dcc_total; i++)
1018     if ((dcc[i].user == u) &&
1019     ((dcc[i].type == &DCC_FORK_BOT) ||
1020     (dcc[i].type == &DCC_BOT_NEW))) {
1021     if (idx >= 0)
1022 ite 1.38 dprintf(idx, _("Already linking to that bot.\n"));
1023 segfault 1.1 return 0;
1024     }
1025 fabian 1.18 /* Address to connect to is in 'info' */
1026 segfault 1.1 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
1027 guppy 1.34 if (!bi || !strlen(bi->address) || !bi->telnet_port || (bi->telnet_port <= 0)) {
1028 segfault 1.1 if (idx >= 0) {
1029 ite 1.38 dprintf(idx, _("Invalid telnet address:port stored for '%s'.\n"), nick);
1030     dprintf(idx, _("Use: .chaddr %s <address>:<port#>[/<relay-port#>]\n"),
1031     nick);
1032 segfault 1.1 }
1033     } else if (dcc_total == max_dcc) {
1034     if (idx >= 0)
1035 ite 1.38 dprintf(idx, _("Sorry, too many DCC connections.\n"));
1036 segfault 1.1 } else {
1037     correct_handle(nick);
1038    
1039     if (idx > -2)
1040 ite 1.38 putlog(LOG_BOTS, "*", _("Linking to %s at %s:%d ..."), nick,
1041 segfault 1.1 bi->address, bi->telnet_port);
1042 fabian 1.2
1043     i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
1044 segfault 1.1 dcc[i].timeval = now;
1045 fabian 1.2 dcc[i].port = bi->telnet_port;
1046 fabian 1.4 dcc[i].user = u;
1047 fabian 1.2 strcpy(dcc[i].nick, nick);
1048     strcpy(dcc[i].host, bi->address);
1049     dcc[i].u.dns->ibuf = idx;
1050     dcc[i].u.dns->cptr = linker;
1051 tothwolf 1.42 dcc[i].u.dns->host = calloc(1, strlen(dcc[i].host) + 1);
1052 fabian 1.2 strcpy(dcc[i].u.dns->host, dcc[i].host);
1053 fabian 1.29 dcc[i].u.dns->dns_success = botlink_resolve_success;
1054     dcc[i].u.dns->dns_failure = botlink_resolve_failure;
1055 fabian 1.2 dcc[i].u.dns->dns_type = RES_IPBYHOST;
1056 fabian 1.4 dcc[i].u.dns->type = &DCC_FORK_BOT;
1057 fabian 1.13 dcc_dnsipbyhost(bi->address);
1058 fabian 1.9 return 1;
1059 segfault 1.1 }
1060     }
1061     return 0;
1062     }
1063    
1064 fabian 1.2 static void botlink_resolve_failure(int i)
1065     {
1066     char s[81];
1067    
1068 ite 1.38 putlog(LOG_BOTS, "*", _("Failed link to %s."), dcc[i].nick);
1069 fabian 1.2 strcpy(s, dcc[i].nick);
1070     lostdcc(i);
1071 fabian 1.18 autolink_cycle(s); /* Check for more auto-connections */
1072 fabian 1.2 }
1073    
1074     static void botlink_resolve_success(int i)
1075     {
1076     int idx = dcc[i].u.dns->ibuf;
1077     char *linker = dcc[i].u.dns->cptr;
1078    
1079 drummer 1.36 strcpy(dcc[i].addr, dcc[i].u.dns->host);
1080 fabian 1.2 changeover_dcc(i, &DCC_FORK_BOT, sizeof(struct bot_info));
1081     dcc[i].timeval = now;
1082     strcpy(dcc[i].u.bot->linker, linker);
1083     strcpy(dcc[i].u.bot->version, "(primitive bot)");
1084     dcc[i].u.bot->numver = idx;
1085 fabian 1.18 dcc[i].u.bot->port = dcc[i].port; /* Remember where i started */
1086 fabian 1.2 dcc[i].sock = getsock(SOCK_STRONGCONN);
1087 fabian 1.31 if (dcc[i].sock < 0 ||
1088 drummer 1.36 open_telnet_raw(dcc[i].sock, dcc[i].addr,
1089 fabian 1.2 dcc[i].port) < 0)
1090     failed_link(i);
1091     }
1092    
1093 segfault 1.1 static void failed_tandem_relay(int idx)
1094     {
1095     int uidx = (-1), i;
1096    
1097     for (i = 0; i < dcc_total; i++)
1098     if ((dcc[i].type == &DCC_PRE_RELAY) &&
1099     (dcc[i].u.relay->sock == dcc[idx].sock))
1100     uidx = i;
1101     if (uidx < 0) {
1102 ite 1.38 putlog(LOG_MISC, "*", "%s %d -> %d", _("Cant find user for relay!"),
1103 segfault 1.1 dcc[idx].sock, dcc[idx].u.relay->sock);
1104     killsock(dcc[idx].sock);
1105     lostdcc(idx);
1106     return;
1107     }
1108     if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
1109     struct chat_info *ci = dcc[uidx].u.relay->chat;
1110    
1111 ite 1.38 dprintf(uidx, "%s %s.\n", _("Could not link to"), dcc[idx].nick);
1112 fabian 1.25 dcc[uidx].status = dcc[uidx].u.relay->old_status;
1113 tothwolf 1.41 free(dcc[uidx].u.relay);
1114 segfault 1.1 dcc[uidx].u.chat = ci;
1115     dcc[uidx].type = &DCC_CHAT;
1116     killsock(dcc[idx].sock);
1117     lostdcc(idx);
1118     return;
1119     }
1120     killsock(dcc[idx].sock);
1121     dcc[idx].sock = getsock(SOCK_STRONGCONN);
1122     dcc[uidx].u.relay->sock = dcc[idx].sock;
1123     dcc[idx].port++;
1124     dcc[idx].timeval = now;
1125 fabian 1.31 if (dcc[idx].sock < 0 ||
1126 drummer 1.36 open_telnet_raw(dcc[idx].sock, dcc[idx].addr[0] ?
1127     dcc[idx].addr :
1128 fabian 1.2 dcc[idx].host, dcc[idx].port) < 0)
1129 segfault 1.1 failed_tandem_relay(idx);
1130     }
1131    
1132 fabian 1.2
1133     static void tandem_relay_resolve_failure(int);
1134     static void tandem_relay_resolve_success(int);
1135    
1136 fabian 1.18 /* Relay to another tandembot
1137     */
1138 fabian 1.14 void tandem_relay(int idx, char *nick, register int i)
1139 segfault 1.1 {
1140     struct userrec *u;
1141     struct bot_addr *bi;
1142 fabian 1.2 struct chat_info *ci;
1143 segfault 1.1
1144     u = get_user_by_handle(userlist, nick);
1145     if (!u || !(u->flags & USER_BOT)) {
1146 ite 1.38 dprintf(idx, "%s %s\n", nick, _("is not a known bot."));
1147 segfault 1.1 return;
1148     }
1149 tothwolf 1.45 if (!strcasecmp(nick, botnetnick)) {
1150 ite 1.38 dprintf(idx, "%s\n", _("Relay to myself? What on EARTH would be the point?!"));
1151 segfault 1.1 return;
1152     }
1153 fabian 1.18 /* Address to connect to is in 'info' */
1154 segfault 1.1 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
1155 guppy 1.34 if (!bi || !strlen(bi->address) || !bi->relay_port || (bi->relay_port <= 0)) {
1156 ite 1.38 dprintf(idx, _("Invalid telnet address:port stored for '%s'.\n"), nick);
1157     dprintf(idx, _("Use: .chaddr %s <address>:<port#>[/<relay-port#>]\n"),
1158     nick);
1159 segfault 1.1
1160     return;
1161     }
1162 fabian 1.25 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
1163     if (i < 0) {
1164 ite 1.38 dprintf(idx, _("Sorry, too many DCC connections.\n"));
1165 segfault 1.1 return;
1166     }
1167    
1168 fabian 1.31 dcc[i].sock = getsock(SOCK_STRONGCONN | SOCK_VIRTUAL);
1169     if (dcc[i].sock < 0) {
1170     lostdcc(i);
1171 ite 1.38 dprintf(idx, _("No free sockets available.\n"));
1172 fabian 1.31 return;
1173     }
1174    
1175 segfault 1.1 dcc[i].port = bi->relay_port;
1176 drummer 1.36 dcc[i].addr[0] = '\0';
1177 segfault 1.1 strcpy(dcc[i].nick, nick);
1178     dcc[i].user = u;
1179     strcpy(dcc[i].host, bi->address);
1180 ite 1.38 dprintf(idx, "Connecting to %s @ %s:%d ...\n", nick,
1181 segfault 1.1 bi->address, bi->relay_port);
1182 ite 1.38 dprintf(idx, _("(Type *BYE* on a line by itself to abort.)\n"));
1183 fabian 1.2 dcc[idx].type = &DCC_PRE_RELAY;
1184 segfault 1.1 ci = dcc[idx].u.chat;
1185 tothwolf 1.42 dcc[idx].u.relay = calloc(1, sizeof(struct relay_info));
1186 segfault 1.1 dcc[idx].u.relay->chat = ci;
1187 fabian 1.25 dcc[idx].u.relay->old_status = dcc[idx].status;
1188 segfault 1.1 dcc[idx].u.relay->sock = dcc[i].sock;
1189     dcc[i].timeval = now;
1190 fabian 1.2 dcc[i].u.dns->ibuf = dcc[idx].sock;
1191 tothwolf 1.42 dcc[i].u.dns->host = calloc(1, strlen(bi->address) + 1);
1192 fabian 1.2 strcpy(dcc[i].u.dns->host, bi->address);
1193 fabian 1.29 dcc[i].u.dns->dns_success = tandem_relay_resolve_success;
1194     dcc[i].u.dns->dns_failure = tandem_relay_resolve_failure;
1195 fabian 1.2 dcc[i].u.dns->dns_type = RES_IPBYHOST;
1196 fabian 1.4 dcc[i].u.dns->type = &DCC_FORK_RELAY;
1197 fabian 1.13 dcc_dnsipbyhost(bi->address);
1198 fabian 1.2 }
1199    
1200     static void tandem_relay_resolve_failure(int idx)
1201     {
1202     struct chat_info *ci;
1203 fabian 1.14 register int uidx = (-1), i;
1204 fabian 1.2
1205     for (i = 0; i < dcc_total; i++)
1206     if ((dcc[i].type == &DCC_PRE_RELAY) &&
1207     (dcc[i].u.relay->sock == dcc[idx].sock)) {
1208     uidx = i;
1209     break;
1210     }
1211     if (uidx < 0) {
1212 ite 1.38 putlog(LOG_MISC, "*", _("Cant find user for relay! %d -> %d"),
1213 fabian 1.2 dcc[idx].sock, dcc[idx].u.relay->sock);
1214     killsock(dcc[idx].sock);
1215     lostdcc(idx);
1216     return;
1217     }
1218     ci = dcc[uidx].u.relay->chat;
1219 ite 1.38 dprintf(uidx, _("Could not link to %s.\n"), dcc[idx].nick);
1220 fabian 1.25 dcc[uidx].status = dcc[uidx].u.relay->old_status;
1221 tothwolf 1.41 free(dcc[uidx].u.relay);
1222 fabian 1.2 dcc[uidx].u.chat = ci;
1223     dcc[uidx].type = &DCC_CHAT;
1224     killsock(dcc[idx].sock);
1225     lostdcc(idx);
1226     }
1227    
1228     static void tandem_relay_resolve_success(int i)
1229     {
1230     int sock = dcc[i].u.dns->ibuf;
1231    
1232 drummer 1.36 strcpy(dcc[i].addr, dcc[i].u.dns->host);
1233 fabian 1.2 changeover_dcc(i, &DCC_FORK_RELAY, sizeof(struct relay_info));
1234 tothwolf 1.42 dcc[i].u.relay->chat = calloc(1, sizeof(struct chat_info));
1235 fabian 1.2
1236     dcc[i].u.relay->sock = sock;
1237     dcc[i].u.relay->port = dcc[i].port;
1238     dcc[i].u.relay->chat->away = NULL;
1239     dcc[i].u.relay->chat->msgs_per_sec = 0;
1240     dcc[i].u.relay->chat->con_flags = 0;
1241     dcc[i].u.relay->chat->buffer = NULL;
1242     dcc[i].u.relay->chat->max_line = 0;
1243     dcc[i].u.relay->chat->line_count = 0;
1244     dcc[i].u.relay->chat->current_lines = 0;
1245     dcc[i].timeval = now;
1246 drummer 1.36 if (open_telnet_raw(dcc[i].sock, dcc[i].addr,
1247 fabian 1.2 dcc[i].port) < 0)
1248 segfault 1.1 failed_tandem_relay(i);
1249     }
1250    
1251 fabian 1.18 /* Input from user before connect is ready
1252     */
1253 fabian 1.14 static void pre_relay(int idx, char *buf, register int i)
1254 segfault 1.1 {
1255 fabian 1.14 register int tidx = (-1);
1256 segfault 1.1
1257     for (i = 0; i < dcc_total; i++)
1258     if ((dcc[i].type == &DCC_FORK_RELAY) &&
1259 fabian 1.2 (dcc[i].u.relay->sock == dcc[idx].sock)) {
1260 segfault 1.1 tidx = i;
1261 fabian 1.2 break;
1262     }
1263     if (tidx < 0) {
1264 fabian 1.25 /* Now try to find it among the DNSWAIT sockets instead. */
1265 fabian 1.2 for (i = 0; i < dcc_total; i++)
1266     if ((dcc[i].type == &DCC_DNSWAIT) &&
1267     (dcc[i].sock == dcc[idx].u.relay->sock)) {
1268     tidx = i;
1269     break;
1270     }
1271     }
1272 segfault 1.1 if (tidx < 0) {
1273 ite 1.38 putlog(LOG_MISC, "*", _("Cant find user for relay! %d -> %d"),
1274 fabian 1.20 dcc[idx].sock, dcc[idx].u.relay->sock);
1275     killsock(dcc[idx].sock);
1276     lostdcc(idx);
1277 segfault 1.1 return;
1278     }
1279 tothwolf 1.45 if (!strcasecmp(buf, "*bye*")) {
1280 fabian 1.18 /* Disconnect */
1281 segfault 1.1 struct chat_info *ci = dcc[idx].u.relay->chat;
1282    
1283 ite 1.38 dprintf(idx, _("Aborting relay attempt to %s.\n"), dcc[tidx].nick);
1284     dprintf(idx, _("You are now back on %s.\n\n"), botnetnick);
1285     putlog(LOG_MISC, "*", _("Relay aborted: %s -> %s"), dcc[idx].nick,
1286 segfault 1.1 dcc[tidx].nick);
1287 fabian 1.2 dcc[idx].status = dcc[idx].u.relay->old_status;
1288 tothwolf 1.41 free(dcc[idx].u.relay);
1289 segfault 1.1 dcc[idx].u.chat = ci;
1290     dcc[idx].type = &DCC_CHAT;
1291     killsock(dcc[tidx].sock);
1292     lostdcc(tidx);
1293     return;
1294     }
1295     }
1296    
1297 fabian 1.18 /* User disconnected before her relay had finished connecting
1298     */
1299 segfault 1.1 static void failed_pre_relay(int idx)
1300     {
1301 fabian 1.14 register int tidx = (-1), i;
1302 segfault 1.1
1303     for (i = 0; i < dcc_total; i++)
1304     if ((dcc[i].type == &DCC_FORK_RELAY) &&
1305 fabian 1.2 (dcc[i].u.relay->sock == dcc[idx].sock)) {
1306 segfault 1.1 tidx = i;
1307 fabian 1.2 break;
1308     }
1309     if (tidx < 0) {
1310 fabian 1.25 /* Now try to find it among the DNSWAIT sockets instead. */
1311 fabian 1.2 for (i = 0; i < dcc_total; i++)
1312     if ((dcc[i].type == &DCC_DNSWAIT) &&
1313     (dcc[i].sock == dcc[idx].u.relay->sock)) {
1314     tidx = i;
1315     break;
1316     }
1317     }
1318 segfault 1.1 if (tidx < 0) {
1319 ite 1.38 putlog(LOG_MISC, "*", _("Cant find user for relay! %d -> %d"),
1320 fabian 1.2 dcc[idx].sock, dcc[idx].u.relay->sock);
1321     killsock(dcc[idx].sock);
1322     lostdcc(idx);
1323 segfault 1.1 return;
1324     }
1325 ite 1.38 putlog(LOG_MISC, "*", _("Lost dcc connection to [%s]%s/%d"), dcc[idx].nick,
1326 segfault 1.1 dcc[idx].host, dcc[idx].port);
1327 ite 1.38 putlog(LOG_MISC, "*", _("(Dropping relay attempt to %s)"), dcc[tidx].nick);
1328 segfault 1.1 if ((dcc[tidx].sock != STDOUT) || backgrd) {
1329     if (idx > tidx) {
1330     int t = tidx;
1331    
1332     tidx = idx;
1333     idx = t;
1334     }
1335     killsock(dcc[tidx].sock);
1336     lostdcc(tidx);
1337     } else {
1338 fabian 1.23 fatal("Lost my terminal?!", 0);
1339 segfault 1.1 }
1340     killsock(dcc[idx].sock);
1341     lostdcc(idx);
1342     }
1343    
1344 fabian 1.14 static void cont_tandem_relay(int idx, char *buf, register int i)
1345 segfault 1.1 {
1346 fabian 1.14 register int uidx = (-1);
1347 segfault 1.1 struct relay_info *ri;
1348    
1349     for (i = 0; i < dcc_total; i++)
1350     if ((dcc[i].type == &DCC_PRE_RELAY) &&
1351     (dcc[i].u.relay->sock == dcc[idx].sock))
1352     uidx = i;
1353     if (uidx < 0) {
1354 ite 1.38 putlog(LOG_MISC, "*", "%s %d -> %d", _("Cant find user for relay!"),
1355 segfault 1.1 dcc[i].sock, dcc[i].u.relay->sock);
1356     killsock(dcc[i].sock);
1357     lostdcc(i);
1358     return;
1359     }
1360     dcc[idx].type = &DCC_RELAY;
1361     dcc[idx].u.relay->sock = dcc[uidx].sock;
1362     dcc[uidx].u.relay->sock = dcc[idx].sock;
1363 ite 1.38 dprintf(uidx, "%s %s ...\n", _("Success!\n\nNOW CONNECTED TO RELAY BOT"), dcc[idx].nick);
1364     dprintf(uidx, "%s\n\n", _("(You can type *BYE* to prematurely close the connection.)"));
1365     putlog(LOG_MISC, "*", "%s %s -> %s", _("Relay link:"),
1366 segfault 1.1 dcc[uidx].nick, dcc[idx].nick);
1367     ri = dcc[uidx].u.relay; /* YEAH */
1368     dcc[uidx].type = &DCC_CHAT;
1369     dcc[uidx].u.chat = ri->chat;
1370     if (dcc[uidx].u.chat->channel >= 0) {
1371     chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
1372 ite 1.38 dcc[uidx].nick, _("left the party line."));
1373 segfault 1.1 if (dcc[uidx].u.chat->channel < 100000)
1374     botnet_send_part_idx(uidx, NULL);
1375     check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
1376     dcc[uidx].u.chat->channel);
1377     }
1378     check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
1379     dcc[uidx].type = &DCC_RELAYING;
1380     dcc[uidx].u.relay = ri;
1381     }
1382    
1383     static void eof_dcc_relay(int idx)
1384     {
1385 fabian 1.14 register int j;
1386 segfault 1.1 struct chat_info *ci;
1387    
1388 fabian 1.25 for (j = 0; j < dcc_total; j++)
1389     if (dcc[j].sock == dcc[idx].u.relay->sock)
1390     break;
1391     if (j == dcc_total) {
1392     killsock(dcc[idx].sock);
1393     lostdcc(idx);
1394     return;
1395     }
1396     dcc[j].status = dcc[j].u.relay->old_status;
1397     /* In case echo was off, turn it back on (send IAC WON'T ECHO): */
1398 segfault 1.1 if (dcc[j].status & STAT_TELNET)
1399 fabian 1.26 dprintf(j, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
1400 ite 1.38 putlog(LOG_MISC, "*", "%s: %s -> %s", _("Ended relay link"), dcc[j].nick,
1401 segfault 1.1 dcc[idx].nick);
1402 ite 1.38 dprintf(j, "\n\n*** %s %s\n", _("RELAY CONNECTION DROPPED.\nYou are now back on"), botnetnick);
1403 segfault 1.1 ci = dcc[j].u.relay->chat;
1404 tothwolf 1.41 free(dcc[j].u.relay);
1405 segfault 1.1 dcc[j].u.chat = ci;
1406     dcc[j].type = &DCC_CHAT;
1407     if (dcc[j].u.chat->channel >= 0) {
1408     chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
1409 ite 1.38 dcc[j].nick, _("rejoined the party line."));
1410 segfault 1.1 if (dcc[j].u.chat->channel < 100000)
1411     botnet_send_join_idx(j, -1);
1412     }
1413     check_tcl_chon(dcc[j].nick, dcc[j].sock);
1414     check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
1415 ite 1.51 geticon(dcc[j].user), dcc[j].sock, dcc[j].host);
1416 segfault 1.1 killsock(dcc[idx].sock);
1417     lostdcc(idx);
1418     }
1419    
1420     static void eof_dcc_relaying(int idx)
1421     {
1422 fabian 1.14 register int j, x = dcc[idx].u.relay->sock;
1423 segfault 1.1
1424 ite 1.38 putlog(LOG_MISC, "*", "%s [%s]%s/%d", _("Lost dcc connection to"), dcc[idx].nick,
1425 segfault 1.1 dcc[idx].host, dcc[idx].port);
1426     killsock(dcc[idx].sock);
1427     lostdcc(idx);
1428 fabian 1.14 for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY); j++);
1429 ite 1.38 putlog(LOG_MISC, "*", "(%s %s)", _("Dropping relay link to"), dcc[j].nick);
1430 segfault 1.1 killsock(dcc[j].sock);
1431 fabian 1.18 lostdcc(j); /* Drop connection to the bot */
1432 segfault 1.1 }
1433    
1434     static void dcc_relay(int idx, char *buf, int j)
1435     {
1436     unsigned char *p = (unsigned char *) buf;
1437     int mark;
1438    
1439 fabian 1.26 for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock ||
1440     dcc[j].type != &DCC_RELAYING; j++);
1441     /* If redirecting to a non-telnet user, swallow telnet codes and
1442     escape sequences. */
1443 segfault 1.1 if (!(dcc[j].status & STAT_TELNET)) {
1444     while (*p != 0) {
1445 fabian 1.26 while (*p != 255 && (*p != '\033' || *(p + 1) != '[') && *p != '\r' && *p)
1446     p++; /* Search for IAC, escape sequences and CR. */
1447 segfault 1.1 if (*p == 255) {
1448     mark = 2;
1449     if (!*(p + 1))
1450 fabian 1.18 mark = 1; /* Bogus */
1451 segfault 1.1 if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
1452     mark = 3;
1453     if (!*(p + 2))
1454 fabian 1.18 mark = 2; /* Bogus */
1455 segfault 1.1 }
1456     strcpy((char *) p, (char *) (p + mark));
1457 fabian 1.26 } else if (*p == '\033') {
1458     unsigned char *e;
1459    
1460     /* Search for the end of the escape sequence. */
1461     for (e = p + 2; *e != 'm' && *e; e++)
1462     ;
1463     strcpy((char *) p, (char *) (e + 1));
1464     } else if (*p == '\r')
1465     strcpy((char *) p, (char *) (p + 1));
1466 segfault 1.1 }
1467     if (!buf[0])
1468     dprintf(-dcc[idx].u.relay->sock, " \n");
1469     else
1470     dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1471     return;
1472     }
1473 fabian 1.18 /* Telnet user */
1474 segfault 1.1 if (!buf[0])
1475     dprintf(-dcc[idx].u.relay->sock, " \r\n");
1476     else
1477     dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
1478     }
1479    
1480     static void dcc_relaying(int idx, char *buf, int j)
1481     {
1482     struct chat_info *ci;
1483    
1484 tothwolf 1.45 if (strcasecmp(buf, "*bye*")) {
1485 segfault 1.1 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1486     return;
1487     }
1488     for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1489     (dcc[j].type != &DCC_RELAY); j++);
1490 fabian 1.25 dcc[idx].status = dcc[idx].u.relay->old_status;
1491     /* In case echo was off, turn it back on (send IAC WON'T ECHO): */
1492 segfault 1.1 if (dcc[idx].status & STAT_TELNET)
1493 fabian 1.26 dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
1494 ite 1.38 dprintf(idx, "\n(%s %s.)\n", _("Breaking connection to"), dcc[j].nick);
1495     dprintf(idx, "%s %s.\n\n", _("You are now back on"), botnetnick);
1496     putlog(LOG_MISC, "*", "%s: %s -> %s", _("Relay broken"),
1497 segfault 1.1 dcc[idx].nick, dcc[j].nick);
1498     if (dcc[idx].u.relay->chat->channel >= 0) {
1499     chanout_but(-1, dcc[idx].u.relay->chat->channel,
1500     "*** %s joined the party line.\n", dcc[idx].nick);
1501     if (dcc[idx].u.relay->chat->channel < 100000)
1502     botnet_send_join_idx(idx, -1);
1503     }
1504     ci = dcc[idx].u.relay->chat;
1505 tothwolf 1.41 free(dcc[idx].u.relay);
1506 segfault 1.1 dcc[idx].u.chat = ci;
1507     dcc[idx].type = &DCC_CHAT;
1508     check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1509 stdarg 1.39 if (dcc[idx].u.chat->channel >= 0) {
1510 segfault 1.1 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1511 ite 1.51 geticon(dcc[idx].user), dcc[idx].sock, dcc[idx].host);
1512 stdarg 1.39 }
1513 segfault 1.1 killsock(dcc[j].sock);
1514     lostdcc(j);
1515     }
1516    
1517     static void display_relay(int i, char *other)
1518     {
1519     sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
1520     }
1521    
1522     static void display_relaying(int i, char *other)
1523     {
1524     sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
1525     }
1526    
1527     static void display_tandem_relay(int i, char *other)
1528     {
1529     strcpy(other, "other rela");
1530     }
1531    
1532     static void display_pre_relay(int i, char *other)
1533     {
1534     strcpy(other, "other >rly");
1535     }
1536    
1537     static void kill_relay(int idx, void *x)
1538     {
1539     register struct relay_info *p = (struct relay_info *) x;
1540    
1541     if (p->chat)
1542     DCC_CHAT.kill(idx, p->chat);
1543 tothwolf 1.41 free(p);
1544 segfault 1.1 }
1545    
1546     struct dcc_table DCC_RELAY =
1547     {
1548     "RELAY",
1549 fabian 1.18 0, /* Flags */
1550 segfault 1.1 eof_dcc_relay,
1551     dcc_relay,
1552 fabian 1.18 NULL,
1553     NULL,
1554 segfault 1.1 display_relay,
1555     kill_relay,
1556 fabian 1.18 NULL
1557 segfault 1.1 };
1558    
1559     static void out_relay(int idx, char *buf, void *x)
1560     {
1561     register struct relay_info *p = (struct relay_info *) x;
1562    
1563     if (p && p->chat)
1564     DCC_CHAT.output(idx, buf, p->chat);
1565     else
1566     tputs(dcc[idx].sock, buf, strlen(buf));
1567     }
1568    
1569     struct dcc_table DCC_RELAYING =
1570     {
1571     "RELAYING",
1572 fabian 1.18 0, /* Flags */
1573 segfault 1.1 eof_dcc_relaying,
1574     dcc_relaying,
1575 fabian 1.18 NULL,
1576     NULL,
1577 segfault 1.1 display_relaying,
1578     kill_relay,
1579     out_relay
1580     };
1581    
1582     struct dcc_table DCC_FORK_RELAY =
1583     {
1584     "FORK_RELAY",
1585 fabian 1.18 0, /* Flags */
1586 segfault 1.1 failed_tandem_relay,
1587     cont_tandem_relay,
1588     &connect_timeout,
1589     failed_tandem_relay,
1590     display_tandem_relay,
1591     kill_relay,
1592 fabian 1.18 NULL
1593 segfault 1.1 };
1594    
1595     struct dcc_table DCC_PRE_RELAY =
1596     {
1597     "PRE_RELAY",
1598 fabian 1.18 0, /* Flags */
1599 segfault 1.1 failed_pre_relay,
1600     pre_relay,
1601 fabian 1.18 NULL,
1602     NULL,
1603 segfault 1.1 display_pre_relay,
1604     kill_relay,
1605 fabian 1.18 NULL
1606 segfault 1.1 };
1607    
1608 fabian 1.18 /* Once a minute, send 'ping' to each bot -- no exceptions
1609     */
1610 segfault 1.1 void check_botnet_pings()
1611     {
1612     int i;
1613 fabian 1.19 int bots, users;
1614     tand_t *bot;
1615 segfault 1.1
1616     for (i = 0; i < dcc_total; i++)
1617     if (dcc[i].type == &DCC_BOT)
1618     if (dcc[i].status & STAT_PINGED) {
1619     char s[1024];
1620    
1621 ite 1.38 putlog(LOG_BOTS, "*", "%s: %s", _("Ping timeout"), dcc[i].nick);
1622 fabian 1.19 bot = findbot(dcc[i].nick);
1623     bots = bots_in_subtree(bot);
1624     users = users_in_subtree(bot);
1625 ite 1.38 simple_sprintf(s, "%s: %s (lost %d bot%s and %d user%s)", _("Ping timeout"),
1626 fabian 1.19 dcc[i].nick, bots, (bots != 1) ? "s" : "",
1627     users, (users != 1) ? "s" : "");
1628 segfault 1.1 chatout("*** %s\n", s);
1629     botnet_send_unlinked(i, dcc[i].nick, s);
1630     killsock(dcc[i].sock);
1631     lostdcc(i);
1632     }
1633     for (i = 0; i < dcc_total; i++)
1634     if (dcc[i].type == &DCC_BOT) {
1635     botnet_send_ping(i);
1636     dcc[i].status |= STAT_PINGED;
1637     }
1638     for (i = 0; i < dcc_total; i++)
1639     if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
1640     tand_t *bot, *via = findbot(dcc[i].nick);
1641    
1642     for (bot = tandbot; bot; bot = bot->next) {
1643     if ((via == bot->via) && (bot != via)) {
1644 fabian 1.18 /* Not leaflike behavior */
1645 segfault 1.1 if (dcc[i].status & STAT_WARNED) {
1646     char s[1024];
1647    
1648 ite 1.38 putlog(LOG_BOTS, "*", "%s %s (%s).", _("Disconnected from:"),
1649     dcc[i].nick, _("unleaflike behavior"));
1650     dprintf(i, "bye %s\n", _("unleaflike behavior"));
1651 fabian 1.19 bot = findbot(dcc[i].nick);
1652     bots = bots_in_subtree(bot);
1653     users = users_in_subtree(bot);
1654     simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s)",
1655 ite 1.38 _("Disconnected from:"), dcc[i].nick, _("unleaflike behavior"),
1656 fabian 1.19 bots, (bots != 1) ? "s" : "", users, (users != 1) ?
1657     "s" : "");
1658 segfault 1.1 chatout("*** %s\n", s);
1659     botnet_send_unlinked(i, dcc[i].nick, s);
1660     killsock(dcc[i].sock);
1661     lostdcc(i);
1662     } else {
1663     botnet_send_reject(i, botnetnick, NULL, bot->bot,
1664     NULL, NULL);
1665     dcc[i].status |= STAT_WARNED;
1666     }
1667     } else
1668     dcc[i].status &= ~STAT_WARNED;
1669     }
1670     }
1671     }
1672    
1673     void zapfbot(int idx)
1674     {
1675     char s[1024];
1676 fabian 1.19 int bots, users;
1677     tand_t *bot;
1678 segfault 1.1
1679 fabian 1.19 bot = findbot(dcc[idx].nick);
1680     bots = bots_in_subtree(bot);
1681     users = users_in_subtree(bot);
1682 ite 1.38 simple_sprintf(s, "%s: %s (lost %d bot%s and %d user%s)", _("Dropped bot"),
1683 fabian 1.19 dcc[idx].nick, bots, (bots != 1) ? "s" : "", users,
1684     (users != 1) ? "s" : "");
1685 segfault 1.1 chatout("*** %s\n", s);
1686     botnet_send_unlinked(idx, dcc[idx].nick, s);
1687     killsock(dcc[idx].sock);
1688 fabian 1.12 lostdcc(idx);
1689 segfault 1.1 }
1690    
1691     void restart_chons()
1692     {
1693     int i;
1694    
1695 fabian 1.18 /* Dump party line members */
1696 segfault 1.1 for (i = 0; i < dcc_total; i++) {
1697     if (dcc[i].type == &DCC_CHAT) {
1698     check_tcl_chon(dcc[i].nick, dcc[i].sock);
1699     check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
1700 ite 1.51 geticon(dcc[i].user), dcc[i].sock, dcc[i].host);
1701 segfault 1.1 }
1702     }
1703     for (i = 0; i < parties; i++) {
1704     check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
1705     party[i].flag, party[i].sock, party[i].from);
1706     }
1707     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23