00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "main.h"
00027 #include "users.h"
00028
00029 extern int noshare;
00030 extern struct userrec *userlist;
00031 extern struct dcc_t *dcc;
00032 extern Tcl_Interp *interp;
00033 extern char whois_fields[];
00034
00035
00036 int share_greet = 0;
00037 static struct user_entry_type *entry_type_list;
00038
00039
00040 void init_userent()
00041 {
00042 entry_type_list = 0;
00043 add_entry_type(&USERENTRY_COMMENT);
00044 add_entry_type(&USERENTRY_XTRA);
00045 add_entry_type(&USERENTRY_INFO);
00046 add_entry_type(&USERENTRY_LASTON);
00047 add_entry_type(&USERENTRY_BOTADDR);
00048 add_entry_type(&USERENTRY_PASS);
00049 add_entry_type(&USERENTRY_HOSTS);
00050 add_entry_type(&USERENTRY_BOTFL);
00051 }
00052
00053 void list_type_kill(struct list_type *t)
00054 {
00055 struct list_type *u;
00056
00057 while (t) {
00058 u = t->next;
00059 if (t->extra)
00060 nfree(t->extra);
00061 nfree(t);
00062 t = u;
00063 }
00064 }
00065
00066 int list_type_expmem(struct list_type *t)
00067 {
00068 int tot = 0;
00069
00070 for (; t; t = t->next)
00071 tot += sizeof(struct list_type) + strlen(t->extra) + 1;
00072
00073 return tot;
00074 }
00075
00076 int def_unpack(struct userrec *u, struct user_entry *e)
00077 {
00078 char *tmp;
00079
00080 tmp = e->u.list->extra;
00081 e->u.list->extra = NULL;
00082 list_type_kill(e->u.list);
00083 e->u.string = tmp;
00084 return 1;
00085 }
00086
00087 int def_pack(struct userrec *u, struct user_entry *e)
00088 {
00089 char *tmp;
00090
00091 tmp = e->u.string;
00092 e->u.list = user_malloc(sizeof(struct list_type));
00093 e->u.list->next = NULL;
00094 e->u.list->extra = tmp;
00095 return 1;
00096 }
00097
00098 int def_kill(struct user_entry *e)
00099 {
00100 nfree(e->u.string);
00101 nfree(e);
00102 return 1;
00103 }
00104
00105 int def_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
00106 {
00107 if (fprintf(f, "--%s %s\n", e->type->name, e->u.string) == EOF)
00108 return 0;
00109 return 1;
00110 }
00111
00112 void *def_get(struct userrec *u, struct user_entry *e)
00113 {
00114 return e->u.string;
00115 }
00116
00117 int def_set(struct userrec *u, struct user_entry *e, void *buf)
00118 {
00119 char *string = (char *) buf;
00120
00121 if (string && !string[0])
00122 string = NULL;
00123 if (!string && !e->u.string)
00124 return 1;
00125 if (string) {
00126 int l = strlen(string);
00127 char *i;
00128
00129 if (l > 160)
00130 l = 160;
00131
00132
00133 e->u.string = user_realloc(e->u.string, l + 1);
00134
00135 strncpyz(e->u.string, string, l + 1);
00136
00137 for (i = e->u.string; *i; i++)
00138
00139
00140
00141 if ((unsigned int) *i < 32 && !strchr("\002\003\026\037", *i))
00142 *i = '?';
00143 } else {
00144 nfree(e->u.string);
00145 e->u.string = NULL;
00146 }
00147 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED))) {
00148 if (e->type != &USERENTRY_INFO || share_greet)
00149 shareout(NULL, "c %s %s %s\n", e->type->name, u->handle,
00150 e->u.string ? e->u.string : "");
00151 }
00152 return 1;
00153 }
00154
00155 int def_gotshare(struct userrec *u, struct user_entry *e, char *data, int idx)
00156 {
00157 putlog(LOG_CMDS, "*", "%s: change %s %s", dcc[idx].nick, e->type->name,
00158 u->handle);
00159 return e->type->set(u, e, data);
00160 }
00161
00162 int def_tcl_get(Tcl_Interp * interp, struct userrec *u,
00163 struct user_entry *e, int argc, char **argv)
00164 {
00165 Tcl_AppendResult(interp, e->u.string, NULL);
00166 return TCL_OK;
00167 }
00168
00169 int def_tcl_set(Tcl_Interp * irp, struct userrec *u,
00170 struct user_entry *e, int argc, char **argv)
00171 {
00172 BADARGS(4, 4, " handle type setting");
00173
00174 e->type->set(u, e, argv[3]);
00175 return TCL_OK;
00176 }
00177
00178 int def_expmem(struct user_entry *e)
00179 {
00180 return strlen(e->u.string) + 1;
00181 }
00182
00183 void def_display(int idx, struct user_entry *e)
00184 {
00185 dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
00186 }
00187
00188 int def_dupuser(struct userrec *new, struct userrec *old, struct user_entry *e)
00189 {
00190 return set_user(e->type, new, e->u.string);
00191 }
00192
00193 static void comment_display(int idx, struct user_entry *e)
00194 {
00195 if (dcc[idx].user && (dcc[idx].user->flags & USER_MASTER))
00196 dprintf(idx, " COMMENT: %.70s\n", e->u.string);
00197 }
00198
00199 struct user_entry_type USERENTRY_COMMENT = {
00200 0,
00201 def_gotshare,
00202 def_dupuser,
00203 def_unpack,
00204 def_pack,
00205 def_write_userfile,
00206 def_kill,
00207 def_get,
00208 def_set,
00209 def_tcl_get,
00210 def_tcl_set,
00211 def_expmem,
00212 comment_display,
00213 "COMMENT"
00214 };
00215
00216 struct user_entry_type USERENTRY_INFO = {
00217 0,
00218 def_gotshare,
00219 def_dupuser,
00220 def_unpack,
00221 def_pack,
00222 def_write_userfile,
00223 def_kill,
00224 def_get,
00225 def_set,
00226 def_tcl_get,
00227 def_tcl_set,
00228 def_expmem,
00229 def_display,
00230 "INFO"
00231 };
00232
00233 int pass_set(struct userrec *u, struct user_entry *e, void *buf)
00234 {
00235 char new[32];
00236 register char *pass = buf;
00237
00238 if (e->u.extra)
00239 nfree(e->u.extra);
00240 if (!pass || !pass[0] || (pass[0] == '-'))
00241 e->u.extra = NULL;
00242 else {
00243 unsigned char *p = (unsigned char *) pass;
00244
00245 if (strlen(pass) > 30)
00246 pass[30] = 0;
00247 while (*p) {
00248 if ((*p <= 32) || (*p == 127))
00249 *p = '?';
00250 p++;
00251 }
00252 if ((u->flags & USER_BOT) || (pass[0] == '+'))
00253 strcpy(new, pass);
00254 else
00255 encrypt_pass(pass, new);
00256 e->u.extra = user_malloc(strlen(new) + 1);
00257 strcpy(e->u.extra, new);
00258 }
00259 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
00260 shareout(NULL, "c PASS %s %s\n", u->handle, pass ? pass : "");
00261 return 1;
00262 }
00263
00264 static int pass_tcl_set(Tcl_Interp * irp, struct userrec *u,
00265 struct user_entry *e, int argc, char **argv)
00266 {
00267 BADARGS(3, 4, " handle PASS ?newpass?");
00268
00269 pass_set(u, e, argc == 3 ? NULL : argv[3]);
00270 return TCL_OK;
00271 }
00272
00273 struct user_entry_type USERENTRY_PASS = {
00274 0,
00275 def_gotshare,
00276 0,
00277 def_unpack,
00278 def_pack,
00279 def_write_userfile,
00280 def_kill,
00281 def_get,
00282 pass_set,
00283 def_tcl_get,
00284 pass_tcl_set,
00285 def_expmem,
00286 0,
00287 "PASS"
00288 };
00289
00290 static int laston_unpack(struct userrec *u, struct user_entry *e)
00291 {
00292 char *par, *arg;
00293 struct laston_info *li;
00294
00295 par = e->u.list->extra;
00296 arg = newsplit(&par);
00297 if (!par[0])
00298 par = "???";
00299 li = user_malloc(sizeof(struct laston_info));
00300 li->lastonplace = user_malloc(strlen(par) + 1);
00301 li->laston = atoi(arg);
00302 strcpy(li->lastonplace, par);
00303 list_type_kill(e->u.list);
00304 e->u.extra = li;
00305 return 1;
00306 }
00307
00308 static int laston_pack(struct userrec *u, struct user_entry *e)
00309 {
00310 char work[1024];
00311 long tv;
00312 struct laston_info *li;
00313 int l;
00314
00315 li = (struct laston_info *) e->u.extra;
00316 tv = li->laston;
00317 l = sprintf(work, "%lu %s", tv, li->lastonplace);
00318 e->u.list = user_malloc(sizeof(struct list_type));
00319 e->u.list->next = NULL;
00320 e->u.list->extra = user_malloc(l + 1);
00321 strcpy(e->u.list->extra, work);
00322 nfree(li->lastonplace);
00323 nfree(li);
00324 return 1;
00325 }
00326
00327 static int laston_write_userfile(FILE *f, struct userrec *u,
00328 struct user_entry *e)
00329 {
00330 long tv;
00331 struct laston_info *li = (struct laston_info *) e->u.extra;
00332
00333 tv = li->laston;
00334 if (fprintf(f, "--LASTON %lu %s\n", tv,
00335 li->lastonplace ? li->lastonplace : "") == EOF)
00336 return 0;
00337 return 1;
00338 }
00339
00340 static int laston_kill(struct user_entry *e)
00341 {
00342 if (((struct laston_info *) (e->u.extra))->lastonplace)
00343 nfree(((struct laston_info *) (e->u.extra))->lastonplace);
00344 nfree(e->u.extra);
00345 nfree(e);
00346 return 1;
00347 }
00348
00349 static int laston_set(struct userrec *u, struct user_entry *e, void *buf)
00350 {
00351 struct laston_info *li = (struct laston_info *) e->u.extra;
00352
00353 if (li != buf) {
00354 if (li) {
00355 nfree(li->lastonplace);
00356 nfree(li);
00357 }
00358
00359 li = e->u.extra = buf;
00360 }
00361
00362 return 1;
00363 }
00364
00365 static int laston_tcl_get(Tcl_Interp * irp, struct userrec *u,
00366 struct user_entry *e, int argc, char **argv)
00367 {
00368 struct laston_info *li = (struct laston_info *) e->u.extra;
00369 char number[20];
00370 long tv;
00371 struct chanuserrec *cr;
00372
00373 BADARGS(3, 4, " handle LASTON ?channel?");
00374
00375 if (argc == 4) {
00376 for (cr = u->chanrec; cr; cr = cr->next)
00377 if (!rfc_casecmp(cr->channel, argv[3])) {
00378 Tcl_AppendResult(irp, int_to_base10(cr->laston), NULL);
00379 break;
00380 }
00381 if (!cr)
00382 Tcl_AppendResult(irp, "0", NULL);
00383 } else {
00384 tv = li->laston;
00385 sprintf(number, "%lu ", tv);
00386 Tcl_AppendResult(irp, number, li->lastonplace, NULL);
00387 }
00388 return TCL_OK;
00389 }
00390
00391 static int laston_tcl_set(Tcl_Interp * irp, struct userrec *u,
00392 struct user_entry *e, int argc, char **argv)
00393 {
00394 struct laston_info *li;
00395 struct chanuserrec *cr;
00396
00397 BADARGS(4, 5, " handle LASTON time ?place?");
00398
00399 if ((argc == 5) && argv[4][0] && strchr(CHANMETA, argv[4][0])) {
00400
00401 for (cr = u->chanrec; cr; cr = cr->next)
00402 if (!rfc_casecmp(cr->channel, argv[4])) {
00403 cr->laston = atoi(argv[3]);
00404 break;
00405 }
00406 }
00407
00408 li = user_malloc(sizeof(struct laston_info));
00409
00410 if (argc == 5) {
00411 li->lastonplace = user_malloc(strlen(argv[4]) + 1);
00412 strcpy(li->lastonplace, argv[4]);
00413 } else {
00414 li->lastonplace = user_malloc(1);
00415 li->lastonplace[0] = 0;
00416 }
00417 li->laston = atoi(argv[3]);
00418 set_user(&USERENTRY_LASTON, u, li);
00419 return TCL_OK;
00420 }
00421
00422 static int laston_expmem(struct user_entry *e)
00423 {
00424 return sizeof(struct laston_info) +
00425 strlen(((struct laston_info *) (e->u.extra))->lastonplace) + 1;
00426 }
00427
00428 static int laston_dupuser(struct userrec *new, struct userrec *old,
00429 struct user_entry *e)
00430 {
00431 struct laston_info *li = e->u.extra, *li2;
00432
00433 if (li) {
00434 li2 = user_malloc(sizeof(struct laston_info));
00435
00436 li2->laston = li->laston;
00437 li2->lastonplace = user_malloc(strlen(li->lastonplace) + 1);
00438 strcpy(li2->lastonplace, li->lastonplace);
00439 return set_user(&USERENTRY_LASTON, new, li2);
00440 }
00441 return 0;
00442 }
00443
00444 struct user_entry_type USERENTRY_LASTON = {
00445 0,
00446 0,
00447 laston_dupuser,
00448 laston_unpack,
00449 laston_pack,
00450 laston_write_userfile,
00451 laston_kill,
00452 def_get,
00453 laston_set,
00454 laston_tcl_get,
00455 laston_tcl_set,
00456 laston_expmem,
00457 0,
00458 "LASTON"
00459 };
00460
00461 static int botaddr_unpack(struct userrec *u, struct user_entry *e)
00462 {
00463 char *p, *q;
00464 struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
00465
00466 egg_bzero(bi, sizeof(struct bot_addr));
00467
00468 if (!(q = strchr((p = e->u.list->extra), ':'))) {
00469 bi->address = user_malloc(strlen(p) + 1);
00470 strcpy(bi->address, p);
00471 } else {
00472 bi->address = user_malloc((q - p) + 1);
00473 strncpy(bi->address, p, q - p);
00474 bi->address[q - p] = 0;
00475 q++;
00476 bi->telnet_port = atoi(q);
00477 if ((q = strchr(q, '/')))
00478 bi->relay_port = atoi(q + 1);
00479 }
00480 if (!bi->telnet_port)
00481 bi->telnet_port = 3333;
00482 if (!bi->relay_port)
00483 bi->relay_port = bi->telnet_port;
00484 list_type_kill(e->u.list);
00485 e->u.extra = bi;
00486 return 1;
00487 }
00488
00489 static int botaddr_pack(struct userrec *u, struct user_entry *e)
00490 {
00491 char work[1024];
00492 struct bot_addr *bi;
00493 int l;
00494
00495 bi = (struct bot_addr *) e->u.extra;
00496 l = simple_sprintf(work, "%s:%u/%u", bi->address, bi->telnet_port,
00497 bi->relay_port);
00498 e->u.list = user_malloc(sizeof(struct list_type));
00499 e->u.list->next = NULL;
00500 e->u.list->extra = user_malloc(l + 1);
00501 strcpy(e->u.list->extra, work);
00502 nfree(bi->address);
00503 nfree(bi);
00504 return 1;
00505 }
00506
00507 static int botaddr_kill(struct user_entry *e)
00508 {
00509 nfree(((struct bot_addr *) (e->u.extra))->address);
00510 nfree(e->u.extra);
00511 nfree(e);
00512 return 1;
00513 }
00514
00515 static int botaddr_write_userfile(FILE *f, struct userrec *u,
00516 struct user_entry *e)
00517 {
00518 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
00519
00520 if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, bi->address,
00521 bi->telnet_port, bi->relay_port) == EOF)
00522 return 0;
00523 return 1;
00524 }
00525
00526 static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
00527 {
00528 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
00529
00530 if (!bi && !buf)
00531 return 1;
00532 if (bi != buf) {
00533 if (bi) {
00534 nfree(bi->address);
00535 nfree(bi);
00536 }
00537 bi = e->u.extra = buf;
00538 }
00539 if (bi && !noshare && !(u->flags & USER_UNSHARED)) {
00540 shareout(NULL, "c BOTADDR %s %s %d %d\n", u->handle,
00541 bi->address, bi->telnet_port, bi->relay_port);
00542 }
00543 return 1;
00544 }
00545
00546 static int botaddr_tcl_get(Tcl_Interp * interp, struct userrec *u,
00547 struct user_entry *e, int argc, char **argv)
00548 {
00549 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
00550 char number[20];
00551
00552 sprintf(number, " %d", bi->telnet_port);
00553 Tcl_AppendResult(interp, bi->address, number, NULL);
00554 sprintf(number, " %d", bi->relay_port);
00555 Tcl_AppendResult(interp, number, NULL);
00556 return TCL_OK;
00557 }
00558
00559 static int botaddr_tcl_set(Tcl_Interp * irp, struct userrec *u,
00560 struct user_entry *e, int argc, char **argv)
00561 {
00562 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
00563
00564 BADARGS(4, 6, " handle type address ?telnetport ?relayport??");
00565
00566 if (u->flags & USER_BOT) {
00567
00568 if (!bi) {
00569 bi = user_malloc(sizeof(struct bot_addr));
00570 egg_bzero(bi, sizeof(struct bot_addr));
00571 } else
00572 nfree(bi->address);
00573 bi->address = user_malloc(strlen(argv[3]) + 1);
00574 strcpy(bi->address, argv[3]);
00575 if (argc > 4)
00576 bi->telnet_port = atoi(argv[4]);
00577 if (argc > 5)
00578 bi->relay_port = atoi(argv[5]);
00579 if (!bi->telnet_port)
00580 bi->telnet_port = 3333;
00581 if (!bi->relay_port)
00582 bi->relay_port = bi->telnet_port;
00583 botaddr_set(u, e, bi);
00584 }
00585 return TCL_OK;
00586 }
00587
00588 static int botaddr_expmem(struct user_entry *e)
00589 {
00590 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
00591
00592 return strlen(bi->address) + 1 + sizeof(struct bot_addr);
00593 }
00594
00595 static void botaddr_display(int idx, struct user_entry *e)
00596 {
00597 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
00598
00599 dprintf(idx, " ADDRESS: %.70s\n", bi->address);
00600 dprintf(idx, " users: %d, bots: %d\n", bi->relay_port, bi->telnet_port);
00601 }
00602
00603 static int botaddr_gotshare(struct userrec *u, struct user_entry *e,
00604 char *buf, int idx)
00605 {
00606 struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
00607 char *arg;
00608
00609 egg_bzero(bi, sizeof(struct bot_addr));
00610 arg = newsplit(&buf);
00611 bi->address = user_malloc(strlen(arg) + 1);
00612 strcpy(bi->address, arg);
00613 arg = newsplit(&buf);
00614 bi->telnet_port = atoi(arg);
00615 bi->relay_port = atoi(buf);
00616 if (!bi->telnet_port)
00617 bi->telnet_port = 3333;
00618 if (!bi->relay_port)
00619 bi->relay_port = bi->telnet_port;
00620 if (!(dcc[idx].status & STAT_GETTING))
00621 putlog(LOG_CMDS, "*", "%s: change botaddr %s", dcc[idx].nick, u->handle);
00622 return botaddr_set(u, e, bi);
00623 }
00624
00625 static int botaddr_dupuser(struct userrec *new, struct userrec *old,
00626 struct user_entry *e)
00627 {
00628 if (old->flags & USER_BOT) {
00629 struct bot_addr *bi = e->u.extra, *bi2;
00630
00631 if (bi) {
00632 bi2 = user_malloc(sizeof(struct bot_addr));
00633
00634 bi2->telnet_port = bi->telnet_port;
00635 bi2->relay_port = bi->relay_port;
00636 bi2->address = user_malloc(strlen(bi->address) + 1);
00637 strcpy(bi2->address, bi->address);
00638 return set_user(&USERENTRY_BOTADDR, new, bi2);
00639 }
00640 }
00641 return 0;
00642 }
00643
00644 struct user_entry_type USERENTRY_BOTADDR = {
00645 0,
00646 botaddr_gotshare,
00647 botaddr_dupuser,
00648 botaddr_unpack,
00649 botaddr_pack,
00650 botaddr_write_userfile,
00651 botaddr_kill,
00652 def_get,
00653 botaddr_set,
00654 botaddr_tcl_get,
00655 botaddr_tcl_set,
00656 botaddr_expmem,
00657 botaddr_display,
00658 "BOTADDR"
00659 };
00660
00661 int xtra_set(struct userrec *u, struct user_entry *e, void *buf)
00662 {
00663 struct xtra_key *curr, *old = NULL, *new = buf;
00664
00665 for (curr = e->u.extra; curr; curr = curr->next) {
00666 if (curr->key && !egg_strcasecmp(curr->key, new->key)) {
00667 old = curr;
00668 break;
00669 }
00670 }
00671 if (!old && (!new->data || !new->data[0])) {
00672
00673 nfree(new->key);
00674 if (new->data)
00675 nfree(new->data);
00676 nfree(new);
00677 return TCL_OK;
00678 }
00679
00680
00681
00682
00683 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
00684 shareout(NULL, "c XTRA %s %s %s\n", u->handle, new->key,
00685 new->data ? new->data : "");
00686 if ((old && old != new) || !new->data || !new->data[0]) {
00687 egg_list_delete(&e->u.list, (struct list_type *) old);
00688 nfree(old->key);
00689 nfree(old->data);
00690 nfree(old);
00691 }
00692 if (old != new && new->data) {
00693 if (new->data[0])
00694 list_insert((&e->u.extra), new)
00695 } else {
00696 if (new->data)
00697 nfree(new->data);
00698 nfree(new->key);
00699 nfree(new);
00700 }
00701 return TCL_OK;
00702 }
00703
00704 static int xtra_tcl_set(Tcl_Interp * irp, struct userrec *u,
00705 struct user_entry *e, int argc, char **argv)
00706 {
00707 struct xtra_key *xk;
00708 int l;
00709
00710 BADARGS(4, 5, " handle type key ?value?");
00711
00712 xk = user_malloc(sizeof(struct xtra_key));
00713 l = strlen(argv[3]);
00714 egg_bzero(xk, sizeof(struct xtra_key));
00715 if (l > 500)
00716 l = 500;
00717 xk->key = user_malloc(l + 1);
00718 strncpyz(xk->key, argv[3], l + 1);
00719
00720 if (argc == 5) {
00721 int k = strlen(argv[4]);
00722
00723 if (k > 500 - l)
00724 k = 500 - l;
00725 xk->data = user_malloc(k + 1);
00726 strncpyz(xk->data, argv[4], k + 1);
00727 }
00728 xtra_set(u, e, xk);
00729 return TCL_OK;
00730 }
00731
00732 int xtra_unpack(struct userrec *u, struct user_entry *e)
00733 {
00734 struct list_type *curr, *head;
00735 struct xtra_key *t;
00736 char *key, *data;
00737
00738 head = curr = e->u.list;
00739 e->u.extra = NULL;
00740 while (curr) {
00741 t = user_malloc(sizeof(struct xtra_key));
00742
00743 data = curr->extra;
00744 key = newsplit(&data);
00745 if (data[0]) {
00746 t->key = user_malloc(strlen(key) + 1);
00747 strcpy(t->key, key);
00748 t->data = user_malloc(strlen(data) + 1);
00749 strcpy(t->data, data);
00750 list_insert((&e->u.extra), t);
00751 }
00752 curr = curr->next;
00753 }
00754 list_type_kill(head);
00755 return 1;
00756 }
00757
00758 static int xtra_pack(struct userrec *u, struct user_entry *e)
00759 {
00760 struct list_type *t;
00761 struct xtra_key *curr, *next;
00762
00763 curr = e->u.extra;
00764 e->u.list = NULL;
00765 while (curr) {
00766 t = user_malloc(sizeof(struct list_type));
00767 t->extra = user_malloc(strlen(curr->key) + strlen(curr->data) + 4);
00768 sprintf(t->extra, "%s %s", curr->key, curr->data);
00769 list_insert((&e->u.list), t);
00770 next = curr->next;
00771 nfree(curr->key);
00772 nfree(curr->data);
00773 nfree(curr);
00774 curr = next;
00775 }
00776 return 1;
00777 }
00778
00779 static void xtra_display(int idx, struct user_entry *e)
00780 {
00781 int code, lc, j;
00782 EGG_CONST char **list;
00783 struct xtra_key *xk;
00784
00785 code = Tcl_SplitList(interp, whois_fields, &lc, &list);
00786 if (code == TCL_ERROR)
00787 return;
00788
00789 for (xk = e->u.extra; xk; xk = xk->next) {
00790
00791 for (j = 0; j < lc; j++) {
00792 if (!egg_strcasecmp(list[j], xk->key))
00793 dprintf(idx, " %s: %s\n", xk->key, xk->data);
00794 }
00795 }
00796 Tcl_Free((char *) list);
00797 }
00798
00799 static int xtra_gotshare(struct userrec *u, struct user_entry *e,
00800 char *buf, int idx)
00801 {
00802 char *arg;
00803 struct xtra_key *xk;
00804 int l;
00805
00806 arg = newsplit(&buf);
00807 if (!arg[0])
00808 return 1;
00809
00810 xk = user_malloc(sizeof(struct xtra_key));
00811 egg_bzero(xk, sizeof(struct xtra_key));
00812 l = strlen(arg);
00813 if (l > 500)
00814 l = 500;
00815 xk->key = user_malloc(l + 1);
00816 strncpyz(xk->key, arg, l + 1);
00817
00818 if (buf[0]) {
00819 int k = strlen(buf);
00820
00821 if (k > 500 - l)
00822 k = 500 - l;
00823 xk->data = user_malloc(k + 1);
00824 strncpyz(xk->data, buf, k + 1);
00825 }
00826 xtra_set(u, e, xk);
00827 return 1;
00828 }
00829
00830 static int xtra_dupuser(struct userrec *new, struct userrec *old,
00831 struct user_entry *e)
00832 {
00833 struct xtra_key *x1, *x2;
00834
00835 for (x1 = e->u.extra; x1; x1 = x1->next) {
00836 x2 = user_malloc(sizeof(struct xtra_key));
00837
00838 x2->key = user_malloc(strlen(x1->key) + 1);
00839 strcpy(x2->key, x1->key);
00840 x2->data = user_malloc(strlen(x1->data) + 1);
00841 strcpy(x2->data, x1->data);
00842 set_user(&USERENTRY_XTRA, new, x2);
00843 }
00844 return 1;
00845 }
00846
00847 static int xtra_write_userfile(FILE *f, struct userrec *u,
00848 struct user_entry *e)
00849 {
00850 struct xtra_key *x;
00851
00852 for (x = e->u.extra; x; x = x->next)
00853 if (fprintf(f, "--XTRA %s %s\n", x->key, x->data) == EOF)
00854 return 0;
00855 return 1;
00856 }
00857
00858 int xtra_kill(struct user_entry *e)
00859 {
00860 struct xtra_key *x, *y;
00861
00862 for (x = e->u.extra; x; x = y) {
00863 y = x->next;
00864 nfree(x->key);
00865 nfree(x->data);
00866 nfree(x);
00867 }
00868 nfree(e);
00869 return 1;
00870 }
00871
00872 static int xtra_tcl_get(Tcl_Interp * irp, struct userrec *u,
00873 struct user_entry *e, int argc, char **argv)
00874 {
00875 struct xtra_key *x;
00876
00877 BADARGS(3, 4, " handle XTRA ?key?");
00878
00879 if (argc == 4) {
00880 for (x = e->u.extra; x; x = x->next)
00881 if (!egg_strcasecmp(argv[3], x->key)) {
00882 Tcl_AppendResult(irp, x->data, NULL);
00883 return TCL_OK;
00884 }
00885 return TCL_OK;
00886 }
00887 for (x = e->u.extra; x; x = x->next) {
00888 char *p;
00889 EGG_CONST char *list[2];
00890
00891 list[0] = x->key;
00892 list[1] = x->data;
00893 p = Tcl_Merge(2, list);
00894 Tcl_AppendElement(irp, p);
00895 Tcl_Free((char *) p);
00896 }
00897 return TCL_OK;
00898 }
00899
00900 static int xtra_expmem(struct user_entry *e)
00901 {
00902 struct xtra_key *x;
00903 int tot = 0;
00904
00905 for (x = e->u.extra; x; x = x->next) {
00906 tot += sizeof(struct xtra_key);
00907
00908 tot += strlen(x->key) + 1;
00909 tot += strlen(x->data) + 1;
00910 }
00911 return tot;
00912 }
00913
00914 struct user_entry_type USERENTRY_XTRA = {
00915 0,
00916 xtra_gotshare,
00917 xtra_dupuser,
00918 xtra_unpack,
00919 xtra_pack,
00920 xtra_write_userfile,
00921 xtra_kill,
00922 def_get,
00923 xtra_set,
00924 xtra_tcl_get,
00925 xtra_tcl_set,
00926 xtra_expmem,
00927 xtra_display,
00928 "XTRA"
00929 };
00930
00931 static int hosts_dupuser(struct userrec *new, struct userrec *old,
00932 struct user_entry *e)
00933 {
00934 struct list_type *h;
00935
00936 for (h = e->u.extra; h; h = h->next)
00937 set_user(&USERENTRY_HOSTS, new, h->extra);
00938 return 1;
00939 }
00940
00941 static int hosts_null(struct userrec *u, struct user_entry *e)
00942 {
00943 return 1;
00944 }
00945
00946 static int hosts_write_userfile(FILE *f, struct userrec *u,
00947 struct user_entry *e)
00948 {
00949 struct list_type *h;
00950
00951 for (h = e->u.extra; h; h = h->next)
00952 if (fprintf(f, "--HOSTS %s\n", h->extra) == EOF)
00953 return 0;
00954 return 1;
00955 }
00956
00957 static int hosts_kill(struct user_entry *e)
00958 {
00959 list_type_kill(e->u.list);
00960 nfree(e);
00961 return 1;
00962 }
00963
00964 static int hosts_expmem(struct user_entry *e)
00965 {
00966 return list_type_expmem(e->u.list);
00967 }
00968
00969 static void hosts_display(int idx, struct user_entry *e)
00970 {
00971 char s[1024];
00972 struct list_type *q;
00973
00974 s[0] = 0;
00975 strcpy(s, " HOSTS: ");
00976 for (q = e->u.list; q; q = q->next) {
00977 if (s[0] && !s[9])
00978 strcat(s, q->extra);
00979 else if (!s[0])
00980 sprintf(s, " %s", q->extra);
00981 else {
00982 if (strlen(s) + strlen(q->extra) + 2 > 65) {
00983 dprintf(idx, "%s\n", s);
00984 sprintf(s, " %s", q->extra);
00985 } else {
00986 strcat(s, ", ");
00987 strcat(s, q->extra);
00988 }
00989 }
00990 }
00991 if (s[0])
00992 dprintf(idx, "%s\n", s);
00993 }
00994
00995 static int hosts_set(struct userrec *u, struct user_entry *e, void *buf)
00996 {
00997 if (!buf || !egg_strcasecmp(buf, "none")) {
00998
00999 list_type_kill(e->u.list);
01000 e->u.list = NULL;
01001 } else {
01002 char *host = buf, *p = strchr(host, ',');
01003 struct list_type **t;
01004
01005
01006 while (p) {
01007 *p = '?';
01008 p = strchr(host, ',');
01009 }
01010
01011
01012
01013 t = &(e->u.list);
01014 while (*t) {
01015 if (cmp_usermasks(host, (*t)->extra)) {
01016 struct list_type *u;
01017
01018 u = *t;
01019 *t = (*t)->next;
01020 if (u->extra)
01021 nfree(u->extra);
01022 nfree(u);
01023 } else
01024 t = &((*t)->next);
01025 }
01026 *t = user_malloc(sizeof(struct list_type));
01027
01028 (*t)->next = NULL;
01029 (*t)->extra = user_malloc(strlen(host) + 1);
01030 strcpy((*t)->extra, host);
01031 }
01032 return 1;
01033 }
01034
01035 static int hosts_tcl_get(Tcl_Interp * irp, struct userrec *u,
01036 struct user_entry *e, int argc, char **argv)
01037 {
01038 struct list_type *x;
01039
01040 BADARGS(3, 3, " handle HOSTS");
01041
01042 for (x = e->u.list; x; x = x->next)
01043 Tcl_AppendElement(irp, x->extra);
01044 return TCL_OK;
01045 }
01046
01047 static int hosts_tcl_set(Tcl_Interp * irp, struct userrec *u,
01048 struct user_entry *e, int argc, char **argv)
01049 {
01050 BADARGS(3, 4, " handle HOSTS ?host?");
01051
01052 if (argc == 4)
01053 addhost_by_handle(u->handle, argv[3]);
01054 else
01055 addhost_by_handle(u->handle, "none");
01056 return TCL_OK;
01057 }
01058
01059 static int hosts_gotshare(struct userrec *u, struct user_entry *e,
01060 char *buf, int idx)
01061 {
01062
01063 return 0;
01064 }
01065
01066 struct user_entry_type USERENTRY_HOSTS = {
01067 0,
01068 hosts_gotshare,
01069 hosts_dupuser,
01070 hosts_null,
01071 hosts_null,
01072 hosts_write_userfile,
01073 hosts_kill,
01074 def_get,
01075 hosts_set,
01076 hosts_tcl_get,
01077 hosts_tcl_set,
01078 hosts_expmem,
01079 hosts_display,
01080 "HOSTS"
01081 };
01082
01083 int egg_list_append(struct list_type **h, struct list_type *i)
01084 {
01085 for (; *h; h = &((*h)->next));
01086 *h = i;
01087 return 1;
01088 }
01089
01090 int egg_list_delete(struct list_type **h, struct list_type *i)
01091 {
01092 for (; *h; h = &((*h)->next))
01093 if (*h == i) {
01094 *h = i->next;
01095 return 1;
01096 }
01097 return 0;
01098 }
01099
01100 int egg_list_contains(struct list_type *h, struct list_type *i)
01101 {
01102 for (; h; h = h->next)
01103 if (h == i) {
01104 return 1;
01105 }
01106 return 0;
01107 }
01108
01109 int add_entry_type(struct user_entry_type *type)
01110 {
01111 struct userrec *u;
01112
01113 list_insert(&entry_type_list, type);
01114 for (u = userlist; u; u = u->next) {
01115 struct user_entry *e = find_user_entry(type, u);
01116
01117 if (e && e->name) {
01118 e->type = type;
01119 e->type->unpack(u, e);
01120 nfree(e->name);
01121 e->name = NULL;
01122 }
01123 }
01124 return 1;
01125 }
01126
01127 int del_entry_type(struct user_entry_type *type)
01128 {
01129 struct userrec *u;
01130
01131 for (u = userlist; u; u = u->next) {
01132 struct user_entry *e = find_user_entry(type, u);
01133
01134 if (e && !e->name) {
01135 e->type->pack(u, e);
01136 e->name = user_malloc(strlen(e->type->name) + 1);
01137 strcpy(e->name, e->type->name);
01138 e->type = NULL;
01139 }
01140 }
01141 return egg_list_delete((struct list_type **) &entry_type_list,
01142 (struct list_type *) type);
01143 }
01144
01145 struct user_entry_type *find_entry_type(char *name)
01146 {
01147 struct user_entry_type *p;
01148
01149 for (p = entry_type_list; p; p = p->next) {
01150 if (!egg_strcasecmp(name, p->name))
01151 return p;
01152 }
01153 return NULL;
01154 }
01155
01156 struct user_entry *find_user_entry(struct user_entry_type *et,
01157 struct userrec *u)
01158 {
01159 struct user_entry **e, *t;
01160
01161 for (e = &(u->entries); *e; e = &((*e)->next)) {
01162 if (((*e)->type == et) ||
01163 ((*e)->name && !egg_strcasecmp((*e)->name, et->name))) {
01164 t = *e;
01165 *e = t->next;
01166 t->next = u->entries;
01167 u->entries = t;
01168 return t;
01169 }
01170 }
01171 return NULL;
01172 }
01173
01174 void *get_user(struct user_entry_type *et, struct userrec *u)
01175 {
01176 struct user_entry *e;
01177
01178 if (u && (e = find_user_entry(et, u)))
01179 return et->get(u, e);
01180 return 0;
01181 }
01182
01183 int set_user(struct user_entry_type *et, struct userrec *u, void *d)
01184 {
01185 struct user_entry *e;
01186 int r;
01187
01188 if (!u || !et)
01189 return 0;
01190
01191 if (!(e = find_user_entry(et, u))) {
01192 e = user_malloc(sizeof(struct user_entry));
01193
01194 e->type = et;
01195 e->name = NULL;
01196 e->u.list = NULL;
01197 list_insert((&(u->entries)), e);
01198 }
01199 r = et->set(u, e, d);
01200 if (!e->u.list) {
01201 egg_list_delete((struct list_type **) &(u->entries), (struct list_type *) e);
01202 nfree(e);
01203 }
01204 return r;
01205 }