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

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

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


Revision 1.29 - (show annotations) (download) (as text)
Thu Feb 7 22:19:05 2002 UTC (17 years, 5 months ago) by wcc
Branch: MAIN
Changes since 1.28: +2 -2 lines
File MIME type: text/x-chdr
Updated copyright info for 2002

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23