/[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.24 - (show annotations) (download) (as text)
Sun Dec 10 15:10:27 2000 UTC (18 years, 10 months ago) by guppy
Branch: MAIN
Changes since 1.23: +7 -14 lines
File MIME type: text/x-chdr
guppy: core_cleanup.diff ...

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23