/[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.34 - (show annotations) (download) (as text)
Mon Feb 3 01:01:07 2003 UTC (16 years, 5 months ago) by stdarg
Branch: MAIN
Changes since 1.33: +0 -22 lines
File MIME type: text/x-chdr
* Let me know if there are any missing files!

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23