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