/[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.31 - (show annotations) (download) (as text)
Sun May 5 15:19:12 2002 UTC (17 years, 6 months ago) by wingman
Branch: MAIN
Changes since 1.30: +9 -1 lines
File MIME type: text/x-chdr
Changes:

 * removed patch.h
 * added proper <filename>.h to (nearly) all <filename.h>
 * moved fixcolon to server.mod and irc.mod
 * moved ip2long to net.h
 * removed some unused function (forgot the name :-P)

Todo:

 * move config.h #include's away from main.h to files which
   needs them
 * clean up lib/eggdrop/module.h
   (now not just main.h is included but nearly all .h files from
    the core, but i guess this fixes itself when the global func
    table is abandon - then the modules must be revised too and
    we can clean up module.h)

And i'll bet i forgot something... ;-)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23