6
6
* memory management for dcc structures
7
7
* timeout checking for dcc connections
9
* $Id: dccutil.c,v 1.34 2002/01/02 03:46:35 guppy Exp $
9
* $Id: dccutil.c,v 1.50 2004/05/26 00:20:19 wcc Exp $
12
12
* Copyright (C) 1997 Robey Pointer
13
* Copyright (C) 1999, 2000, 2001, 2002 Eggheads Development Team
13
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Eggheads Development Team
15
15
* This program is free software; you can redistribute it and/or
16
16
* modify it under the terms of the GNU General Public License
34
34
#include "modules.h"
35
35
#include "tandem.h"
37
extern struct dcc_t *dcc;
38
extern int dcc_total, max_dcc, dcc_flood_thr, backgrd, MAXSOCKS;
39
extern char botnetnick[], spaces[], version[];
41
extern sock_list *socklist;
42
extern Tcl_Interp *interp;
37
extern struct dcc_t *dcc;
38
extern int dcc_total, max_dcc, dcc_flood_thr, backgrd, copy_to_tmp, MAXSOCKS;
39
extern char botnetnick[], version[];
41
extern sock_list *socklist;
42
extern Tcl_Interp *interp;
44
char motdfile[121] = "text/motd"; /* File where the motd is stored */
45
int connect_timeout = 15; /* How long to wait before a telnet
46
connection times out */
44
char motdfile[121] = "text/motd"; /* File where the motd is stored */
45
int connect_timeout = 15; /* How long to wait before a telnet
46
* connection times out */
48
48
int reserved_port_min = 0;
49
49
int reserved_port_max = 0;
62
62
MAXSOCKS = max_dcc + 10;
64
64
socklist = (sock_list *) nrealloc((void *) socklist,
65
sizeof(sock_list) * MAXSOCKS);
65
sizeof(sock_list) * MAXSOCKS);
67
67
socklist = (sock_list *) nmalloc(sizeof(sock_list) * MAXSOCKS);
68
68
for (; osock < MAXSOCKS; osock++)
110
110
idx = EGG_VARARGS_START(int, arg1, va);
111
111
format = va_arg(va, char *);
112
113
egg_vsnprintf(buf, 1023, format, va);
114
115
/* We can not use the return value vsnprintf() to determine where
155
156
char *p = add_cr(buf);
157
158
tputs(dcc[idx].sock, p, strlen(p));
158
} else if (dcc[idx].type && dcc[idx].type->output) {
159
} else if (dcc[idx].type && dcc[idx].type->output)
159
160
dcc[idx].type->output(idx, buf, dcc[idx].u.other);
161
162
tputs(dcc[idx].sock, buf, len);
196
198
x = EGG_VARARGS_START(int, arg1, va);
197
199
chan = va_arg(va, int);
198
200
format = va_arg(va, char *);
199
202
egg_vsnprintf(s, 511, format, va);
213
216
void dcc_chatter(int idx)
216
struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
219
struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
218
221
get_user_flagrec(dcc[idx].user, &fr, NULL);
224
227
check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
225
228
/* Still there? */
226
229
if ((idx >= dcc_total) || (dcc[idx].sock != j))
228
231
/* Tcl script may have taken control */
229
232
if (dcc[idx].type == &DCC_CHAT) {
230
233
if (!strcmp(dcc[idx].u.chat->con_chan, "***"))
235
238
* so dont bother sending them
239
242
dcc[idx].u.chat->channel = i;
240
if (dcc[idx].u.chat->channel >= 0) {
241
if (dcc[idx].u.chat->channel < 100000) {
242
botnet_send_join_idx(idx, -1);
243
if ((dcc[idx].u.chat->channel >= 0) &&
244
(dcc[idx].u.chat->channel < GLOBAL_CHANS))
245
botnet_send_join_idx(idx, -1);
245
246
check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
246
geticon(idx), dcc[idx].sock, dcc[idx].host);
247
geticon(idx), dcc[idx].sock, dcc[idx].host);
248
249
/* But *do* bother with sending it locally */
249
250
if (!dcc[idx].u.chat->channel) {
250
251
chanout_but(-1, 0, "*** %s joined the party line.\n", dcc[idx].nick);
251
252
} else if (dcc[idx].u.chat->channel > 0) {
252
253
chanout_but(-1, dcc[idx].u.chat->channel,
253
"*** %s joined the channel.\n", dcc[idx].nick);
254
"*** %s joined the channel.\n", dcc[idx].nick);
259
/* Closes an open FD for transfer sockets. */
260
void killtransfer(int n)
264
if (dcc[n].type->flags & DCT_FILETRAN) {
265
if (dcc[n].u.xfer->f) {
266
fclose(dcc[n].u.xfer->f);
267
dcc[n].u.xfer->f = NULL;
269
if (dcc[n].u.xfer->filename && copy_to_tmp) {
270
for (i = 0; i < dcc_total; i++) {
271
if ((i != n) && (dcc[i].type->flags & DCT_FILETRAN) &&
272
(dcc[i].u.xfer->filename) &&
273
(!strcmp(dcc[i].u.xfer->filename, dcc[n].u.xfer->filename))) {
279
unlink(dcc[n].u.xfer->filename);
261
287
void lostdcc(int n)
289
/* Make sure it's a valid dcc index. */
290
if (n < 0 || n >= max_dcc)
263
293
if (dcc[n].type && dcc[n].type->kill)
264
294
dcc[n].type->kill(n, dcc[n].u.other);
265
295
else if (dcc[n].u.other)
266
296
nfree(dcc[n].u.other);
267
297
egg_bzero(&dcc[n], sizeof(struct dcc_t));
270
300
dcc[n].type = &DCC_LOST;
287
317
if (n < dcc_total)
288
318
egg_memcpy(&dcc[n], &dcc[dcc_total], sizeof(struct dcc_t));
290
egg_bzero(&dcc[n], sizeof(struct dcc_t)); /* drummer */
320
egg_bzero(&dcc[n], sizeof(struct dcc_t)); /* drummer */
293
323
/* Clean up sockets that were just left for dead.
312
342
void tell_dcc(int zidx)
317
spaces[HANDLEN - 9] = 0;
318
dprintf(zidx, "SOCK ADDR PORT NICK %s HOST TYPE\n"
320
dprintf(zidx, "---- -------- ----- ---------%s ----------------- ----\n"
322
spaces[HANDLEN - 9] = ' ';
349
/* calculate max nicklen */
351
for (i = 0; i < dcc_total; i++) {
352
if (strlen(dcc[i].nick) > nicklen)
353
nicklen = strlen(dcc[i].nick);
358
egg_snprintf(format, sizeof format, "%%-4s %%-8s %%-5s %%-%us %%-17s %%s\n",
360
dprintf(zidx, format, "SOCK", "ADDR", "PORT", "NICK", "HOST", "TYPE");
361
dprintf(zidx, format, "----", "--------", "-----", "---------",
362
"-----------------", "----");
364
egg_snprintf(format, sizeof format, "%%-4d %%08X %%5d %%-%us %%-17s %%s\n",
323
366
/* Show server */
324
367
for (i = 0; i < dcc_total; i++) {
325
368
j = strlen(dcc[i].host);
333
376
sprintf(other, "?:%lX !! ERROR !!", (long) dcc[i].type);
336
k = HANDLEN - strlen(dcc[i].nick);
338
dprintf(zidx, "%-4d %08X %5d %s%s %-17s %s\n", dcc[i].sock, dcc[i].addr,
339
dcc[i].port, dcc[i].nick, spaces, dcc[i].host + j, other);
379
dprintf(zidx, format, dcc[i].sock, dcc[i].addr, dcc[i].port, dcc[i].nick,
380
dcc[i].host + j, other);
352
392
if (dcc[idx].u.chat->channel >= 0) {
353
393
chanout_but(-1, dcc[idx].u.chat->channel,
354
"*** %s is no longer away.\n", dcc[idx].nick);
355
if (dcc[idx].u.chat->channel < 100000) {
394
"*** %s is no longer away.\n", dcc[idx].nick);
395
if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
356
396
botnet_send_away(-1, botnetnick, dcc[idx].sock, NULL, idx);
378
418
strcpy(dcc[idx].u.chat->away, s);
379
419
if (dcc[idx].u.chat->channel >= 0) {
380
420
chanout_but(-1, dcc[idx].u.chat->channel,
381
"*** %s is now away: %s\n", dcc[idx].nick, s);
382
if (dcc[idx].u.chat->channel < 100000) {
421
"*** %s is now away: %s\n", dcc[idx].nick, s);
422
if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
383
423
botnet_send_away(-1, botnetnick, dcc[idx].sock, s, idx);
492
533
dprintf(idx, "*** FLOOD: %s.\n", IRC_GOODBYE);
493
534
/* Evil assumption here that flags&DCT_CHAT implies chat type */
494
if ((dcc[idx].type->flags & DCT_CHAT) && chat &&
495
(chat->channel >= 0)) {
535
if ((dcc[idx].type->flags & DCT_CHAT) && chat && (chat->channel >= 0)) {
498
egg_snprintf(x, sizeof x, DCC_FLOODBOOT, dcc[idx].nick);
499
chanout_but(idx, chat->channel, "*** %s", x);
500
if (chat->channel < 100000)
501
botnet_send_part_idx(idx, x);
538
egg_snprintf(x, sizeof x, DCC_FLOODBOOT, dcc[idx].nick);
539
chanout_but(idx, chat->channel, "*** %s", x);
540
if (chat->channel < GLOBAL_CHANS)
541
botnet_send_part_idx(idx, x);
503
543
check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
504
544
if ((dcc[idx].sock != STDOUT) || backgrd) {
505
killsock(dcc[idx].sock);
545
killsock(dcc[idx].sock);
508
dprintf(DP_STDOUT, "\n### SIMULATION RESET ###\n\n");
548
dprintf(DP_STDOUT, "\n### SIMULATION RESET ###\n\n");
511
return 1; /* <- flood */
551
return 1; /* <- flood */
526
566
/* If it's a partyliner (chatterer :) */
527
567
/* Horrible assumption that DCT_CHAT using structure uses same format
529
if ((dcc[idx].type->flags & DCT_CHAT) &&
530
(dcc[idx].u.chat->channel >= 0)) {
569
if ((dcc[idx].type->flags & DCT_CHAT) && (dcc[idx].u.chat->channel >= 0)) {
533
572
egg_snprintf(x, sizeof x, DCC_BOOTED3, by, dcc[idx].nick,
534
reason[0] ? ": " : "", reason);
573
reason[0] ? ": " : "", reason);
535
574
chanout_but(idx, dcc[idx].u.chat->channel, "*** %s.\n", x);
536
if (dcc[idx].u.chat->channel < 100000)
575
if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
537
576
botnet_send_part_idx(idx, x);
539
578
check_tcl_chof(dcc[idx].nick, dcc[idx].sock);