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

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

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


Revision 1.2 - (show 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 /*
2 * userent.c -- handles:
3 * user-entry handling, new style more versatile.
4 *
5 * $Id: userent.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
6 */
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 #ifdef IPV6
481 for (p = bi->address; *p; p++)
482 if (*p == ';')
483 *p = ':';
484 #endif
485 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 #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 l = simple_sprintf(work, "%s:%u/%u", bi->address, bi->telnet_port,
512 bi->relay_port);
513 #endif
514 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 #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 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 #endif
555 }
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