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

Contents of /eggdrop1.9/src/dccutil.c

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


Revision 1.15 - (show annotations) (download) (as text)
Mon Jan 17 21:59:10 2000 UTC (19 years, 9 months ago) by fabian
Branch: MAIN
Changes since 1.14: +3 -8 lines
File MIME type: text/x-chdr
resync with 1.4, 17Jan2000

1 /*
2 * dccutil.c -- handles:
3 * lots of little functions to send formatted text to
4 * varying types of connections
5 * '.who', '.whom', and '.dccstat' code
6 * memory management for dcc structures
7 * timeout checking for dcc connections
8 *
9 * dprintf'ized, 28aug1995
10 *
11 * $Id: dccutil.c,v 1.14 2000/01/01 19:34:13 fabian Exp $
12 */
13 /*
14 * Copyright (C) 1997 Robey Pointer
15 * Copyright (C) 1999 Eggheads
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 */
31
32 #include "main.h"
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include "chan.h"
36 #include "modules.h"
37 #include "tandem.h"
38
39 extern struct dcc_t *dcc;
40 extern int dcc_total, max_dcc, dcc_flood_thr, backgrd;
41 extern char botnetnick[], spaces[], version[];
42 extern time_t now;
43
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 */
47 int reserved_port = 0;
48
49 extern sock_list *socklist;
50 extern int MAXSOCKS;
51
52 void init_dcc_max()
53 {
54 int osock = MAXSOCKS;
55
56 if (max_dcc < 1)
57 max_dcc = 1;
58 if (dcc)
59 dcc = nrealloc(dcc, sizeof(struct dcc_t) * max_dcc);
60
61 else
62 dcc = nmalloc(sizeof(struct dcc_t) * max_dcc);
63
64 MAXSOCKS = max_dcc + 10;
65 if (socklist)
66 socklist = (sock_list *) nrealloc((void *) socklist,
67 sizeof(sock_list) * MAXSOCKS);
68 else
69 socklist = (sock_list *) nmalloc(sizeof(sock_list) * MAXSOCKS);
70 for (; osock < MAXSOCKS; osock++)
71 socklist[osock].flags = SOCK_UNUSED;
72 }
73
74 int expmem_dccutil()
75 {
76 int tot, i;
77
78 Context;
79 tot = sizeof(struct dcc_t) * max_dcc + sizeof(sock_list) * MAXSOCKS;
80
81 for (i = 0; i < dcc_total; i++) {
82 if (dcc[i].type && dcc[i].type->expmem)
83 tot += dcc[i].type->expmem(dcc[i].u.other);
84 }
85 return tot;
86 }
87
88 static char SBUF[1024];
89
90 /* replace \n with \r\n */
91 char *add_cr(char *buf)
92 {
93 static char WBUF[1024];
94 char *p, *q;
95
96 for (p = buf, q = WBUF; *p; p++, q++) {
97 if (*p == '\n')
98 *q++ = '\r';
99 *q = *p;
100 }
101 *q = *p;
102 return WBUF;
103 }
104
105 extern void (*qserver) (int, char *, int);
106
107 void dprintf EGG_VARARGS_DEF(int, arg1)
108 {
109 char *format;
110 int idx, len;
111
112 va_list va;
113 idx = EGG_VARARGS_START(int, arg1, va);
114 format = va_arg(va, char *);
115
116 #ifdef HAVE_VSNPRINTF
117 if ((len = vsnprintf(SBUF, 1023, format, va)) < 0)
118 SBUF[len = 1023] = 0;
119 #else
120 len = vsprintf(SBUF, format, va);
121 #endif
122 va_end(va);
123 if (idx < 0) {
124 tputs(-idx, SBUF, len);
125 } else if (idx > 0x7FF0) {
126 switch (idx) {
127 case DP_LOG:
128 putlog(LOG_MISC, "*", "%s", SBUF);
129 break;
130 case DP_STDOUT:
131 tputs(STDOUT, SBUF, len);
132 break;
133 case DP_STDERR:
134 tputs(STDERR, SBUF, len);
135 break;
136 case DP_SERVER:
137 case DP_HELP:
138 case DP_MODE:
139 case DP_MODE_NEXT:
140 case DP_SERVER_NEXT:
141 case DP_HELP_NEXT:
142 qserver(idx, SBUF, len);
143 break;
144 }
145 return;
146 } else {
147 if (len > 500) { /* truncate to fit */
148 SBUF[500] = 0;
149 strcat(SBUF, "\n");
150 len = 501;
151 }
152 if (dcc[idx].type && ((long) (dcc[idx].type->output) == 1)) {
153 char *p = add_cr(SBUF);
154
155 tputs(dcc[idx].sock, p, strlen(p));
156 } else if (dcc[idx].type && dcc[idx].type->output) {
157 dcc[idx].type->output(idx, SBUF, dcc[idx].u.other);
158 } else
159 tputs(dcc[idx].sock, SBUF, len);
160 }
161 }
162
163 void chatout EGG_VARARGS_DEF(char *, arg1)
164 {
165 int i;
166 char *format;
167 char s[601];
168
169 va_list va;
170 format = EGG_VARARGS_START(char *, arg1, va);
171
172 #ifdef HAVE_VSNPRINTF
173 if (vsnprintf(s, 511, format, va) < 0)
174 s[511] = 0;
175 #else
176 vsprintf(s, format, va);
177 #endif
178 for (i = 0; i < dcc_total; i++)
179 if (dcc[i].type == &DCC_CHAT)
180 if (dcc[i].u.chat->channel >= 0)
181 dprintf(i, "%s", s);
182 va_end(va);
183 }
184
185 /* print to all on this channel but one */
186 void chanout_but EGG_VARARGS_DEF(int, arg1)
187 {
188 int i, x, chan;
189 char *format;
190 char s[601];
191
192 va_list va;
193 x = EGG_VARARGS_START(int, arg1, va);
194 chan = va_arg(va, int);
195 format = va_arg(va, char *);
196
197 #ifdef HAVE_VSNPRINTF
198 if (vsnprintf(s, 511, format, va) < 0)
199 s[511] = 0;
200 #else
201 vsprintf(s, format, va);
202 #endif
203 for (i = 0; i < dcc_total; i++)
204 if ((dcc[i].type == &DCC_CHAT) && (i != x))
205 if (dcc[i].u.chat->channel == chan)
206 dprintf(i, "%s", s);
207 va_end(va);
208 }
209
210 void dcc_chatter(int idx)
211 {
212 int i, j;
213 struct flag_record fr =
214 {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
215
216 get_user_flagrec(dcc[idx].user, &fr, NULL);
217 dprintf(idx, "Connected to %s, running %s\n", botnetnick, version);
218 show_motd(idx);
219 dprintf(idx, "Commands start with '.' (like '.quit' or '.help')\n");
220 dprintf(idx, "Everything else goes out to the party line.\n\n");
221 i = dcc[idx].u.chat->channel;
222 dcc[idx].u.chat->channel = 234567;
223 j = dcc[idx].sock;
224 strcpy(dcc[idx].u.chat->con_chan, "***");
225 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
226 /* still there? */
227 if ((idx >= dcc_total) || (dcc[idx].sock != j))
228 return; /* nope */
229 /* tcl script may have taken control */
230 if (dcc[idx].type == &DCC_CHAT) {
231 if (!strcmp(dcc[idx].u.chat->con_chan, "***"))
232 strcpy(dcc[idx].u.chat->con_chan, "*");
233 if (dcc[idx].u.chat->channel == 234567) {
234 /* if the chat channel has already been altered it's *highly*
235 * probably join/part messages have been broadcast everywhere,
236 * so dont bother sending them */
237 if (i == -2)
238 i = 0;
239 dcc[idx].u.chat->channel = i;
240 if (dcc[idx].u.chat->channel >= 0) {
241 Context;
242 if (dcc[idx].u.chat->channel < 100000) {
243 botnet_send_join_idx(idx, -1);
244 }
245 }
246 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
247 geticon(idx), dcc[idx].sock, dcc[idx].host);
248 }
249 /* but *do* bother with sending it locally */
250 if (dcc[idx].u.chat->channel == 0) {
251 chanout_but(-1, 0, "*** %s joined the party line.\n", dcc[idx].nick);
252 } else if (dcc[idx].u.chat->channel > 0) {
253 chanout_but(-1, dcc[idx].u.chat->channel,
254 "*** %s joined the channel.\n", dcc[idx].nick);
255 }
256 }
257 }
258
259 /* Mark an entry as lost and deconstruct it's contents. It will be securely
260 * removed from the dcc list in the main loop.
261 */
262 void lostdcc(int n)
263 {
264 if (dcc[n].type && dcc[n].type->kill)
265 dcc[n].type->kill(n, dcc[n].u.other);
266 else if (dcc[n].u.other)
267 nfree(dcc[n].u.other);
268 bzero(&dcc[n], sizeof(struct dcc_t));
269
270 dcc[n].sock = (-1);
271 dcc[n].type = &DCC_LOST;
272 }
273
274 /* Remove entry from dcc list. Think twice before using this function,
275 * because it invalidates any variables that point to a specific dcc
276 * entry!
277 */
278 void removedcc(int n)
279 {
280 if (dcc[n].type && dcc[n].type->kill)
281 dcc[n].type->kill(n, dcc[n].u.other);
282 else if (dcc[n].u.other)
283 nfree(dcc[n].u.other);
284 dcc_total--;
285 if (n < dcc_total)
286 my_memcpy((char *) &dcc[n], (char *) &dcc[dcc_total],
287 sizeof(struct dcc_t));
288 else
289 bzero(&dcc[n], sizeof(struct dcc_t)); /* drummer */
290 }
291
292 /* Clean up sockets that were just left for dead.
293 */
294 void dcc_remove_lost(void)
295 {
296 int i;
297
298 Context;
299 for (i = 0; i < dcc_total; i++) {
300 if (dcc[i].type == &DCC_LOST) {
301 dcc[i].type = NULL;
302 dcc[i].sock = (-1);
303 removedcc(i);
304 i--;
305 }
306 }
307 }
308
309 /* show list of current dcc's to a dcc-chatter */
310 /* positive value: idx given -- negative value: sock given */
311 void tell_dcc(int zidx)
312 {
313 int i, j, k;
314 char other[160];
315
316 Context;
317 spaces[HANDLEN - 9] = 0;
318 dprintf(zidx, "SOCK ADDR PORT NICK %s HOST TYPE\n"
319 ,spaces);
320 dprintf(zidx, "---- -------- ----- ---------%s ----------------- ----\n"
321 ,spaces);
322 spaces[HANDLEN - 9] = ' ';
323 /* show server */
324 for (i = 0; i < dcc_total; i++) {
325 j = strlen(dcc[i].host);
326 if (j > 17)
327 j -= 17;
328 else
329 j = 0;
330 if (dcc[i].type && dcc[i].type->display)
331 dcc[i].type->display(i, other);
332 else {
333 sprintf(other, "?:%lX !! ERROR !!", (long) dcc[i].type);
334 break;
335 }
336 k = HANDLEN - strlen(dcc[i].nick);
337 spaces[k] = 0;
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);
340 spaces[k] = ' ';
341 }
342 }
343
344 /* mark someone on dcc chat as no longer away */
345 void not_away(int idx)
346 {
347 Context;
348 if (dcc[idx].u.chat->away == NULL) {
349 dprintf(idx, "You weren't away!\n");
350 return;
351 }
352 if (dcc[idx].u.chat->channel >= 0) {
353 chanout_but(-1, dcc[idx].u.chat->channel,
354 "*** %s is no longer away.\n", dcc[idx].nick);
355 Context;
356 if (dcc[idx].u.chat->channel < 100000) {
357 botnet_send_away(-1, botnetnick, dcc[idx].sock, NULL, idx);
358 }
359 }
360 dprintf(idx, "You're not away any more.\n");
361 nfree(dcc[idx].u.chat->away);
362 dcc[idx].u.chat->away = NULL;
363 check_tcl_away(botnetnick, dcc[idx].sock, NULL);
364 }
365
366 void set_away(int idx, char *s)
367 {
368 if (s == NULL) {
369 not_away(idx);
370 return;
371 }
372 if (!s[0]) {
373 not_away(idx);
374 return;
375 }
376 if (dcc[idx].u.chat->away != NULL)
377 nfree(dcc[idx].u.chat->away);
378 dcc[idx].u.chat->away = (char *) nmalloc(strlen(s) + 1);
379 strcpy(dcc[idx].u.chat->away, s);
380 if (dcc[idx].u.chat->channel >= 0) {
381 chanout_but(-1, dcc[idx].u.chat->channel,
382 "*** %s is now away: %s\n", dcc[idx].nick, s);
383 Context;
384 if (dcc[idx].u.chat->channel < 100000) {
385 botnet_send_away(-1, botnetnick, dcc[idx].sock, s, idx);
386 }
387 }
388 dprintf(idx, "You are now away.\n");
389 check_tcl_away(botnetnick, dcc[idx].sock, s);
390 }
391
392 /* this helps the memory debugging */
393 void *_get_data_ptr(int size, char *file, int line)
394 {
395 char *p;
396
397 #ifdef DEBUG_MEM
398 char x[1024];
399
400 simple_sprintf(x, "dccutil.c:%s", file);
401 p = n_malloc(size, x, line);
402 #else
403 p = nmalloc(size);
404 #endif
405 bzero(p, size);
406 return p;
407 }
408
409 /* make a password, 10-15 random letters and digits */
410 void makepass(char *s)
411 {
412 int i;
413
414 i = 10 + (random() % 6);
415 make_rand_str(s, i);
416 }
417
418 void flush_lines(int idx, struct chat_info *ci)
419 {
420 int c = ci->line_count;
421 struct msgq *p = ci->buffer, *o;
422
423 while (p && c < (ci->max_line)) {
424 ci->current_lines--;
425 tputs(dcc[idx].sock, p->msg, p->len);
426 nfree(p->msg);
427 o = p->next;
428 nfree(p);
429 p = o;
430 c++;
431 }
432 if (p != NULL) {
433 if (dcc[idx].status & STAT_TELNET)
434 tputs(dcc[idx].sock, "[More]: ", 8);
435 else
436 tputs(dcc[idx].sock, "[More]\n", 7);
437 }
438 ci->buffer = p;
439 ci->line_count = 0;
440 }
441
442 int new_dcc(struct dcc_table *type, int xtra_size)
443 {
444 int i = dcc_total;
445
446 if (dcc_total == max_dcc)
447 return -1;
448 dcc_total++;
449 bzero((char *) &dcc[i], sizeof(struct dcc_t));
450
451 dcc[i].type = type;
452 if (xtra_size) {
453 dcc[i].u.other = nmalloc(xtra_size);
454 bzero(dcc[i].u.other, xtra_size);
455 }
456 return i;
457
458 }
459
460 /* Changes the given dcc entry to another type */
461 void changeover_dcc(int i, struct dcc_table *type, int xtra_size)
462 {
463 /* free old structure */
464 if (dcc[i].type && dcc[i].type->kill)
465 dcc[i].type->kill(i, dcc[i].u.other);
466 else if (dcc[i].u.other) {
467 nfree(dcc[i].u.other);
468 dcc[i].u.other = NULL;
469 }
470
471 dcc[i].type = type;
472 if (xtra_size) {
473 dcc[i].u.other = nmalloc(xtra_size);
474 bzero(dcc[i].u.other, xtra_size);
475 }
476 }
477
478 int detect_dcc_flood(time_t * timer, struct chat_info *chat, int idx)
479 {
480 time_t t;
481
482 if (dcc_flood_thr == 0)
483 return 0;
484 t = now;
485 if (*timer != t) {
486 *timer = t;
487 chat->msgs_per_sec = 0;
488 } else {
489 chat->msgs_per_sec++;
490 if (chat->msgs_per_sec > dcc_flood_thr) {
491 /* FLOOD */
492 dprintf(idx, "*** FLOOD: %s.\n", IRC_GOODBYE);
493 /* evil assumption here that flags&DCT_CHAT implies chat type */
494 if ((dcc[idx].type->flags & DCT_CHAT) && chat &&
495 (chat->channel >= 0)) {
496 char x[1024];
497
498 simple_sprintf(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);
502 }
503 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
504 if ((dcc[idx].sock != STDOUT) || backgrd) {
505 killsock(dcc[idx].sock);
506 lostdcc(idx);
507 } else {
508 dprintf(DP_STDOUT, "\n### SIMULATION RESET ###\n\n");
509 dcc_chatter(idx);
510 }
511 return 1; /* <- flood */
512 }
513 }
514 return 0;
515 }
516
517 /* handle someone being booted from dcc chat */
518 void do_boot(int idx, char *by, char *reason)
519 {
520 int files = (dcc[idx].type != &DCC_CHAT);
521
522 dprintf(idx, DCC_BOOTED1);
523 dprintf(idx, DCC_BOOTED2, DCC_BOOTED2_ARGS);
524 /* if it's a partyliner (chatterer :) */
525 /* horrible assumption that DCT_CHAT using structure uses same format
526 * as DCC_CHAT */
527 if ((dcc[idx].type->flags & DCT_CHAT) &&
528 (dcc[idx].u.chat->channel >= 0)) {
529 char x[1024];
530
531 simple_sprintf(x, "%s booted %s from the party line%s%s",
532 by, dcc[idx].nick, reason[0] ? ": " : "", reason);
533 chanout_but(idx, dcc[idx].u.chat->channel, "*** %s.\n", x);
534 if (dcc[idx].u.chat->channel < 100000)
535 botnet_send_part_idx(idx, x);
536 }
537 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
538 if ((dcc[idx].sock != STDOUT) || backgrd) {
539 killsock(dcc[idx].sock);
540 lostdcc(idx);
541 /* entry must remain in the table so it can be logged by the caller */
542 } else {
543 dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
544 dcc_chatter(idx);
545 }
546 return;
547 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23