/[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.33 - (show annotations) (download) (as text)
Thu Jan 2 21:33:17 2003 UTC (16 years, 11 months ago) by wcc
Branch: MAIN
Changes since 1.32: +2 -2 lines
File MIME type: text/x-chdr
* Updated copyright info for 2003.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23