/[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.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Mon Jul 26 21:11:06 2010 UTC (8 years, 10 months ago) by simple
Branch: eggheads
CVS Tags: v1
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Imported Eggdrop 1.6.20

1 /*
2 * userent.c -- handles:
3 * user-entry handling, new style more versatile.
4 *
5 * $Id: userent.c,v 1.40 2010/02/07 17:21:14 pseudo 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 if (!bi->telnet_port)
481 bi->telnet_port = 3333;
482 if (!bi->relay_port)
483 bi->relay_port = bi->telnet_port;
484 list_type_kill(e->u.list);
485 e->u.extra = bi;
486 return 1;
487 }
488
489 static int botaddr_pack(struct userrec *u, struct user_entry *e)
490 {
491 char work[1024];
492 struct bot_addr *bi;
493 int l;
494
495 bi = (struct bot_addr *) e->u.extra;
496 l = simple_sprintf(work, "%s:%u/%u", bi->address, bi->telnet_port,
497 bi->relay_port);
498 e->u.list = user_malloc(sizeof(struct list_type));
499 e->u.list->next = NULL;
500 e->u.list->extra = user_malloc(l + 1);
501 strcpy(e->u.list->extra, work);
502 nfree(bi->address);
503 nfree(bi);
504 return 1;
505 }
506
507 static int botaddr_kill(struct user_entry *e)
508 {
509 nfree(((struct bot_addr *) (e->u.extra))->address);
510 nfree(e->u.extra);
511 nfree(e);
512 return 1;
513 }
514
515 static int botaddr_write_userfile(FILE *f, struct userrec *u,
516 struct user_entry *e)
517 {
518 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
519
520 if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, bi->address,
521 bi->telnet_port, bi->relay_port) == EOF)
522 return 0;
523 return 1;
524 }
525
526 static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
527 {
528 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
529
530 if (!bi && !buf)
531 return 1;
532 if (bi != buf) {
533 if (bi) {
534 nfree(bi->address);
535 nfree(bi);
536 }
537 bi = e->u.extra = buf;
538 }
539 if (bi && !noshare && !(u->flags & USER_UNSHARED)) {
540 shareout(NULL, "c BOTADDR %s %s %d %d\n", u->handle,
541 bi->address, bi->telnet_port, bi->relay_port);
542 }
543 return 1;
544 }
545
546 static int botaddr_tcl_get(Tcl_Interp * interp, struct userrec *u,
547 struct user_entry *e, int argc, char **argv)
548 {
549 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
550 char number[20];
551
552 sprintf(number, " %d", bi->telnet_port);
553 Tcl_AppendResult(interp, bi->address, number, NULL);
554 sprintf(number, " %d", bi->relay_port);
555 Tcl_AppendResult(interp, number, NULL);
556 return TCL_OK;
557 }
558
559 static int botaddr_tcl_set(Tcl_Interp * irp, struct userrec *u,
560 struct user_entry *e, int argc, char **argv)
561 {
562 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
563
564 BADARGS(4, 6, " handle type address ?telnetport ?relayport??");
565
566 if (u->flags & USER_BOT) {
567 /* Silently ignore for users */
568 if (!bi) {
569 bi = user_malloc(sizeof(struct bot_addr));
570 egg_bzero(bi, sizeof(struct bot_addr));
571 } else
572 nfree(bi->address);
573 bi->address = user_malloc(strlen(argv[3]) + 1);
574 strcpy(bi->address, argv[3]);
575 if (argc > 4)
576 bi->telnet_port = atoi(argv[4]);
577 if (argc > 5)
578 bi->relay_port = atoi(argv[5]);
579 if (!bi->telnet_port)
580 bi->telnet_port = 3333;
581 if (!bi->relay_port)
582 bi->relay_port = bi->telnet_port;
583 botaddr_set(u, e, bi);
584 }
585 return TCL_OK;
586 }
587
588 static int botaddr_expmem(struct user_entry *e)
589 {
590 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
591
592 return strlen(bi->address) + 1 + sizeof(struct bot_addr);
593 }
594
595 static void botaddr_display(int idx, struct user_entry *e)
596 {
597 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
598
599 dprintf(idx, " ADDRESS: %.70s\n", bi->address);
600 dprintf(idx, " users: %d, bots: %d\n", bi->relay_port, bi->telnet_port);
601 }
602
603 static int botaddr_gotshare(struct userrec *u, struct user_entry *e,
604 char *buf, int idx)
605 {
606 struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
607 char *arg;
608
609 egg_bzero(bi, sizeof(struct bot_addr));
610 arg = newsplit(&buf);
611 bi->address = user_malloc(strlen(arg) + 1);
612 strcpy(bi->address, arg);
613 arg = newsplit(&buf);
614 bi->telnet_port = atoi(arg);
615 bi->relay_port = atoi(buf);
616 if (!bi->telnet_port)
617 bi->telnet_port = 3333;
618 if (!bi->relay_port)
619 bi->relay_port = bi->telnet_port;
620 if (!(dcc[idx].status & STAT_GETTING))
621 putlog(LOG_CMDS, "*", "%s: change botaddr %s", dcc[idx].nick, u->handle);
622 return botaddr_set(u, e, bi);
623 }
624
625 static int botaddr_dupuser(struct userrec *new, struct userrec *old,
626 struct user_entry *e)
627 {
628 if (old->flags & USER_BOT) {
629 struct bot_addr *bi = e->u.extra, *bi2;
630
631 if (bi) {
632 bi2 = user_malloc(sizeof(struct bot_addr));
633
634 bi2->telnet_port = bi->telnet_port;
635 bi2->relay_port = bi->relay_port;
636 bi2->address = user_malloc(strlen(bi->address) + 1);
637 strcpy(bi2->address, bi->address);
638 return set_user(&USERENTRY_BOTADDR, new, bi2);
639 }
640 }
641 return 0;
642 }
643
644 struct user_entry_type USERENTRY_BOTADDR = {
645 0, /* always 0 ;) */
646 botaddr_gotshare,
647 botaddr_dupuser,
648 botaddr_unpack,
649 botaddr_pack,
650 botaddr_write_userfile,
651 botaddr_kill,
652 def_get,
653 botaddr_set,
654 botaddr_tcl_get,
655 botaddr_tcl_set,
656 botaddr_expmem,
657 botaddr_display,
658 "BOTADDR"
659 };
660
661 int xtra_set(struct userrec *u, struct user_entry *e, void *buf)
662 {
663 struct xtra_key *curr, *old = NULL, *new = buf;
664
665 for (curr = e->u.extra; curr; curr = curr->next) {
666 if (curr->key && !egg_strcasecmp(curr->key, new->key)) {
667 old = curr;
668 break;
669 }
670 }
671 if (!old && (!new->data || !new->data[0])) {
672 /* Delete non-existant entry -- doh ++rtc */
673 nfree(new->key);
674 if (new->data)
675 nfree(new->data);
676 nfree(new);
677 return TCL_OK;
678 }
679
680 /* We will possibly free new below, so let's send the information
681 * to the botnet now
682 */
683 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
684 shareout(NULL, "c XTRA %s %s %s\n", u->handle, new->key,
685 new->data ? new->data : "");
686 if ((old && old != new) || !new->data || !new->data[0]) {
687 egg_list_delete(&e->u.list, (struct list_type *) old);
688 nfree(old->key);
689 nfree(old->data);
690 nfree(old);
691 }
692 if (old != new && new->data) {
693 if (new->data[0])
694 list_insert((&e->u.extra), new) /* do not add a ';' here */
695 } else {
696 if (new->data)
697 nfree(new->data);
698 nfree(new->key);
699 nfree(new);
700 }
701 return TCL_OK;
702 }
703
704 static int xtra_tcl_set(Tcl_Interp * irp, struct userrec *u,
705 struct user_entry *e, int argc, char **argv)
706 {
707 struct xtra_key *xk;
708 int l;
709
710 BADARGS(4, 5, " handle type key ?value?");
711
712 xk = user_malloc(sizeof(struct xtra_key));
713 l = strlen(argv[3]);
714 egg_bzero(xk, sizeof(struct xtra_key));
715 if (l > 500)
716 l = 500;
717 xk->key = user_malloc(l + 1);
718 strncpyz(xk->key, argv[3], l + 1);
719
720 if (argc == 5) {
721 int k = strlen(argv[4]);
722
723 if (k > 500 - l)
724 k = 500 - l;
725 xk->data = user_malloc(k + 1);
726 strncpyz(xk->data, argv[4], k + 1);
727 }
728 xtra_set(u, e, xk);
729 return TCL_OK;
730 }
731
732 int xtra_unpack(struct userrec *u, struct user_entry *e)
733 {
734 struct list_type *curr, *head;
735 struct xtra_key *t;
736 char *key, *data;
737
738 head = curr = e->u.list;
739 e->u.extra = NULL;
740 while (curr) {
741 t = user_malloc(sizeof(struct xtra_key));
742
743 data = curr->extra;
744 key = newsplit(&data);
745 if (data[0]) {
746 t->key = user_malloc(strlen(key) + 1);
747 strcpy(t->key, key);
748 t->data = user_malloc(strlen(data) + 1);
749 strcpy(t->data, data);
750 list_insert((&e->u.extra), t);
751 }
752 curr = curr->next;
753 }
754 list_type_kill(head);
755 return 1;
756 }
757
758 static int xtra_pack(struct userrec *u, struct user_entry *e)
759 {
760 struct list_type *t;
761 struct xtra_key *curr, *next;
762
763 curr = e->u.extra;
764 e->u.list = NULL;
765 while (curr) {
766 t = user_malloc(sizeof(struct list_type));
767 t->extra = user_malloc(strlen(curr->key) + strlen(curr->data) + 4);
768 sprintf(t->extra, "%s %s", curr->key, curr->data);
769 list_insert((&e->u.list), t);
770 next = curr->next;
771 nfree(curr->key);
772 nfree(curr->data);
773 nfree(curr);
774 curr = next;
775 }
776 return 1;
777 }
778
779 static void xtra_display(int idx, struct user_entry *e)
780 {
781 int code, lc, j;
782 EGG_CONST char **list;
783 struct xtra_key *xk;
784
785 code = Tcl_SplitList(interp, whois_fields, &lc, &list);
786 if (code == TCL_ERROR)
787 return;
788 /* Scan thru xtra field, searching for matches */
789 for (xk = e->u.extra; xk; xk = xk->next) {
790 /* Ok, it's a valid xtra field entry */
791 for (j = 0; j < lc; j++) {
792 if (!egg_strcasecmp(list[j], xk->key))
793 dprintf(idx, " %s: %s\n", xk->key, xk->data);
794 }
795 }
796 Tcl_Free((char *) list);
797 }
798
799 static int xtra_gotshare(struct userrec *u, struct user_entry *e,
800 char *buf, int idx)
801 {
802 char *arg;
803 struct xtra_key *xk;
804 int l;
805
806 arg = newsplit(&buf);
807 if (!arg[0])
808 return 1;
809
810 xk = user_malloc(sizeof(struct xtra_key));
811 egg_bzero(xk, sizeof(struct xtra_key));
812 l = strlen(arg);
813 if (l > 500)
814 l = 500;
815 xk->key = user_malloc(l + 1);
816 strncpyz(xk->key, arg, l + 1);
817
818 if (buf[0]) {
819 int k = strlen(buf);
820
821 if (k > 500 - l)
822 k = 500 - l;
823 xk->data = user_malloc(k + 1);
824 strncpyz(xk->data, buf, k + 1);
825 }
826 xtra_set(u, e, xk);
827 return 1;
828 }
829
830 static int xtra_dupuser(struct userrec *new, struct userrec *old,
831 struct user_entry *e)
832 {
833 struct xtra_key *x1, *x2;
834
835 for (x1 = e->u.extra; x1; x1 = x1->next) {
836 x2 = user_malloc(sizeof(struct xtra_key));
837
838 x2->key = user_malloc(strlen(x1->key) + 1);
839 strcpy(x2->key, x1->key);
840 x2->data = user_malloc(strlen(x1->data) + 1);
841 strcpy(x2->data, x1->data);
842 set_user(&USERENTRY_XTRA, new, x2);
843 }
844 return 1;
845 }
846
847 static int xtra_write_userfile(FILE *f, struct userrec *u,
848 struct user_entry *e)
849 {
850 struct xtra_key *x;
851
852 for (x = e->u.extra; x; x = x->next)
853 if (fprintf(f, "--XTRA %s %s\n", x->key, x->data) == EOF)
854 return 0;
855 return 1;
856 }
857
858 int xtra_kill(struct user_entry *e)
859 {
860 struct xtra_key *x, *y;
861
862 for (x = e->u.extra; x; x = y) {
863 y = x->next;
864 nfree(x->key);
865 nfree(x->data);
866 nfree(x);
867 }
868 nfree(e);
869 return 1;
870 }
871
872 static int xtra_tcl_get(Tcl_Interp * irp, struct userrec *u,
873 struct user_entry *e, int argc, char **argv)
874 {
875 struct xtra_key *x;
876
877 BADARGS(3, 4, " handle XTRA ?key?");
878
879 if (argc == 4) {
880 for (x = e->u.extra; x; x = x->next)
881 if (!egg_strcasecmp(argv[3], x->key)) {
882 Tcl_AppendResult(irp, x->data, NULL);
883 return TCL_OK;
884 }
885 return TCL_OK;
886 }
887 for (x = e->u.extra; x; x = x->next) {
888 char *p;
889 EGG_CONST char *list[2];
890
891 list[0] = x->key;
892 list[1] = x->data;
893 p = Tcl_Merge(2, list);
894 Tcl_AppendElement(irp, p);
895 Tcl_Free((char *) p);
896 }
897 return TCL_OK;
898 }
899
900 static int xtra_expmem(struct user_entry *e)
901 {
902 struct xtra_key *x;
903 int tot = 0;
904
905 for (x = e->u.extra; x; x = x->next) {
906 tot += sizeof(struct xtra_key);
907
908 tot += strlen(x->key) + 1;
909 tot += strlen(x->data) + 1;
910 }
911 return tot;
912 }
913
914 struct user_entry_type USERENTRY_XTRA = {
915 0,
916 xtra_gotshare,
917 xtra_dupuser,
918 xtra_unpack,
919 xtra_pack,
920 xtra_write_userfile,
921 xtra_kill,
922 def_get,
923 xtra_set,
924 xtra_tcl_get,
925 xtra_tcl_set,
926 xtra_expmem,
927 xtra_display,
928 "XTRA"
929 };
930
931 static int hosts_dupuser(struct userrec *new, struct userrec *old,
932 struct user_entry *e)
933 {
934 struct list_type *h;
935
936 for (h = e->u.extra; h; h = h->next)
937 set_user(&USERENTRY_HOSTS, new, h->extra);
938 return 1;
939 }
940
941 static int hosts_null(struct userrec *u, struct user_entry *e)
942 {
943 return 1;
944 }
945
946 static int hosts_write_userfile(FILE *f, struct userrec *u,
947 struct user_entry *e)
948 {
949 struct list_type *h;
950
951 for (h = e->u.extra; h; h = h->next)
952 if (fprintf(f, "--HOSTS %s\n", h->extra) == EOF)
953 return 0;
954 return 1;
955 }
956
957 static int hosts_kill(struct user_entry *e)
958 {
959 list_type_kill(e->u.list);
960 nfree(e);
961 return 1;
962 }
963
964 static int hosts_expmem(struct user_entry *e)
965 {
966 return list_type_expmem(e->u.list);
967 }
968
969 static void hosts_display(int idx, struct user_entry *e)
970 {
971 char s[1024];
972 struct list_type *q;
973
974 s[0] = 0;
975 strcpy(s, " HOSTS: ");
976 for (q = e->u.list; q; q = q->next) {
977 if (s[0] && !s[9])
978 strcat(s, q->extra);
979 else if (!s[0])
980 sprintf(s, " %s", q->extra);
981 else {
982 if (strlen(s) + strlen(q->extra) + 2 > 65) {
983 dprintf(idx, "%s\n", s);
984 sprintf(s, " %s", q->extra);
985 } else {
986 strcat(s, ", ");
987 strcat(s, q->extra);
988 }
989 }
990 }
991 if (s[0])
992 dprintf(idx, "%s\n", s);
993 }
994
995 static int hosts_set(struct userrec *u, struct user_entry *e, void *buf)
996 {
997 if (!buf || !egg_strcasecmp(buf, "none")) {
998 /* When the bot crashes, it's in this part, not in the 'else' part */
999 list_type_kill(e->u.list);
1000 e->u.list = NULL;
1001 } else {
1002 char *host = buf, *p = strchr(host, ',');
1003 struct list_type **t;
1004
1005 /* Can't have ,'s in hostmasks */
1006 while (p) {
1007 *p = '?';
1008 p = strchr(host, ',');
1009 }
1010 /* fred1: check for redundant hostmasks with
1011 * controversial "superpenis" algorithm ;) */
1012 /* I'm surprised Raistlin hasn't gotten involved in this controversy */
1013 t = &(e->u.list);
1014 while (*t) {
1015 if (cmp_usermasks(host, (*t)->extra)) {
1016 struct list_type *u;
1017
1018 u = *t;
1019 *t = (*t)->next;
1020 if (u->extra)
1021 nfree(u->extra);
1022 nfree(u);
1023 } else
1024 t = &((*t)->next);
1025 }
1026 *t = user_malloc(sizeof(struct list_type));
1027
1028 (*t)->next = NULL;
1029 (*t)->extra = user_malloc(strlen(host) + 1);
1030 strcpy((*t)->extra, host);
1031 }
1032 return 1;
1033 }
1034
1035 static int hosts_tcl_get(Tcl_Interp * irp, struct userrec *u,
1036 struct user_entry *e, int argc, char **argv)
1037 {
1038 struct list_type *x;
1039
1040 BADARGS(3, 3, " handle HOSTS");
1041
1042 for (x = e->u.list; x; x = x->next)
1043 Tcl_AppendElement(irp, x->extra);
1044 return TCL_OK;
1045 }
1046
1047 static int hosts_tcl_set(Tcl_Interp * irp, struct userrec *u,
1048 struct user_entry *e, int argc, char **argv)
1049 {
1050 BADARGS(3, 4, " handle HOSTS ?host?");
1051
1052 if (argc == 4)
1053 addhost_by_handle(u->handle, argv[3]);
1054 else
1055 addhost_by_handle(u->handle, "none"); /* drummer */
1056 return TCL_OK;
1057 }
1058
1059 static int hosts_gotshare(struct userrec *u, struct user_entry *e,
1060 char *buf, int idx)
1061 {
1062 /* doh, try to be too clever and it bites your butt */
1063 return 0;
1064 }
1065
1066 struct user_entry_type USERENTRY_HOSTS = {
1067 0,
1068 hosts_gotshare,
1069 hosts_dupuser,
1070 hosts_null,
1071 hosts_null,
1072 hosts_write_userfile,
1073 hosts_kill,
1074 def_get,
1075 hosts_set,
1076 hosts_tcl_get,
1077 hosts_tcl_set,
1078 hosts_expmem,
1079 hosts_display,
1080 "HOSTS"
1081 };
1082
1083 int egg_list_append(struct list_type **h, struct list_type *i)
1084 {
1085 for (; *h; h = &((*h)->next));
1086 *h = i;
1087 return 1;
1088 }
1089
1090 int egg_list_delete(struct list_type **h, struct list_type *i)
1091 {
1092 for (; *h; h = &((*h)->next))
1093 if (*h == i) {
1094 *h = i->next;
1095 return 1;
1096 }
1097 return 0;
1098 }
1099
1100 int egg_list_contains(struct list_type *h, struct list_type *i)
1101 {
1102 for (; h; h = h->next)
1103 if (h == i) {
1104 return 1;
1105 }
1106 return 0;
1107 }
1108
1109 int add_entry_type(struct user_entry_type *type)
1110 {
1111 struct userrec *u;
1112
1113 list_insert(&entry_type_list, type);
1114 for (u = userlist; u; u = u->next) {
1115 struct user_entry *e = find_user_entry(type, u);
1116
1117 if (e && e->name) {
1118 e->type = type;
1119 e->type->unpack(u, e);
1120 nfree(e->name);
1121 e->name = NULL;
1122 }
1123 }
1124 return 1;
1125 }
1126
1127 int del_entry_type(struct user_entry_type *type)
1128 {
1129 struct userrec *u;
1130
1131 for (u = userlist; u; u = u->next) {
1132 struct user_entry *e = find_user_entry(type, u);
1133
1134 if (e && !e->name) {
1135 e->type->pack(u, e);
1136 e->name = user_malloc(strlen(e->type->name) + 1);
1137 strcpy(e->name, e->type->name);
1138 e->type = NULL;
1139 }
1140 }
1141 return egg_list_delete((struct list_type **) &entry_type_list,
1142 (struct list_type *) type);
1143 }
1144
1145 struct user_entry_type *find_entry_type(char *name)
1146 {
1147 struct user_entry_type *p;
1148
1149 for (p = entry_type_list; p; p = p->next) {
1150 if (!egg_strcasecmp(name, p->name))
1151 return p;
1152 }
1153 return NULL;
1154 }
1155
1156 struct user_entry *find_user_entry(struct user_entry_type *et,
1157 struct userrec *u)
1158 {
1159 struct user_entry **e, *t;
1160
1161 for (e = &(u->entries); *e; e = &((*e)->next)) {
1162 if (((*e)->type == et) ||
1163 ((*e)->name && !egg_strcasecmp((*e)->name, et->name))) {
1164 t = *e;
1165 *e = t->next;
1166 t->next = u->entries;
1167 u->entries = t;
1168 return t;
1169 }
1170 }
1171 return NULL;
1172 }
1173
1174 void *get_user(struct user_entry_type *et, struct userrec *u)
1175 {
1176 struct user_entry *e;
1177
1178 if (u && (e = find_user_entry(et, u)))
1179 return et->get(u, e);
1180 return 0;
1181 }
1182
1183 int set_user(struct user_entry_type *et, struct userrec *u, void *d)
1184 {
1185 struct user_entry *e;
1186 int r;
1187
1188 if (!u || !et)
1189 return 0;
1190
1191 if (!(e = find_user_entry(et, u))) {
1192 e = user_malloc(sizeof(struct user_entry));
1193
1194 e->type = et;
1195 e->name = NULL;
1196 e->u.list = NULL;
1197 list_insert((&(u->entries)), e);
1198 }
1199 r = et->set(u, e, d);
1200 if (!e->u.list) {
1201 egg_list_delete((struct list_type **) &(u->entries), (struct list_type *) e);
1202 nfree(e);
1203 }
1204 return r;
1205 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23