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

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

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


Revision 1.36 - (hide annotations) (download) (as text)
Sun Oct 7 04:02:54 2001 UTC (18 years ago) by stdarg
Branch: MAIN
Changes since 1.35: +1 -2 lines
File MIME type: text/x-chdr
Got rid of bind tables in the exported irc function table. They're not used anywhere in the core or other normal modules. Other people should use find_bind_table(), not #define's.
Got rid of H_* bind tables in irc module. All are BT_* now.
Integrated the new bind tables in with the normal bind/unbind command.
Made tcl callbacks work with the normal data types (string, int, user (handle)).
Got rid of old bind tables in server.mod
Made ctcp.mod use the new bind tables.
Wrote down most of the stuff I did so that ITE could see a detailed report :) hehe (although I have a feeling I've left something out)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23