/[cvs]/eggdrop1.8/src/userent.c
ViewVC logotype

Annotation of /eggdrop1.8/src/userent.c

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


Revision 1.2 - (hide annotations) (download) (as text)
Thu Aug 5 18:12:05 2010 UTC (8 years, 9 months ago) by pseudo
Branch: MAIN
Changes since 1.1: +32 -1 lines
File MIME type: text/x-chdr
Added new, full IPv6 support to eggdrop.

1 simple 1.1 /*
2     * userent.c -- handles:
3     * user-entry handling, new style more versatile.
4     *
5 pseudo 1.2 * $Id: userent.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
6 simple 1.1 */
7     /*
8     * Copyright (C) 1997 Robey Pointer
9     * Copyright (C) 1999 - 2010 Eggheads Development Team
10     *
11     * This program is free software; you can redistribute it and/or
12     * modify it under the terms of the GNU General Public License
13     * as published by the Free Software Foundation; either version 2
14     * of the License, or (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24     */
25    
26     #include "main.h"
27     #include "users.h"
28    
29     extern int noshare;
30     extern struct userrec *userlist;
31     extern struct dcc_t *dcc;
32     extern Tcl_Interp *interp;
33     extern char whois_fields[];
34    
35    
36     int share_greet = 0; /* Share greeting info */
37     static struct user_entry_type *entry_type_list;
38    
39    
40     void init_userent()
41     {
42     entry_type_list = 0;
43     add_entry_type(&USERENTRY_COMMENT);
44     add_entry_type(&USERENTRY_XTRA);
45     add_entry_type(&USERENTRY_INFO);
46     add_entry_type(&USERENTRY_LASTON);
47     add_entry_type(&USERENTRY_BOTADDR);
48     add_entry_type(&USERENTRY_PASS);
49     add_entry_type(&USERENTRY_HOSTS);
50     add_entry_type(&USERENTRY_BOTFL);
51     }
52    
53     void list_type_kill(struct list_type *t)
54     {
55     struct list_type *u;
56    
57     while (t) {
58     u = t->next;
59     if (t->extra)
60     nfree(t->extra);
61     nfree(t);
62     t = u;
63     }
64     }
65    
66     int list_type_expmem(struct list_type *t)
67     {
68     int tot = 0;
69    
70     for (; t; t = t->next)
71     tot += sizeof(struct list_type) + strlen(t->extra) + 1;
72    
73     return tot;
74     }
75    
76     int def_unpack(struct userrec *u, struct user_entry *e)
77     {
78     char *tmp;
79    
80     tmp = e->u.list->extra;
81     e->u.list->extra = NULL;
82     list_type_kill(e->u.list);
83     e->u.string = tmp;
84     return 1;
85     }
86    
87     int def_pack(struct userrec *u, struct user_entry *e)
88     {
89     char *tmp;
90    
91     tmp = e->u.string;
92     e->u.list = user_malloc(sizeof(struct list_type));
93     e->u.list->next = NULL;
94     e->u.list->extra = tmp;
95     return 1;
96     }
97    
98     int def_kill(struct user_entry *e)
99     {
100     nfree(e->u.string);
101     nfree(e);
102     return 1;
103     }
104    
105     int def_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
106     {
107     if (fprintf(f, "--%s %s\n", e->type->name, e->u.string) == EOF)
108     return 0;
109     return 1;
110     }
111    
112     void *def_get(struct userrec *u, struct user_entry *e)
113     {
114     return e->u.string;
115     }
116    
117     int def_set(struct userrec *u, struct user_entry *e, void *buf)
118     {
119     char *string = (char *) buf;
120    
121     if (string && !string[0])
122     string = NULL;
123     if (!string && !e->u.string)
124     return 1;
125     if (string) {
126     int l = strlen(string);
127     char *i;
128    
129     if (l > 160)
130     l = 160;
131    
132    
133     e->u.string = user_realloc(e->u.string, l + 1);
134    
135     strncpyz(e->u.string, string, l + 1);
136    
137     for (i = e->u.string; *i; i++)
138     /* Allow bold, inverse, underline, color text here...
139     * But never add cr or lf!! --rtc
140     */
141     if ((unsigned int) *i < 32 && !strchr("\002\003\026\037", *i))
142     *i = '?';
143     } else {
144     nfree(e->u.string);
145     e->u.string = NULL;
146     }
147     if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED))) {
148     if (e->type != &USERENTRY_INFO || share_greet)
149     shareout(NULL, "c %s %s %s\n", e->type->name, u->handle,
150     e->u.string ? e->u.string : "");
151     }
152     return 1;
153     }
154    
155     int def_gotshare(struct userrec *u, struct user_entry *e, char *data, int idx)
156     {
157     putlog(LOG_CMDS, "*", "%s: change %s %s", dcc[idx].nick, e->type->name,
158     u->handle);
159     return e->type->set(u, e, data);
160     }
161    
162     int def_tcl_get(Tcl_Interp * interp, struct userrec *u,
163     struct user_entry *e, int argc, char **argv)
164     {
165     Tcl_AppendResult(interp, e->u.string, NULL);
166     return TCL_OK;
167     }
168    
169     int def_tcl_set(Tcl_Interp * irp, struct userrec *u,
170     struct user_entry *e, int argc, char **argv)
171     {
172     BADARGS(4, 4, " handle type setting");
173    
174     e->type->set(u, e, argv[3]);
175     return TCL_OK;
176     }
177    
178     int def_expmem(struct user_entry *e)
179     {
180     return strlen(e->u.string) + 1;
181     }
182    
183     void def_display(int idx, struct user_entry *e)
184     {
185     dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
186     }
187    
188     int def_dupuser(struct userrec *new, struct userrec *old, struct user_entry *e)
189     {
190     return set_user(e->type, new, e->u.string);
191     }
192    
193     static void comment_display(int idx, struct user_entry *e)
194     {
195     if (dcc[idx].user && (dcc[idx].user->flags & USER_MASTER))
196     dprintf(idx, " COMMENT: %.70s\n", e->u.string);
197     }
198    
199     struct user_entry_type USERENTRY_COMMENT = {
200     0, /* always 0 ;) */
201     def_gotshare,
202     def_dupuser,
203     def_unpack,
204     def_pack,
205     def_write_userfile,
206     def_kill,
207     def_get,
208     def_set,
209     def_tcl_get,
210     def_tcl_set,
211     def_expmem,
212     comment_display,
213     "COMMENT"
214     };
215    
216     struct user_entry_type USERENTRY_INFO = {
217     0, /* always 0 ;) */
218     def_gotshare,
219     def_dupuser,
220     def_unpack,
221     def_pack,
222     def_write_userfile,
223     def_kill,
224     def_get,
225     def_set,
226     def_tcl_get,
227     def_tcl_set,
228     def_expmem,
229     def_display,
230     "INFO"
231     };
232    
233     int pass_set(struct userrec *u, struct user_entry *e, void *buf)
234     {
235     char new[32];
236     register char *pass = buf;
237    
238     if (e->u.extra)
239     nfree(e->u.extra);
240     if (!pass || !pass[0] || (pass[0] == '-'))
241     e->u.extra = NULL;
242     else {
243     unsigned char *p = (unsigned char *) pass;
244    
245     if (strlen(pass) > 30)
246     pass[30] = 0;
247     while (*p) {
248     if ((*p <= 32) || (*p == 127))
249     *p = '?';
250     p++;
251     }
252     if ((u->flags & USER_BOT) || (pass[0] == '+'))
253     strcpy(new, pass);
254     else
255     encrypt_pass(pass, new);
256     e->u.extra = user_malloc(strlen(new) + 1);
257     strcpy(e->u.extra, new);
258     }
259     if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
260     shareout(NULL, "c PASS %s %s\n", u->handle, pass ? pass : "");
261     return 1;
262     }
263    
264     static int pass_tcl_set(Tcl_Interp * irp, struct userrec *u,
265     struct user_entry *e, int argc, char **argv)
266     {
267     BADARGS(3, 4, " handle PASS ?newpass?");
268    
269     pass_set(u, e, argc == 3 ? NULL : argv[3]);
270     return TCL_OK;
271     }
272    
273     struct user_entry_type USERENTRY_PASS = {
274     0,
275     def_gotshare,
276     0,
277     def_unpack,
278     def_pack,
279     def_write_userfile,
280     def_kill,
281     def_get,
282     pass_set,
283     def_tcl_get,
284     pass_tcl_set,
285     def_expmem,
286     0,
287     "PASS"
288     };
289    
290     static int laston_unpack(struct userrec *u, struct user_entry *e)
291     {
292     char *par, *arg;
293     struct laston_info *li;
294    
295     par = e->u.list->extra;
296     arg = newsplit(&par);
297     if (!par[0])
298     par = "???";
299     li = user_malloc(sizeof(struct laston_info));
300     li->lastonplace = user_malloc(strlen(par) + 1);
301     li->laston = atoi(arg);
302     strcpy(li->lastonplace, par);
303     list_type_kill(e->u.list);
304     e->u.extra = li;
305     return 1;
306     }
307    
308     static int laston_pack(struct userrec *u, struct user_entry *e)
309     {
310     char work[1024];
311     long tv;
312     struct laston_info *li;
313     int l;
314    
315     li = (struct laston_info *) e->u.extra;
316     tv = li->laston;
317     l = sprintf(work, "%lu %s", tv, li->lastonplace);
318     e->u.list = user_malloc(sizeof(struct list_type));
319     e->u.list->next = NULL;
320     e->u.list->extra = user_malloc(l + 1);
321     strcpy(e->u.list->extra, work);
322     nfree(li->lastonplace);
323     nfree(li);
324     return 1;
325     }
326    
327     static int laston_write_userfile(FILE *f, struct userrec *u,
328     struct user_entry *e)
329     {
330     long tv;
331     struct laston_info *li = (struct laston_info *) e->u.extra;
332    
333     tv = li->laston;
334     if (fprintf(f, "--LASTON %lu %s\n", tv,
335     li->lastonplace ? li->lastonplace : "") == EOF)
336     return 0;
337     return 1;
338     }
339    
340     static int laston_kill(struct user_entry *e)
341     {
342     if (((struct laston_info *) (e->u.extra))->lastonplace)
343     nfree(((struct laston_info *) (e->u.extra))->lastonplace);
344     nfree(e->u.extra);
345     nfree(e);
346     return 1;
347     }
348    
349     static int laston_set(struct userrec *u, struct user_entry *e, void *buf)
350     {
351     struct laston_info *li = (struct laston_info *) e->u.extra;
352    
353     if (li != buf) {
354     if (li) {
355     nfree(li->lastonplace);
356     nfree(li);
357     }
358    
359     li = e->u.extra = buf;
360     }
361     /* donut share laston info */
362     return 1;
363     }
364    
365     static int laston_tcl_get(Tcl_Interp * irp, struct userrec *u,
366     struct user_entry *e, int argc, char **argv)
367     {
368     struct laston_info *li = (struct laston_info *) e->u.extra;
369     char number[20];
370     long tv;
371     struct chanuserrec *cr;
372    
373     BADARGS(3, 4, " handle LASTON ?channel?");
374    
375     if (argc == 4) {
376     for (cr = u->chanrec; cr; cr = cr->next)
377     if (!rfc_casecmp(cr->channel, argv[3])) {
378     Tcl_AppendResult(irp, int_to_base10(cr->laston), NULL);
379     break;
380     }
381     if (!cr)
382     Tcl_AppendResult(irp, "0", NULL);
383     } else {
384     tv = li->laston;
385     sprintf(number, "%lu ", tv);
386     Tcl_AppendResult(irp, number, li->lastonplace, NULL);
387     }
388     return TCL_OK;
389     }
390    
391     static int laston_tcl_set(Tcl_Interp * irp, struct userrec *u,
392     struct user_entry *e, int argc, char **argv)
393     {
394     struct laston_info *li;
395     struct chanuserrec *cr;
396    
397     BADARGS(4, 5, " handle LASTON time ?place?");
398    
399     if ((argc == 5) && argv[4][0] && strchr(CHANMETA, argv[4][0])) {
400     /* Search for matching channel */
401     for (cr = u->chanrec; cr; cr = cr->next)
402     if (!rfc_casecmp(cr->channel, argv[4])) {
403     cr->laston = atoi(argv[3]);
404     break;
405     }
406     }
407     /* Save globally */
408     li = user_malloc(sizeof(struct laston_info));
409    
410     if (argc == 5) {
411     li->lastonplace = user_malloc(strlen(argv[4]) + 1);
412     strcpy(li->lastonplace, argv[4]);
413     } else {
414     li->lastonplace = user_malloc(1);
415     li->lastonplace[0] = 0;
416     }
417     li->laston = atoi(argv[3]);
418     set_user(&USERENTRY_LASTON, u, li);
419     return TCL_OK;
420     }
421    
422     static int laston_expmem(struct user_entry *e)
423     {
424     return sizeof(struct laston_info) +
425     strlen(((struct laston_info *) (e->u.extra))->lastonplace) + 1;
426     }
427    
428     static int laston_dupuser(struct userrec *new, struct userrec *old,
429     struct user_entry *e)
430     {
431     struct laston_info *li = e->u.extra, *li2;
432    
433     if (li) {
434     li2 = user_malloc(sizeof(struct laston_info));
435    
436     li2->laston = li->laston;
437     li2->lastonplace = user_malloc(strlen(li->lastonplace) + 1);
438     strcpy(li2->lastonplace, li->lastonplace);
439     return set_user(&USERENTRY_LASTON, new, li2);
440     }
441     return 0;
442     }
443    
444     struct user_entry_type USERENTRY_LASTON = {
445     0, /* always 0 ;) */
446     0,
447     laston_dupuser,
448     laston_unpack,
449     laston_pack,
450     laston_write_userfile,
451     laston_kill,
452     def_get,
453     laston_set,
454     laston_tcl_get,
455     laston_tcl_set,
456     laston_expmem,
457     0,
458     "LASTON"
459     };
460    
461     static int botaddr_unpack(struct userrec *u, struct user_entry *e)
462     {
463     char *p, *q;
464     struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
465    
466     egg_bzero(bi, sizeof(struct bot_addr));
467    
468     if (!(q = strchr((p = e->u.list->extra), ':'))) {
469     bi->address = user_malloc(strlen(p) + 1);
470     strcpy(bi->address, p);
471     } else {
472     bi->address = user_malloc((q - p) + 1);
473     strncpy(bi->address, p, q - p);
474     bi->address[q - p] = 0;
475     q++;
476     bi->telnet_port = atoi(q);
477     if ((q = strchr(q, '/')))
478     bi->relay_port = atoi(q + 1);
479     }
480 pseudo 1.2 #ifdef IPV6
481     for (p = bi->address; *p; p++)
482     if (*p == ';')
483     *p = ':';
484     #endif
485 simple 1.1 if (!bi->telnet_port)
486     bi->telnet_port = 3333;
487     if (!bi->relay_port)
488     bi->relay_port = bi->telnet_port;
489     list_type_kill(e->u.list);
490     e->u.extra = bi;
491     return 1;
492     }
493    
494     static int botaddr_pack(struct userrec *u, struct user_entry *e)
495     {
496     char work[1024];
497     struct bot_addr *bi;
498     int l;
499    
500     bi = (struct bot_addr *) e->u.extra;
501 pseudo 1.2 #ifdef IPV6
502     char *p, *addr = user_malloc(strlen(bi->address) + 1);
503     strcpy(addr, bi->address);
504     for (p = addr; *p; p++)
505     if (*p == ':')
506     *p = ';';
507     l = simple_sprintf(work, "%s:%u/%u", p, bi->telnet_port,
508     bi->relay_port);
509     nfree(addr);
510     #else
511 simple 1.1 l = simple_sprintf(work, "%s:%u/%u", bi->address, bi->telnet_port,
512     bi->relay_port);
513 pseudo 1.2 #endif
514 simple 1.1 e->u.list = user_malloc(sizeof(struct list_type));
515     e->u.list->next = NULL;
516     e->u.list->extra = user_malloc(l + 1);
517     strcpy(e->u.list->extra, work);
518     nfree(bi->address);
519     nfree(bi);
520     return 1;
521     }
522    
523     static int botaddr_kill(struct user_entry *e)
524     {
525     nfree(((struct bot_addr *) (e->u.extra))->address);
526     nfree(e->u.extra);
527     nfree(e);
528     return 1;
529     }
530    
531     static int botaddr_write_userfile(FILE *f, struct userrec *u,
532     struct user_entry *e)
533     {
534     register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
535    
536 pseudo 1.2 #ifdef IPV6
537     char *p, *addr = user_malloc(strlen(bi->address) + 1);
538     strcpy(addr, bi->address);
539     for (p = addr; *p; p++)
540     if (*p == ':')
541     *p = ';';
542     if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, addr,
543     bi->telnet_port, bi->relay_port) == EOF) {
544     nfree(addr);
545     return 0;
546     }
547     nfree(addr);
548     return 1;
549     #else
550 simple 1.1 if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, bi->address,
551     bi->telnet_port, bi->relay_port) == EOF)
552     return 0;
553     return 1;
554 pseudo 1.2 #endif
555 simple 1.1 }
556    
557     static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
558     {
559     register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
560    
561     if (!bi && !buf)
562     return 1;
563     if (bi != buf) {
564     if (bi) {
565     nfree(bi->address);
566     nfree(bi);
567     }
568     bi = e->u.extra = buf;
569     }
570     if (bi && !noshare && !(u->flags & USER_UNSHARED)) {
571     shareout(NULL, "c BOTADDR %s %s %d %d\n", u->handle,
572     bi->address, bi->telnet_port, bi->relay_port);
573     }
574     return 1;
575     }
576    
577     static int botaddr_tcl_get(Tcl_Interp * interp, struct userrec *u,
578     struct user_entry *e, int argc, char **argv)
579     {
580     register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
581     char number[20];
582    
583     sprintf(number, " %d", bi->telnet_port);
584     Tcl_AppendResult(interp, bi->address, number, NULL);
585     sprintf(number, " %d", bi->relay_port);
586     Tcl_AppendResult(interp, number, NULL);
587     return TCL_OK;
588     }
589    
590     static int botaddr_tcl_set(Tcl_Interp * irp, struct userrec *u,
591     struct user_entry *e, int argc, char **argv)
592     {
593     register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
594    
595     BADARGS(4, 6, " handle type address ?telnetport ?relayport??");
596    
597     if (u->flags & USER_BOT) {
598     /* Silently ignore for users */
599     if (!bi) {
600     bi = user_malloc(sizeof(struct bot_addr));
601     egg_bzero(bi, sizeof(struct bot_addr));
602     } else
603     nfree(bi->address);
604     bi->address = user_malloc(strlen(argv[3]) + 1);
605     strcpy(bi->address, argv[3]);
606     if (argc > 4)
607     bi->telnet_port = atoi(argv[4]);
608     if (argc > 5)
609     bi->relay_port = atoi(argv[5]);
610     if (!bi->telnet_port)
611     bi->telnet_port = 3333;
612     if (!bi->relay_port)
613     bi->relay_port = bi->telnet_port;
614     botaddr_set(u, e, bi);
615     }
616     return TCL_OK;
617     }
618    
619     static int botaddr_expmem(struct user_entry *e)
620     {
621     register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
622    
623     return strlen(bi->address) + 1 + sizeof(struct bot_addr);
624     }
625    
626     static void botaddr_display(int idx, struct user_entry *e)
627     {
628     register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
629    
630     dprintf(idx, " ADDRESS: %.70s\n", bi->address);
631     dprintf(idx, " users: %d, bots: %d\n", bi->relay_port, bi->telnet_port);
632     }
633    
634     static int botaddr_gotshare(struct userrec *u, struct user_entry *e,
635     char *buf, int idx)
636     {
637     struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
638     char *arg;
639    
640     egg_bzero(bi, sizeof(struct bot_addr));
641     arg = newsplit(&buf);
642     bi->address = user_malloc(strlen(arg) + 1);
643     strcpy(bi->address, arg);
644     arg = newsplit(&buf);
645     bi->telnet_port = atoi(arg);
646     bi->relay_port = atoi(buf);
647     if (!bi->telnet_port)
648     bi->telnet_port = 3333;
649     if (!bi->relay_port)
650     bi->relay_port = bi->telnet_port;
651     if (!(dcc[idx].status & STAT_GETTING))
652     putlog(LOG_CMDS, "*", "%s: change botaddr %s", dcc[idx].nick, u->handle);
653     return botaddr_set(u, e, bi);
654     }
655    
656     static int botaddr_dupuser(struct userrec *new, struct userrec *old,
657     struct user_entry *e)
658     {
659     if (old->flags & USER_BOT) {
660     struct bot_addr *bi = e->u.extra, *bi2;
661    
662     if (bi) {
663     bi2 = user_malloc(sizeof(struct bot_addr));
664    
665     bi2->telnet_port = bi->telnet_port;
666     bi2->relay_port = bi->relay_port;
667     bi2->address = user_malloc(strlen(bi->address) + 1);
668     strcpy(bi2->address, bi->address);
669     return set_user(&USERENTRY_BOTADDR, new, bi2);
670     }
671     }
672     return 0;
673     }
674    
675     struct user_entry_type USERENTRY_BOTADDR = {
676     0, /* always 0 ;) */
677     botaddr_gotshare,
678     botaddr_dupuser,
679     botaddr_unpack,
680     botaddr_pack,
681     botaddr_write_userfile,
682     botaddr_kill,
683     def_get,
684     botaddr_set,
685     botaddr_tcl_get,
686     botaddr_tcl_set,
687     botaddr_expmem,
688     botaddr_display,
689     "BOTADDR"
690     };
691    
692     int xtra_set(struct userrec *u, struct user_entry *e, void *buf)
693     {
694     struct xtra_key *curr, *old = NULL, *new = buf;
695    
696     for (curr = e->u.extra; curr; curr = curr->next) {
697     if (curr->key && !egg_strcasecmp(curr->key, new->key)) {
698     old = curr;
699     break;
700     }
701     }
702     if (!old && (!new->data || !new->data[0])) {
703     /* Delete non-existant entry -- doh ++rtc */
704     nfree(new->key);
705     if (new->data)
706     nfree(new->data);
707     nfree(new);
708     return TCL_OK;
709     }
710    
711     /* We will possibly free new below, so let's send the information
712     * to the botnet now
713     */
714     if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
715     shareout(NULL, "c XTRA %s %s %s\n", u->handle, new->key,
716     new->data ? new->data : "");
717     if ((old && old != new) || !new->data || !new->data[0]) {
718     egg_list_delete(&e->u.list, (struct list_type *) old);
719     nfree(old->key);
720     nfree(old->data);
721     nfree(old);
722     }
723     if (old != new && new->data) {
724     if (new->data[0])
725     list_insert((&e->u.extra), new) /* do not add a ';' here */
726     } else {
727     if (new->data)
728     nfree(new->data);
729     nfree(new->key);
730     nfree(new);
731     }
732     return TCL_OK;
733     }
734    
735     static int xtra_tcl_set(Tcl_Interp * irp, struct userrec *u,
736     struct user_entry *e, int argc, char **argv)
737     {
738     struct xtra_key *xk;
739     int l;
740    
741     BADARGS(4, 5, " handle type key ?value?");
742    
743     xk = user_malloc(sizeof(struct xtra_key));
744     l = strlen(argv[3]);
745     egg_bzero(xk, sizeof(struct xtra_key));
746     if (l > 500)
747     l = 500;
748     xk->key = user_malloc(l + 1);
749     strncpyz(xk->key, argv[3], l + 1);
750    
751     if (argc == 5) {
752     int k = strlen(argv[4]);
753    
754     if (k > 500 - l)
755     k = 500 - l;
756     xk->data = user_malloc(k + 1);
757     strncpyz(xk->data, argv[4], k + 1);
758     }
759     xtra_set(u, e, xk);
760     return TCL_OK;
761     }
762    
763     int xtra_unpack(struct userrec *u, struct user_entry *e)
764     {
765     struct list_type *curr, *head;
766     struct xtra_key *t;
767     char *key, *data;
768    
769     head = curr = e->u.list;
770     e->u.extra = NULL;
771     while (curr) {
772     t = user_malloc(sizeof(struct xtra_key));
773    
774     data = curr->extra;
775     key = newsplit(&data);
776     if (data[0]) {
777     t->key = user_malloc(strlen(key) + 1);
778     strcpy(t->key, key);
779     t->data = user_malloc(strlen(data) + 1);
780     strcpy(t->data, data);
781     list_insert((&e->u.extra), t);
782     }
783     curr = curr->next;
784     }
785     list_type_kill(head);
786     return 1;
787     }
788    
789     static int xtra_pack(struct userrec *u, struct user_entry *e)
790     {
791     struct list_type *t;
792     struct xtra_key *curr, *next;
793    
794     curr = e->u.extra;
795     e->u.list = NULL;
796     while (curr) {
797     t = user_malloc(sizeof(struct list_type));
798     t->extra = user_malloc(strlen(curr->key) + strlen(curr->data) + 4);
799     sprintf(t->extra, "%s %s", curr->key, curr->data);
800     list_insert((&e->u.list), t);
801     next = curr->next;
802     nfree(curr->key);
803     nfree(curr->data);
804     nfree(curr);
805     curr = next;
806     }
807     return 1;
808     }
809    
810     static void xtra_display(int idx, struct user_entry *e)
811     {
812     int code, lc, j;
813     EGG_CONST char **list;
814     struct xtra_key *xk;
815    
816     code = Tcl_SplitList(interp, whois_fields, &lc, &list);
817     if (code == TCL_ERROR)
818     return;
819     /* Scan thru xtra field, searching for matches */
820     for (xk = e->u.extra; xk; xk = xk->next) {
821     /* Ok, it's a valid xtra field entry */
822     for (j = 0; j < lc; j++) {
823     if (!egg_strcasecmp(list[j], xk->key))
824     dprintf(idx, " %s: %s\n", xk->key, xk->data);
825     }
826     }
827     Tcl_Free((char *) list);
828     }
829    
830     static int xtra_gotshare(struct userrec *u, struct user_entry *e,
831     char *buf, int idx)
832     {
833     char *arg;
834     struct xtra_key *xk;
835     int l;
836    
837     arg = newsplit(&buf);
838     if (!arg[0])
839     return 1;
840    
841     xk = user_malloc(sizeof(struct xtra_key));
842     egg_bzero(xk, sizeof(struct xtra_key));
843     l = strlen(arg);
844     if (l > 500)
845     l = 500;
846     xk->key = user_malloc(l + 1);
847     strncpyz(xk->key, arg, l + 1);
848    
849     if (buf[0]) {
850     int k = strlen(buf);
851    
852     if (k > 500 - l)
853     k = 500 - l;
854     xk->data = user_malloc(k + 1);
855     strncpyz(xk->data, buf, k + 1);
856     }
857     xtra_set(u, e, xk);
858     return 1;
859     }
860    
861     static int xtra_dupuser(struct userrec *new, struct userrec *old,
862     struct user_entry *e)
863     {
864     struct xtra_key *x1, *x2;
865    
866     for (x1 = e->u.extra; x1; x1 = x1->next) {
867     x2 = user_malloc(sizeof(struct xtra_key));
868    
869     x2->key = user_malloc(strlen(x1->key) + 1);
870     strcpy(x2->key, x1->key);
871     x2->data = user_malloc(strlen(x1->data) + 1);
872     strcpy(x2->data, x1->data);
873     set_user(&USERENTRY_XTRA, new, x2);
874     }
875     return 1;
876     }
877    
878     static int xtra_write_userfile(FILE *f, struct userrec *u,
879     struct user_entry *e)
880     {
881     struct xtra_key *x;
882    
883     for (x = e->u.extra; x; x = x->next)
884     if (fprintf(f, "--XTRA %s %s\n", x->key, x->data) == EOF)
885     return 0;
886     return 1;
887     }
888    
889     int xtra_kill(struct user_entry *e)
890     {
891     struct xtra_key *x, *y;
892    
893     for (x = e->u.extra; x; x = y) {
894     y = x->next;
895     nfree(x->key);
896     nfree(x->data);
897     nfree(x);
898     }
899     nfree(e);
900     return 1;
901     }
902    
903     static int xtra_tcl_get(Tcl_Interp * irp, struct userrec *u,
904     struct user_entry *e, int argc, char **argv)
905     {
906     struct xtra_key *x;
907    
908     BADARGS(3, 4, " handle XTRA ?key?");
909    
910     if (argc == 4) {
911     for (x = e->u.extra; x; x = x->next)
912     if (!egg_strcasecmp(argv[3], x->key)) {
913     Tcl_AppendResult(irp, x->data, NULL);
914     return TCL_OK;
915     }
916     return TCL_OK;
917     }
918     for (x = e->u.extra; x; x = x->next) {
919     char *p;
920     EGG_CONST char *list[2];
921    
922     list[0] = x->key;
923     list[1] = x->data;
924     p = Tcl_Merge(2, list);
925     Tcl_AppendElement(irp, p);
926     Tcl_Free((char *) p);
927     }
928     return TCL_OK;
929     }
930    
931     static int xtra_expmem(struct user_entry *e)
932     {
933     struct xtra_key *x;
934     int tot = 0;
935    
936     for (x = e->u.extra; x; x = x->next) {
937     tot += sizeof(struct xtra_key);
938    
939     tot += strlen(x->key) + 1;
940     tot += strlen(x->data) + 1;
941     }
942     return tot;
943     }
944    
945     struct user_entry_type USERENTRY_XTRA = {
946     0,
947     xtra_gotshare,
948     xtra_dupuser,
949     xtra_unpack,
950     xtra_pack,
951     xtra_write_userfile,
952     xtra_kill,
953     def_get,
954     xtra_set,
955     xtra_tcl_get,
956     xtra_tcl_set,
957     xtra_expmem,
958     xtra_display,
959     "XTRA"
960     };
961    
962     static int hosts_dupuser(struct userrec *new, struct userrec *old,
963     struct user_entry *e)
964     {
965     struct list_type *h;
966    
967     for (h = e->u.extra; h; h = h->next)
968     set_user(&USERENTRY_HOSTS, new, h->extra);
969     return 1;
970     }
971    
972     static int hosts_null(struct userrec *u, struct user_entry *e)
973     {
974     return 1;
975     }
976    
977     static int hosts_write_userfile(FILE *f, struct userrec *u,
978     struct user_entry *e)
979     {
980     struct list_type *h;
981    
982     for (h = e->u.extra; h; h = h->next)
983     if (fprintf(f, "--HOSTS %s\n", h->extra) == EOF)
984     return 0;
985     return 1;
986     }
987    
988     static int hosts_kill(struct user_entry *e)
989     {
990     list_type_kill(e->u.list);
991     nfree(e);
992     return 1;
993     }
994    
995     static int hosts_expmem(struct user_entry *e)
996     {
997     return list_type_expmem(e->u.list);
998     }
999    
1000     static void hosts_display(int idx, struct user_entry *e)
1001     {
1002     char s[1024];
1003     struct list_type *q;
1004    
1005     s[0] = 0;
1006     strcpy(s, " HOSTS: ");
1007     for (q = e->u.list; q; q = q->next) {
1008     if (s[0] && !s[9])
1009     strcat(s, q->extra);
1010     else if (!s[0])
1011     sprintf(s, " %s", q->extra);
1012     else {
1013     if (strlen(s) + strlen(q->extra) + 2 > 65) {
1014     dprintf(idx, "%s\n", s);
1015     sprintf(s, " %s", q->extra);
1016     } else {
1017     strcat(s, ", ");
1018     strcat(s, q->extra);
1019     }
1020     }
1021     }
1022     if (s[0])
1023     dprintf(idx, "%s\n", s);
1024     }
1025    
1026     static int hosts_set(struct userrec *u, struct user_entry *e, void *buf)
1027     {
1028     if (!buf || !egg_strcasecmp(buf, "none")) {
1029     /* When the bot crashes, it's in this part, not in the 'else' part */
1030     list_type_kill(e->u.list);
1031     e->u.list = NULL;
1032     } else {
1033     char *host = buf, *p = strchr(host, ',');
1034     struct list_type **t;
1035    
1036     /* Can't have ,'s in hostmasks */
1037     while (p) {
1038     *p = '?';
1039     p = strchr(host, ',');
1040     }
1041     /* fred1: check for redundant hostmasks with
1042     * controversial "superpenis" algorithm ;) */
1043     /* I'm surprised Raistlin hasn't gotten involved in this controversy */
1044     t = &(e->u.list);
1045     while (*t) {
1046     if (cmp_usermasks(host, (*t)->extra)) {
1047     struct list_type *u;
1048    
1049     u = *t;
1050     *t = (*t)->next;
1051     if (u->extra)
1052     nfree(u->extra);
1053     nfree(u);
1054     } else
1055     t = &((*t)->next);
1056     }
1057     *t = user_malloc(sizeof(struct list_type));
1058    
1059     (*t)->next = NULL;
1060     (*t)->extra = user_malloc(strlen(host) + 1);
1061     strcpy((*t)->extra, host);
1062     }
1063     return 1;
1064     }
1065    
1066     static int hosts_tcl_get(Tcl_Interp * irp, struct userrec *u,
1067     struct user_entry *e, int argc, char **argv)
1068     {
1069     struct list_type *x;
1070    
1071     BADARGS(3, 3, " handle HOSTS");
1072    
1073     for (x = e->u.list; x; x = x->next)
1074     Tcl_AppendElement(irp, x->extra);
1075     return TCL_OK;
1076     }
1077    
1078     static int hosts_tcl_set(Tcl_Interp * irp, struct userrec *u,
1079     struct user_entry *e, int argc, char **argv)
1080     {
1081     BADARGS(3, 4, " handle HOSTS ?host?");
1082    
1083     if (argc == 4)
1084     addhost_by_handle(u->handle, argv[3]);
1085     else
1086     addhost_by_handle(u->handle, "none"); /* drummer */
1087     return TCL_OK;
1088     }
1089    
1090     static int hosts_gotshare(struct userrec *u, struct user_entry *e,
1091     char *buf, int idx)
1092     {
1093     /* doh, try to be too clever and it bites your butt */
1094     return 0;
1095     }
1096    
1097     struct user_entry_type USERENTRY_HOSTS = {
1098     0,
1099     hosts_gotshare,
1100     hosts_dupuser,
1101     hosts_null,
1102     hosts_null,
1103     hosts_write_userfile,
1104     hosts_kill,
1105     def_get,
1106     hosts_set,
1107     hosts_tcl_get,
1108     hosts_tcl_set,
1109     hosts_expmem,
1110     hosts_display,
1111     "HOSTS"
1112     };
1113    
1114     int egg_list_append(struct list_type **h, struct list_type *i)
1115     {
1116     for (; *h; h = &((*h)->next));
1117     *h = i;
1118     return 1;
1119     }
1120    
1121     int egg_list_delete(struct list_type **h, struct list_type *i)
1122     {
1123     for (; *h; h = &((*h)->next))
1124     if (*h == i) {
1125     *h = i->next;
1126     return 1;
1127     }
1128     return 0;
1129     }
1130    
1131     int egg_list_contains(struct list_type *h, struct list_type *i)
1132     {
1133     for (; h; h = h->next)
1134     if (h == i) {
1135     return 1;
1136     }
1137     return 0;
1138     }
1139    
1140     int add_entry_type(struct user_entry_type *type)
1141     {
1142     struct userrec *u;
1143    
1144     list_insert(&entry_type_list, type);
1145     for (u = userlist; u; u = u->next) {
1146     struct user_entry *e = find_user_entry(type, u);
1147    
1148     if (e && e->name) {
1149     e->type = type;
1150     e->type->unpack(u, e);
1151     nfree(e->name);
1152     e->name = NULL;
1153     }
1154     }
1155     return 1;
1156     }
1157    
1158     int del_entry_type(struct user_entry_type *type)
1159     {
1160     struct userrec *u;
1161    
1162     for (u = userlist; u; u = u->next) {
1163     struct user_entry *e = find_user_entry(type, u);
1164    
1165     if (e && !e->name) {
1166     e->type->pack(u, e);
1167     e->name = user_malloc(strlen(e->type->name) + 1);
1168     strcpy(e->name, e->type->name);
1169     e->type = NULL;
1170     }
1171     }
1172     return egg_list_delete((struct list_type **) &entry_type_list,
1173     (struct list_type *) type);
1174     }
1175    
1176     struct user_entry_type *find_entry_type(char *name)
1177     {
1178     struct user_entry_type *p;
1179    
1180     for (p = entry_type_list; p; p = p->next) {
1181     if (!egg_strcasecmp(name, p->name))
1182     return p;
1183     }
1184     return NULL;
1185     }
1186    
1187     struct user_entry *find_user_entry(struct user_entry_type *et,
1188     struct userrec *u)
1189     {
1190     struct user_entry **e, *t;
1191    
1192     for (e = &(u->entries); *e; e = &((*e)->next)) {
1193     if (((*e)->type == et) ||
1194     ((*e)->name && !egg_strcasecmp((*e)->name, et->name))) {
1195     t = *e;
1196     *e = t->next;
1197     t->next = u->entries;
1198     u->entries = t;
1199     return t;
1200     }
1201     }
1202     return NULL;
1203     }
1204    
1205     void *get_user(struct user_entry_type *et, struct userrec *u)
1206     {
1207     struct user_entry *e;
1208    
1209     if (u && (e = find_user_entry(et, u)))
1210     return et->get(u, e);
1211     return 0;
1212     }
1213    
1214     int set_user(struct user_entry_type *et, struct userrec *u, void *d)
1215     {
1216     struct user_entry *e;
1217     int r;
1218    
1219     if (!u || !et)
1220     return 0;
1221    
1222     if (!(e = find_user_entry(et, u))) {
1223     e = user_malloc(sizeof(struct user_entry));
1224    
1225     e->type = et;
1226     e->name = NULL;
1227     e->u.list = NULL;
1228     list_insert((&(u->entries)), e);
1229     }
1230     r = et->set(u, e, d);
1231     if (!e->u.list) {
1232     egg_list_delete((struct list_type **) &(u->entries), (struct list_type *) e);
1233     nfree(e);
1234     }
1235     return r;
1236     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23