userent.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648
  1. /*
  2. * userent.c -- handles:
  3. * user-entry handling, new stylem more versatile.
  4. *
  5. */
  6. #include "main.h"
  7. #include "users.h"
  8. extern int noshare, cfg_noshare, cfg_count;
  9. extern struct cfg_entry **cfg;
  10. extern struct userrec *userlist;
  11. extern struct dcc_t *dcc;
  12. extern Tcl_Interp *interp;
  13. extern char whois_fields[], botnetnick[];
  14. extern time_t now;
  15. int share_greet = 0; /* Share greeting info */
  16. static struct user_entry_type *entry_type_list;
  17. void init_userent()
  18. {
  19. entry_type_list = 0;
  20. add_entry_type(&USERENTRY_COMMENT);
  21. add_entry_type(&USERENTRY_XTRA);
  22. add_entry_type(&USERENTRY_INFO);
  23. add_entry_type(&USERENTRY_LASTON);
  24. add_entry_type(&USERENTRY_BOTADDR);
  25. add_entry_type(&USERENTRY_PASS);
  26. add_entry_type(&USERENTRY_SECPASS);
  27. add_entry_type(&USERENTRY_HOSTS);
  28. add_entry_type(&USERENTRY_BOTFL);
  29. add_entry_type(&USERENTRY_STATS);
  30. add_entry_type(&USERENTRY_ADDED);
  31. add_entry_type(&USERENTRY_CONFIG);
  32. }
  33. void list_type_kill(struct list_type *t)
  34. {
  35. struct list_type *u;
  36. while (t) {
  37. u = t->next;
  38. if (t->extra)
  39. nfree(t->extra);
  40. nfree(t);
  41. t = u;
  42. }
  43. }
  44. int list_type_expmem(struct list_type *t)
  45. {
  46. int tot = 0;
  47. for (; t; t = t->next)
  48. tot += sizeof(struct list_type) + strlen(t->extra) + 1;
  49. return tot;
  50. }
  51. int def_unpack(struct userrec *u, struct user_entry *e)
  52. {
  53. char *tmp;
  54. tmp = e->u.list->extra;
  55. e->u.list->extra = NULL;
  56. list_type_kill(e->u.list);
  57. e->u.string = tmp;
  58. return 1;
  59. }
  60. int def_pack(struct userrec *u, struct user_entry *e)
  61. {
  62. char *tmp;
  63. tmp = e->u.string;
  64. e->u.list = user_malloc(sizeof(struct list_type));
  65. e->u.list->next = NULL;
  66. e->u.list->extra = tmp;
  67. return 1;
  68. }
  69. int def_kill(struct user_entry *e)
  70. {
  71. nfree(e->u.string);
  72. nfree(e);
  73. return 1;
  74. }
  75. int def_write_userfile(FILE * f, struct userrec *u, struct user_entry *e)
  76. {
  77. if (lfprintf(f, "--%s %s\n", e->type->name, e->u.string) == EOF)
  78. return 0;
  79. return 1;
  80. }
  81. void *def_get(struct userrec *u, struct user_entry *e)
  82. {
  83. return e->u.string;
  84. }
  85. int def_set(struct userrec *u, struct user_entry *e, void *buf)
  86. {
  87. char *string = (char *) buf;
  88. if (string && !string[0])
  89. string = NULL;
  90. if (!string && !e->u.string)
  91. return 1;
  92. if (string) {
  93. int l = strlen (string);
  94. char *i;
  95. if (l > 160)
  96. l = 160;
  97. e->u.string = user_realloc (e->u.string, l + 1);
  98. strncpyz (e->u.string, string, l + 1);
  99. for (i = e->u.string; *i; i++)
  100. /* Allow bold, inverse, underline, color text here...
  101. * But never add cr or lf!! --rtc
  102. */
  103. if ((unsigned int) *i < 32 && !strchr ("\002\003\026\037", *i))
  104. *i = '?';
  105. } else { /* string == NULL && e->u.string != NULL */
  106. nfree(e->u.string);
  107. e->u.string = NULL;
  108. }
  109. if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED))) {
  110. if (e->type != &USERENTRY_INFO || share_greet)
  111. shareout(NULL, "c %s %s %s\n", e->type->name, u->handle,
  112. e->u.string ? e->u.string : "");
  113. }
  114. return 1;
  115. }
  116. int def_gotshare(struct userrec *u, struct user_entry *e,
  117. char *data, int idx)
  118. {
  119. #ifdef HUB
  120. putlog(LOG_CMDS, "@", "%s: change %s %s", dcc[idx].nick, e->type->name,
  121. u->handle);
  122. #endif
  123. return e->type->set(u, e, data);
  124. }
  125. int def_tcl_get(Tcl_Interp * interp, struct userrec *u,
  126. struct user_entry *e, int argc, char **argv)
  127. {
  128. Tcl_AppendResult(interp, e->u.string, NULL);
  129. return TCL_OK;
  130. }
  131. int def_tcl_set(Tcl_Interp * irp, struct userrec *u,
  132. struct user_entry *e, int argc, char **argv)
  133. {
  134. BADARGS(4, 4, " handle type setting");
  135. e->type->set(u, e, argv[3]);
  136. return TCL_OK;
  137. }
  138. int def_expmem(struct user_entry *e)
  139. {
  140. return strlen(e->u.string) + 1;
  141. }
  142. void def_display(int idx, struct user_entry *e, struct userrec *u)
  143. {
  144. dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
  145. }
  146. int def_dupuser(struct userrec *new, struct userrec *old,
  147. struct user_entry *e)
  148. {
  149. return set_user(e->type, new, e->u.string);
  150. }
  151. static void comment_display(int idx, struct user_entry *e, struct userrec *u)
  152. {
  153. if (dcc[idx].user && (dcc[idx].user->flags & USER_MASTER))
  154. dprintf(idx, " COMMENT: %s\n", e->u.string);
  155. }
  156. struct user_entry_type USERENTRY_COMMENT =
  157. {
  158. 0, /* always 0 ;) */
  159. def_gotshare,
  160. def_dupuser,
  161. def_unpack,
  162. def_pack,
  163. def_write_userfile,
  164. def_kill,
  165. def_get,
  166. def_set,
  167. def_tcl_get,
  168. def_tcl_set,
  169. def_expmem,
  170. comment_display,
  171. "COMMENT"
  172. };
  173. struct user_entry_type USERENTRY_INFO =
  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. def_expmem,
  187. def_display,
  188. "INFO"
  189. };
  190. void added_display(int idx, struct user_entry *e, struct userrec *u)
  191. {
  192. /* format: unixtime handle */
  193. if (dcc[idx].user && (dcc[idx].user->flags & USER_OWNER)) {
  194. char tmp[30],
  195. tmp2[70],
  196. *hnd;
  197. time_t tm;
  198. strncpy0(tmp, e->u.string, sizeof(tmp));
  199. hnd = strchr(tmp, ' ');
  200. if (hnd)
  201. *hnd++ = 0;
  202. tm = atoi(tmp);
  203. strftime(tmp2, sizeof(tmp2), STR("%a, %d %b %Y %H:%M:%S GMT"), gmtime(&tm));
  204. if (hnd)
  205. dprintf(idx, STR(" -- Added %s by %s\n"), tmp2, hnd);
  206. else
  207. dprintf(idx, STR(" -- Added %s\n"), tmp2);
  208. }
  209. }
  210. int added_gotshare(struct userrec *u, struct user_entry *e, char *data, int idx)
  211. {
  212. return e->type->set(u, e, data);
  213. }
  214. struct user_entry_type USERENTRY_ADDED = {
  215. 0, /* always 0 ;) */
  216. added_gotshare,
  217. def_dupuser,
  218. def_unpack,
  219. def_pack,
  220. def_write_userfile,
  221. def_kill,
  222. def_get,
  223. def_set,
  224. 0,
  225. 0,
  226. def_expmem,
  227. added_display,
  228. "ADDED"
  229. };
  230. int config_set(struct userrec *u, struct user_entry *e, void *buf)
  231. {
  232. struct xtra_key *curr,
  233. *old = NULL,
  234. *new = buf;
  235. for (curr = e->u.extra; curr; curr = curr->next) {
  236. if (curr->key && !egg_strcasecmp(curr->key, new->key)) {
  237. old = curr;
  238. break;
  239. }
  240. }
  241. if (!old && (!new->data || !new->data[0])) {
  242. /* delete non-existant entry -- doh ++rtc */
  243. nfree(new->key);
  244. if (new->data)
  245. nfree(new->data);
  246. nfree(new);
  247. return 1;
  248. }
  249. /* we will possibly free new below, so let's send the information
  250. * to the botnet now */
  251. if (!noshare && !cfg_noshare) {
  252. shareout(NULL, STR("c CONFIG %s %s %s\n"), u->handle, new->key, new->data ? new->data : "");
  253. }
  254. if ((old && old != new) || !new->data || !new->data[0]) {
  255. list_delete((struct list_type **) (&e->u.extra), (struct list_type *) old);
  256. nfree(old->key);
  257. nfree(old->data);
  258. nfree(old);
  259. }
  260. if (old != new && new->data) {
  261. if (new->data[0]) {
  262. list_insert((&e->u.extra), new);
  263. } else {
  264. nfree(new->data);
  265. nfree(new->key);
  266. nfree(new);
  267. }
  268. }
  269. return 1;
  270. }
  271. int config_unpack(struct userrec *u, struct user_entry *e)
  272. {
  273. struct list_type *curr,
  274. *head;
  275. struct xtra_key *t;
  276. char *key,
  277. *data;
  278. head = curr = e->u.list;
  279. e->u.extra = NULL;
  280. while (curr) {
  281. t = user_malloc(sizeof(struct xtra_key));
  282. data = curr->extra;
  283. key = newsplit(&data);
  284. if (data[0]) {
  285. t->key = user_malloc(strlen(key) + 1);
  286. strcpy(t->key, key);
  287. t->data = user_malloc(strlen(data) + 1);
  288. strcpy(t->data, data);
  289. list_insert((&e->u.extra), t);
  290. }
  291. curr = curr->next;
  292. }
  293. list_type_kill(head);
  294. return 1;
  295. }
  296. int config_pack(struct userrec *u, struct user_entry *e)
  297. {
  298. struct list_type *t;
  299. struct xtra_key *curr,
  300. *next;
  301. curr = e->u.extra;
  302. e->u.list = NULL;
  303. while (curr) {
  304. t = user_malloc(sizeof(struct list_type));
  305. t->extra = user_malloc(strlen(curr->key) + strlen(curr->data) + 4);
  306. sprintf(t->extra, STR("%s %s"), curr->key, curr->data);
  307. list_insert((&e->u.list), t);
  308. next = curr->next;
  309. nfree(curr->key);
  310. nfree(curr->data);
  311. nfree(curr);
  312. curr = next;
  313. }
  314. return 1;
  315. }
  316. void config_display(int idx, struct user_entry *e, struct userrec *u)
  317. {
  318. #ifdef HUB
  319. struct xtra_key *xk;
  320. struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
  321. get_user_flagrec(dcc[idx].user, &fr, NULL);
  322. /* scan thru xtra field, searching for matches */
  323. for (xk = e->u.extra; xk; xk = xk->next) {
  324. /* ok, it's a valid xtra field entry */
  325. if (glob_owner(fr))
  326. dprintf(idx, STR(" %s: %s\n"), xk->key, xk->data);
  327. }
  328. #endif
  329. }
  330. int config_gotshare(struct userrec *u, struct user_entry *e, char *buf, int idx)
  331. {
  332. char *arg;
  333. struct xtra_key *xk;
  334. int l;
  335. arg = newsplit(&buf);
  336. if (!arg[0])
  337. return 1;
  338. if (!strcmp(u->handle, botnetnick)) {
  339. struct cfg_entry *cfgent = NULL;
  340. int i;
  341. cfg_noshare++;
  342. for (i = 0; !cfgent && (i < cfg_count); i++)
  343. if (!strcmp(arg, cfg[i]->name) && (cfg[i]->flags & CFGF_LOCAL))
  344. cfgent = cfg[i];
  345. if (cfgent) {
  346. set_cfg_str(botnetnick, cfgent->name, buf[0] ? buf : NULL);
  347. }
  348. cfg_noshare--;
  349. return 1;
  350. }
  351. xk = user_malloc(sizeof(struct xtra_key));
  352. egg_bzero(xk, sizeof(struct xtra_key));
  353. l = strlen(arg);
  354. if (l > 1500)
  355. l = 1500;
  356. xk->key = user_malloc(l + 1);
  357. strncpy0(xk->key, arg, l + 1);
  358. if (buf[0]) {
  359. int k = strlen(buf);
  360. if (k > 1500 - l)
  361. k = 1500 - l;
  362. xk->data = user_malloc(k + 1);
  363. strncpy0(xk->data, buf, k + 1);
  364. }
  365. config_set(u, e, xk);
  366. return 1;
  367. }
  368. int config_dupuser(struct userrec *new, struct userrec *old, struct user_entry *e)
  369. {
  370. struct xtra_key *x1,
  371. *x2;
  372. for (x1 = e->u.extra; x1; x1 = x1->next) {
  373. x2 = user_malloc(sizeof(struct xtra_key));
  374. x2->key = user_malloc(strlen(x1->key) + 1);
  375. strcpy(x2->key, x1->key);
  376. x2->data = user_malloc(strlen(x1->data) + 1);
  377. strcpy(x2->data, x1->data);
  378. set_user(&USERENTRY_CONFIG, new, x2);
  379. }
  380. return 1;
  381. }
  382. int config_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
  383. {
  384. struct xtra_key *x;
  385. for (x = e->u.extra; x; x = x->next)
  386. lfprintf(f, STR("--CONFIG %s %s\n"), x->key, x->data);
  387. return 1;
  388. }
  389. int config_kill(struct user_entry *e)
  390. {
  391. struct xtra_key *x,
  392. *y;
  393. for (x = e->u.extra; x; x = y) {
  394. y = x->next;
  395. nfree(x->key);
  396. nfree(x->data);
  397. nfree(x);
  398. }
  399. nfree(e);
  400. return 1;
  401. }
  402. /* FIXME: possible expmem leak here */
  403. int config_expmem(struct user_entry *e)
  404. {
  405. struct xtra_key *x;
  406. int tot = 0;
  407. for (x = e->u.extra; x; x = x->next) {
  408. tot += sizeof(struct xtra_key);
  409. tot += strlen(x->key) + 1;
  410. tot += strlen(x->data) + 1;
  411. }
  412. return tot;
  413. }
  414. struct user_entry_type USERENTRY_CONFIG = {
  415. 0,
  416. config_gotshare,
  417. config_dupuser,
  418. config_unpack,
  419. config_pack,
  420. config_write_userfile,
  421. config_kill,
  422. def_get,
  423. config_set,
  424. 0,
  425. 0,
  426. config_expmem,
  427. config_display,
  428. "CONFIG"
  429. };
  430. void stats_add(struct userrec *u, int login, int op)
  431. {
  432. char *s,
  433. s2[50];
  434. int sl,
  435. so;
  436. if (!u)
  437. return;
  438. s = get_user(&USERENTRY_STATS, u);
  439. if (s) {
  440. strncpy0(s2, s, sizeof(s2));
  441. } else
  442. strcpy(s2, STR("0 0"));
  443. s = strchr(s2, ' ');
  444. if (s) {
  445. s++;
  446. so = atoi(s);
  447. } else
  448. so = 0;
  449. sl = atoi(s2);
  450. if (login)
  451. sl++;
  452. if (op)
  453. so++;
  454. sprintf(s2, STR("%i %i"), sl, so);
  455. set_user(&USERENTRY_STATS, u, s2);
  456. }
  457. void stats_display(int idx, struct user_entry *e, struct userrec *u)
  458. {
  459. /* format: logincount opcount */
  460. if (dcc[idx].user && (dcc[idx].user->flags & USER_OWNER)) {
  461. char *p;
  462. p = strchr(e->u.string, ' ');
  463. if (p)
  464. dprintf(idx, STR(" -- %i logins, %i ops\n"), atoi(e->u.string), atoi(p));
  465. }
  466. }
  467. int stats_gotshare(struct userrec *u, struct user_entry *e, char *data, int idx)
  468. {
  469. return e->type->set(u, e, data);
  470. }
  471. struct user_entry_type USERENTRY_STATS = {
  472. 0, /* always 0 ;) */
  473. stats_gotshare,
  474. def_dupuser,
  475. def_unpack,
  476. def_pack,
  477. def_write_userfile,
  478. def_kill,
  479. def_get,
  480. def_set,
  481. 0,
  482. 0,
  483. def_expmem,
  484. stats_display,
  485. "STATS"
  486. };
  487. int pass_set(struct userrec *u, struct user_entry *e, void *buf)
  488. {
  489. char new[32];
  490. register char *pass = buf;
  491. if (e->u.extra)
  492. nfree(e->u.extra);
  493. if (!pass || !pass[0] || (pass[0] == '-'))
  494. e->u.extra = NULL;
  495. else {
  496. unsigned char *p = (unsigned char *) pass;
  497. if (strlen(pass) > 15)
  498. pass[15] = 0;
  499. while (*p) {
  500. if ((*p <= 32) || (*p == 127))
  501. *p = '?';
  502. p++;
  503. }
  504. if ((u->flags & USER_BOT) || (pass[0] == '+'))
  505. strcpy(new, pass);
  506. else
  507. encrypt_pass(pass, new);
  508. e->u.extra = user_malloc(strlen(new) + 1);
  509. strcpy(e->u.extra, new);
  510. }
  511. if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
  512. shareout(NULL, "c PASS %s %s\n", u->handle, pass ? pass : "");
  513. return 1;
  514. }
  515. static int pass_tcl_set(Tcl_Interp * irp, struct userrec *u,
  516. struct user_entry *e, int argc, char **argv)
  517. {
  518. BADARGS(3, 4, " handle PASS ?newpass?");
  519. pass_set(u, e, argc == 3 ? NULL : argv[3]);
  520. return TCL_OK;
  521. }
  522. struct user_entry_type USERENTRY_PASS =
  523. {
  524. 0,
  525. def_gotshare,
  526. 0,
  527. def_unpack,
  528. def_pack,
  529. def_write_userfile,
  530. def_kill,
  531. def_get,
  532. pass_set,
  533. def_tcl_get,
  534. pass_tcl_set,
  535. def_expmem,
  536. 0,
  537. "PASS"
  538. };
  539. void secpass_display(int idx, struct user_entry *e, struct userrec *u)
  540. {
  541. struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
  542. get_user_flagrec(dcc[idx].user, &fr, NULL);
  543. if (!strcmp(u->handle, dcc[idx].nick) || glob_admin(fr)) {
  544. #ifdef HUB
  545. dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
  546. #else
  547. dprintf(idx, " %s: Hidden on leaf bots.", e->type->name);
  548. if (dcc[idx].u.chat->su_nick)
  549. dprintf(idx, " Nice try, %s.", dcc[idx].u.chat->su_nick);
  550. dprintf(idx, "\n");
  551. #endif /* HUB */
  552. }
  553. }
  554. struct user_entry_type USERENTRY_SECPASS =
  555. {
  556. 0,
  557. def_gotshare,
  558. def_dupuser,
  559. def_unpack,
  560. def_pack,
  561. def_write_userfile,
  562. def_kill,
  563. def_get,
  564. def_set,
  565. 0,
  566. 0,
  567. def_expmem,
  568. secpass_display,
  569. "SECPASS"
  570. };
  571. static int laston_unpack(struct userrec *u, struct user_entry *e)
  572. {
  573. char *par, *arg;
  574. struct laston_info *li;
  575. par = e->u.list->extra;
  576. arg = newsplit (&par);
  577. if (!par[0])
  578. par = "???";
  579. li = user_malloc(sizeof(struct laston_info));
  580. li->lastonplace = user_malloc(strlen(par) + 1);
  581. li->laston = atoi(arg);
  582. strcpy(li->lastonplace, par);
  583. list_type_kill(e->u.list);
  584. e->u.extra = li;
  585. return 1;
  586. }
  587. static int laston_pack(struct userrec *u, struct user_entry *e)
  588. {
  589. char work[1024];
  590. struct laston_info *li;
  591. int l;
  592. li = (struct laston_info *) e->u.extra;
  593. l = sprintf(work, "%lu %s", li->laston, li->lastonplace);
  594. e->u.list = user_malloc(sizeof(struct list_type));
  595. e->u.list->next = NULL;
  596. e->u.list->extra = user_malloc(l + 1);
  597. strcpy(e->u.list->extra, work);
  598. nfree(li->lastonplace);
  599. nfree(li);
  600. return 1;
  601. }
  602. static int laston_write_userfile(FILE * f,
  603. struct userrec *u,
  604. struct user_entry *e)
  605. {
  606. struct laston_info *li = (struct laston_info *) e->u.extra;
  607. if (lfprintf(f, "--LASTON %lu %s\n", li->laston,
  608. li->lastonplace ? li->lastonplace : "") == EOF)
  609. return 0;
  610. return 1;
  611. }
  612. static int laston_kill(struct user_entry *e)
  613. {
  614. if (((struct laston_info *) (e->u.extra))->lastonplace)
  615. nfree(((struct laston_info *) (e->u.extra))->lastonplace);
  616. nfree(e->u.extra);
  617. nfree(e);
  618. return 1;
  619. }
  620. static int laston_set(struct userrec *u, struct user_entry *e, void *buf)
  621. {
  622. struct laston_info *li = (struct laston_info *) e->u.extra;
  623. if (li != buf) {
  624. if (li) {
  625. nfree(li->lastonplace);
  626. nfree(li);
  627. }
  628. li = e->u.extra = buf;
  629. }
  630. /* donut share laston info */
  631. return 1;
  632. }
  633. static int laston_tcl_get(Tcl_Interp * irp, struct userrec *u,
  634. struct user_entry *e, int argc, char **argv)
  635. {
  636. struct laston_info *li = (struct laston_info *) e->u.extra;
  637. char number[20];
  638. struct chanuserrec *cr;
  639. BADARGS(3, 4, " handle LASTON ?channel?");
  640. if (argc == 4) {
  641. for (cr = u->chanrec; cr; cr = cr->next)
  642. if (!rfc_casecmp(cr->channel, argv[3])) {
  643. Tcl_AppendResult(irp, int_to_base10(cr->laston), NULL);
  644. break;
  645. }
  646. if (!cr)
  647. Tcl_AppendResult(irp, "0", NULL);
  648. } else {
  649. sprintf(number, "%lu ", li->laston);
  650. Tcl_AppendResult(irp, number, li->lastonplace, NULL);
  651. }
  652. return TCL_OK;
  653. }
  654. static int laston_tcl_set(Tcl_Interp * irp, struct userrec *u,
  655. struct user_entry *e, int argc, char **argv)
  656. {
  657. struct laston_info *li;
  658. struct chanuserrec *cr;
  659. BADARGS(4, 5, " handle LASTON time ?place?");
  660. if ((argc == 5) && argv[4][0] && strchr(CHANMETA, argv[4][0])) {
  661. /* Search for matching channel */
  662. for (cr = u->chanrec; cr; cr = cr->next)
  663. if (!rfc_casecmp(cr->channel, argv[4])) {
  664. cr->laston = atoi(argv[3]);
  665. break;
  666. }
  667. }
  668. /* Save globally */
  669. li = user_malloc(sizeof(struct laston_info));
  670. if (argc == 5) {
  671. li->lastonplace = user_malloc(strlen(argv[4]) + 1);
  672. strcpy(li->lastonplace, argv[4]);
  673. } else {
  674. li->lastonplace = user_malloc(1);
  675. li->lastonplace[0] = 0;
  676. }
  677. li->laston = atoi(argv[3]);
  678. set_user(&USERENTRY_LASTON, u, li);
  679. return TCL_OK;
  680. }
  681. /* FIXME: possible expmem leak here */
  682. static int laston_expmem(struct user_entry *e)
  683. {
  684. return sizeof(struct laston_info) +
  685. strlen(((struct laston_info *) (e->u.extra))->lastonplace) + 1;
  686. }
  687. static int laston_dupuser(struct userrec *new, struct userrec *old,
  688. struct user_entry *e)
  689. {
  690. struct laston_info *li = e->u.extra, *li2;
  691. if (li) {
  692. li2 = user_malloc(sizeof(struct laston_info));
  693. li2->laston = li->laston;
  694. li2->lastonplace = user_malloc(strlen(li->lastonplace) + 1);
  695. strcpy(li2->lastonplace, li->lastonplace);
  696. return set_user(&USERENTRY_LASTON, new, li2);
  697. }
  698. return 0;
  699. }
  700. struct user_entry_type USERENTRY_LASTON =
  701. {
  702. 0, /* always 0 ;) */
  703. 0,
  704. laston_dupuser,
  705. laston_unpack,
  706. laston_pack,
  707. laston_write_userfile,
  708. laston_kill,
  709. def_get,
  710. laston_set,
  711. laston_tcl_get,
  712. laston_tcl_set,
  713. laston_expmem,
  714. 0,
  715. "LASTON"
  716. };
  717. static int botaddr_unpack(struct userrec *u, struct user_entry *e)
  718. {
  719. char p[1024],
  720. *q1,
  721. *q2;
  722. struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
  723. bzero(bi, sizeof(struct bot_addr));
  724. /* address:port/port:hublevel:uplink */
  725. Context;
  726. Assert(e);
  727. Assert(e->name);
  728. bzero(bi, sizeof(struct bot_addr));
  729. strcpy(p, e->u.list->extra);
  730. q1 = strchr(p, ':');
  731. if (q1)
  732. *q1++ = 0;
  733. bi->address = user_malloc(strlen(p) + 1);
  734. strcpy(bi->address, p);
  735. if (q1) {
  736. q2 = strchr(q1, ':');
  737. if (q2)
  738. *q2++ = 0;
  739. bi->telnet_port = atoi(q1);
  740. q1 = strchr(q1, '/');
  741. if (q1) {
  742. q1++;
  743. bi->relay_port = atoi(q1);
  744. }
  745. if (q2) {
  746. q1 = strchr(q2, ':');
  747. if (q1) {
  748. *q1++ = 0;
  749. bi->uplink = user_malloc(strlen(q1) + 1);
  750. strcpy(bi->uplink, q1);
  751. }
  752. bi->hublevel = atoi(q2);
  753. }
  754. }
  755. if (!bi->telnet_port)
  756. bi->telnet_port = 3333;
  757. if (!bi->relay_port)
  758. bi->relay_port = bi->telnet_port;
  759. if (!bi->uplink) {
  760. bi->uplink = user_malloc(1);
  761. bi->uplink[0] = 0;
  762. }
  763. list_type_kill(e->u.list);
  764. e->u.extra = bi;
  765. return 1;
  766. }
  767. static int botaddr_pack(struct userrec *u, struct user_entry *e)
  768. {
  769. char work[1024];
  770. struct bot_addr *bi;
  771. int l;
  772. Assert(e);
  773. Assert(!e->name);
  774. bi = (struct bot_addr *) e->u.extra;
  775. l = simple_sprintf(work, STR("%s:%u/%u:%u:%s"), bi->address, bi->telnet_port, bi->relay_port, bi->hublevel, bi->uplink);
  776. e->u.list = user_malloc(sizeof(struct list_type));
  777. e->u.list->next = NULL;
  778. e->u.list->extra = user_malloc(l + 1);
  779. strcpy(e->u.list->extra, work);
  780. nfree(bi->address);
  781. nfree(bi->uplink);
  782. nfree(bi);
  783. return 1;
  784. }
  785. static int botaddr_kill(struct user_entry *e)
  786. {
  787. nfree(((struct bot_addr *) (e->u.extra))->address);
  788. nfree(((struct bot_addr *) (e->u.extra))->uplink);
  789. nfree(e->u.extra);
  790. nfree(e);
  791. return 1;
  792. }
  793. static int botaddr_write_userfile(FILE *f, struct userrec *u,
  794. struct user_entry *e)
  795. {
  796. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  797. if (lfprintf(f, "--%s %s:%u/%u:%u:%s\n", e->type->name, bi->address,
  798. bi->telnet_port, bi->relay_port, bi->hublevel, bi->uplink) == EOF)
  799. return 0;
  800. return 1;
  801. }
  802. static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
  803. {
  804. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  805. Context;
  806. if (!bi && !buf)
  807. return 1;
  808. if (bi != buf) {
  809. if (bi) {
  810. Assert(bi->address);
  811. nfree(bi->address);
  812. Assert(bi->uplink);
  813. nfree(bi->uplink);
  814. nfree(bi);
  815. }
  816. ContextNote("(sharebug) occurred in botaddr_set");
  817. bi = e->u.extra = buf;
  818. }
  819. Assert(u);
  820. if (bi && !noshare && !(u->flags & USER_UNSHARED)) {
  821. shareout(NULL, STR("c BOTADDR %s %s %d %d %d %s\n"),u->handle, (bi->address && bi->address[0]) ? bi->address : STR("127.0.0.1"), bi->telnet_port, bi->relay_port, bi->hublevel, bi->uplink);
  822. }
  823. return 1;
  824. }
  825. static int botaddr_tcl_get(Tcl_Interp *interp, struct userrec *u,
  826. struct user_entry *e, int argc, char **argv)
  827. {
  828. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  829. char number[20];
  830. Context;
  831. sprintf(number, STR(" %d"), bi->telnet_port);
  832. Tcl_AppendResult(interp, bi->address, number, NULL);
  833. sprintf(number, STR(" %d"), bi->relay_port);
  834. Tcl_AppendResult(interp, number, NULL);
  835. sprintf(number, STR(" %d"), bi->hublevel);
  836. Tcl_AppendResult(interp, number, NULL);
  837. Tcl_AppendResult(interp, bi->uplink, NULL);
  838. return TCL_OK;
  839. }
  840. static int botaddr_tcl_set(Tcl_Interp *irp, struct userrec *u,
  841. struct user_entry *e, int argc, char **argv)
  842. {
  843. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  844. BADARGS(4, 6, " handle type address ?telnetport ?relayport??");
  845. if (u->flags & USER_BOT) {
  846. /* Silently ignore for users */
  847. if (!bi) {
  848. bi = user_malloc(sizeof(struct bot_addr));
  849. egg_bzero(bi, sizeof (struct bot_addr));
  850. } else {
  851. nfree(bi->address);
  852. }
  853. bi->address = user_malloc(strlen(argv[3]) + 1);
  854. strcpy(bi->address, argv[3]);
  855. if (argc > 4)
  856. bi->telnet_port = atoi(argv[4]);
  857. if (argc > 5)
  858. bi->relay_port = atoi(argv[5]);
  859. if (!bi->telnet_port)
  860. bi->telnet_port = 3333;
  861. if (!bi->relay_port)
  862. bi->relay_port = bi->telnet_port;
  863. botaddr_set(u, e, bi);
  864. }
  865. return TCL_OK;
  866. }
  867. /* FIXME: possible expmem leak here */
  868. static int botaddr_expmem(struct user_entry *e)
  869. {
  870. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  871. Context;
  872. return strlen(bi->address) + 1 + strlen(bi->uplink) + 1 + sizeof(struct bot_addr);
  873. }
  874. static void botaddr_display(int idx, struct user_entry *e, struct userrec *u)
  875. {
  876. #ifdef HUB
  877. struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
  878. get_user_flagrec(dcc[idx].user, &fr, NULL);
  879. if (glob_admin(fr)) {
  880. register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
  881. dprintf(idx, STR(" ADDRESS: %.70s\n"), bi->address);
  882. dprintf(idx, STR(" telnet: %d, relay: %d\n"), bi->telnet_port, bi->relay_port);
  883. dprintf(idx, STR(" hublevel: %d, uplink: %s\n"), bi->hublevel, bi->uplink);
  884. }
  885. #endif
  886. }
  887. static int botaddr_gotshare(struct userrec *u, struct user_entry *e,
  888. char *buf, int idx)
  889. {
  890. struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
  891. char *arg;
  892. bzero(bi, sizeof(struct bot_addr));
  893. arg = newsplit(&buf);
  894. bi->address = user_malloc(strlen(arg) + 1);
  895. strcpy(bi->address, arg);
  896. arg = newsplit(&buf);
  897. bi->telnet_port = atoi(arg);
  898. arg = newsplit(&buf);
  899. bi->relay_port = atoi(arg);
  900. arg = newsplit(&buf);
  901. bi->hublevel = atoi(arg);
  902. bi->uplink = user_malloc(strlen(buf) + 1);
  903. strcpy(bi->uplink, buf);
  904. if (!bi->telnet_port)
  905. bi->telnet_port = 3333;
  906. if (!bi->relay_port)
  907. bi->relay_port = bi->telnet_port;
  908. return botaddr_set(u, e, bi);
  909. }
  910. static int botaddr_dupuser(struct userrec *new, struct userrec *old,
  911. struct user_entry *e)
  912. {
  913. if (old->flags & USER_BOT) {
  914. struct bot_addr *bi = e->u.extra,
  915. *bi2;
  916. if (bi) {
  917. bi2 = user_malloc(sizeof(struct bot_addr));
  918. bi2->telnet_port = bi->telnet_port;
  919. bi2->relay_port = bi->relay_port;
  920. bi2->hublevel = bi->hublevel;
  921. bi2->address = user_malloc(strlen(bi->address) + 1);
  922. bi2->uplink = user_malloc(strlen(bi->uplink) + 1);
  923. strcpy(bi2->address, bi->address);
  924. strcpy(bi2->uplink, bi->uplink);
  925. return set_user(&USERENTRY_BOTADDR, new, bi2);
  926. }
  927. }
  928. return 0;
  929. }
  930. struct user_entry_type USERENTRY_BOTADDR =
  931. {
  932. 0, /* always 0 ;) */
  933. botaddr_gotshare,
  934. botaddr_dupuser,
  935. botaddr_unpack,
  936. botaddr_pack,
  937. botaddr_write_userfile,
  938. botaddr_kill,
  939. def_get,
  940. botaddr_set,
  941. botaddr_tcl_get,
  942. botaddr_tcl_set,
  943. botaddr_expmem,
  944. botaddr_display,
  945. "BOTADDR"
  946. };
  947. int xtra_set(struct userrec *u, struct user_entry *e, void *buf)
  948. {
  949. struct xtra_key *curr, *old = NULL, *new = buf;
  950. for (curr = e->u.extra; curr; curr = curr->next) {
  951. if (curr->key && !egg_strcasecmp(curr->key, new->key)) {
  952. old = curr;
  953. break;
  954. }
  955. }
  956. if (!old && (!new->data || !new->data[0])) {
  957. /* Delete non-existant entry -- doh ++rtc */
  958. nfree(new->key);
  959. if (new->data)
  960. nfree(new->data);
  961. nfree(new);
  962. return TCL_OK;
  963. }
  964. /* We will possibly free new below, so let's send the information
  965. * to the botnet now
  966. */
  967. if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
  968. shareout(NULL, "c XTRA %s %s %s\n", u->handle, new->key,
  969. new->data ? new->data : "");
  970. if ((old && old != new) || !new->data || !new->data[0]) {
  971. list_delete((struct list_type **) (&e->u.extra),
  972. (struct list_type *) old);
  973. nfree(old->key);
  974. nfree(old->data);
  975. nfree(old);
  976. }
  977. if (old != new && new->data) {
  978. if (new->data[0])
  979. list_insert((&e->u.extra), new) /* do not add a ';' here */
  980. } else {
  981. if (new->data)
  982. nfree(new->data);
  983. nfree(new->key);
  984. nfree(new);
  985. }
  986. return TCL_OK;
  987. }
  988. static int xtra_tcl_set(Tcl_Interp * irp, struct userrec *u,
  989. struct user_entry *e, int argc, char **argv)
  990. {
  991. struct xtra_key *xk;
  992. int l;
  993. BADARGS(4, 5, " handle type key ?value?");
  994. xk = user_malloc(sizeof(struct xtra_key));
  995. l = strlen(argv[3]);
  996. egg_bzero(xk, sizeof (struct xtra_key));
  997. if (l > 500)
  998. l = 500;
  999. xk->key = user_malloc(l + 1);
  1000. strncpyz(xk->key, argv[3], l + 1);
  1001. if (argc == 5) {
  1002. int k = strlen(argv[4]);
  1003. if (k > 500 - l)
  1004. k = 500 - l;
  1005. xk->data = user_malloc(k + 1);
  1006. strncpyz(xk->data, argv[4], k + 1);
  1007. }
  1008. xtra_set(u, e, xk);
  1009. return TCL_OK;
  1010. }
  1011. int xtra_unpack(struct userrec *u, struct user_entry *e)
  1012. {
  1013. struct list_type *curr, *head;
  1014. struct xtra_key *t;
  1015. char *key, *data;
  1016. Context;
  1017. head = curr = e->u.list;
  1018. e->u.extra = NULL;
  1019. while (curr) {
  1020. t = user_malloc(sizeof(struct xtra_key));
  1021. data = curr->extra;
  1022. key = newsplit(&data);
  1023. if (data[0]) {
  1024. t->key = user_malloc(strlen(key) + 1);
  1025. strcpy(t->key, key);
  1026. t->data = user_malloc(strlen(data) + 1);
  1027. strcpy(t->data, data);
  1028. list_insert((&e->u.extra), t);
  1029. }
  1030. curr = curr->next;
  1031. }
  1032. list_type_kill(head);
  1033. return 1;
  1034. }
  1035. static int xtra_pack(struct userrec *u, struct user_entry *e)
  1036. {
  1037. struct list_type *t;
  1038. struct xtra_key *curr, *next;
  1039. curr = e->u.extra;
  1040. e->u.list = NULL;
  1041. while (curr) {
  1042. t = user_malloc(sizeof(struct list_type));
  1043. t->extra = user_malloc(strlen(curr->key) + strlen(curr->data) + 4);
  1044. sprintf(t->extra, "%s %s", curr->key, curr->data);
  1045. list_insert((&e->u.list), t);
  1046. next = curr->next;
  1047. nfree(curr->key);
  1048. nfree(curr->data);
  1049. nfree(curr);
  1050. curr = next;
  1051. }
  1052. return 1;
  1053. }
  1054. static void xtra_display(int idx, struct user_entry *e, struct userrec *u)
  1055. {
  1056. int code, lc, j;
  1057. struct xtra_key *xk;
  1058. #if ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))
  1059. CONST char **list;
  1060. #else
  1061. char **list;
  1062. #endif
  1063. code = Tcl_SplitList(interp, whois_fields, &lc, &list);
  1064. if (code == TCL_ERROR)
  1065. return;
  1066. /* Scan thru xtra field, searching for matches */
  1067. for (xk = e->u.extra; xk; xk = xk->next) {
  1068. /* Ok, it's a valid xtra field entry */
  1069. for (j = 0; j < lc; j++) {
  1070. if (!egg_strcasecmp(list[j], xk->key))
  1071. dprintf(idx, " %s: %s\n", xk->key, xk->data);
  1072. }
  1073. }
  1074. Tcl_Free((char *) list);
  1075. }
  1076. static int xtra_gotshare(struct userrec *u, struct user_entry *e,
  1077. char *buf, int idx)
  1078. {
  1079. char *arg;
  1080. struct xtra_key *xk;
  1081. int l;
  1082. arg = newsplit (&buf);
  1083. if (!arg[0])
  1084. return 1;
  1085. xk = user_malloc (sizeof(struct xtra_key));
  1086. egg_bzero(xk, sizeof(struct xtra_key));
  1087. l = strlen(arg);
  1088. if (l > 500)
  1089. l = 500;
  1090. xk->key = user_malloc(l + 1);
  1091. strncpyz(xk->key, arg, l + 1);
  1092. if (buf[0]) {
  1093. int k = strlen(buf);
  1094. if (k > 500 - l)
  1095. k = 500 - l;
  1096. xk->data = user_malloc(k + 1);
  1097. strncpyz(xk->data, buf, k + 1);
  1098. }
  1099. xtra_set(u, e, xk);
  1100. return 1;
  1101. }
  1102. static int xtra_dupuser(struct userrec *new, struct userrec *old,
  1103. struct user_entry *e)
  1104. {
  1105. struct xtra_key *x1, *x2;
  1106. for (x1 = e->u.extra; x1; x1 = x1->next) {
  1107. x2 = user_malloc(sizeof(struct xtra_key));
  1108. x2->key = user_malloc(strlen(x1->key) + 1);
  1109. strcpy(x2->key, x1->key);
  1110. x2->data = user_malloc(strlen(x1->data) + 1);
  1111. strcpy(x2->data, x1->data);
  1112. set_user(&USERENTRY_XTRA, new, x2);
  1113. }
  1114. return 1;
  1115. }
  1116. static int xtra_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
  1117. {
  1118. struct xtra_key *x;
  1119. for (x = e->u.extra; x; x = x->next)
  1120. if (lfprintf(f, "--XTRA %s %s\n", x->key, x->data) == EOF)
  1121. return 0;
  1122. return 1;
  1123. }
  1124. int xtra_kill(struct user_entry *e)
  1125. {
  1126. struct xtra_key *x, *y;
  1127. for (x = e->u.extra; x; x = y) {
  1128. y = x->next;
  1129. nfree(x->key);
  1130. nfree(x->data);
  1131. nfree(x);
  1132. }
  1133. nfree(e);
  1134. return 1;
  1135. }
  1136. static int xtra_tcl_get(Tcl_Interp *irp, struct userrec *u,
  1137. struct user_entry *e, int argc, char **argv)
  1138. {
  1139. struct xtra_key *x;
  1140. BADARGS(3, 4, " handle XTRA ?key?");
  1141. if (argc == 4) {
  1142. for (x = e->u.extra; x; x = x->next)
  1143. if (!egg_strcasecmp(argv[3], x->key)) {
  1144. Tcl_AppendResult(irp, x->data, NULL);
  1145. return TCL_OK;
  1146. }
  1147. return TCL_OK;
  1148. }
  1149. for (x = e->u.extra; x; x = x->next) {
  1150. char *p;
  1151. #if ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))
  1152. CONST char *list[2];
  1153. #else
  1154. char *list[2];
  1155. #endif
  1156. list[0] = x->key;
  1157. list[1] = x->data;
  1158. p = Tcl_Merge(2, list);
  1159. Tcl_AppendElement(irp, p);
  1160. Tcl_Free((char *) p);
  1161. }
  1162. return TCL_OK;
  1163. }
  1164. /* FIXME: possible expmem leak here
  1165. * also, ghost does not have xtra_ it was changed to config
  1166. */
  1167. static int xtra_expmem(struct user_entry *e)
  1168. {
  1169. struct xtra_key *x;
  1170. int tot = 0;
  1171. for (x = e->u.extra; x; x = x->next) {
  1172. tot += sizeof(struct xtra_key);
  1173. tot += strlen(x->key) + 1;
  1174. tot += strlen(x->data) + 1;
  1175. }
  1176. return tot;
  1177. }
  1178. struct user_entry_type USERENTRY_XTRA =
  1179. {
  1180. 0,
  1181. xtra_gotshare,
  1182. xtra_dupuser,
  1183. xtra_unpack,
  1184. xtra_pack,
  1185. xtra_write_userfile,
  1186. xtra_kill,
  1187. def_get,
  1188. xtra_set,
  1189. xtra_tcl_get,
  1190. xtra_tcl_set,
  1191. xtra_expmem,
  1192. xtra_display,
  1193. "XTRA"
  1194. };
  1195. static int hosts_dupuser(struct userrec *new, struct userrec *old,
  1196. struct user_entry *e)
  1197. {
  1198. struct list_type *h;
  1199. for (h = e->u.extra; h; h = h->next)
  1200. set_user(&USERENTRY_HOSTS, new, h->extra);
  1201. return 1;
  1202. }
  1203. static int hosts_null(struct userrec *u, struct user_entry *e)
  1204. {
  1205. return 1;
  1206. }
  1207. static int hosts_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
  1208. {
  1209. struct list_type *h;
  1210. for (h = e->u.extra; h; h = h->next)
  1211. if (lfprintf(f, "--HOSTS %s\n", h->extra) == EOF)
  1212. return 0;
  1213. return 1;
  1214. }
  1215. static int hosts_kill(struct user_entry *e)
  1216. {
  1217. list_type_kill(e->u.list);
  1218. nfree(e);
  1219. return 1;
  1220. }
  1221. static int hosts_expmem(struct user_entry *e)
  1222. {
  1223. return list_type_expmem(e->u.list);
  1224. }
  1225. static void hosts_display(int idx, struct user_entry *e, struct userrec *u)
  1226. {
  1227. #ifdef LEAF
  1228. /* if this is a su, dont show hosts
  1229. * otherwise, let users see their own hosts */
  1230. if (!strcmp(u->handle,dcc[idx].nick) && !dcc[idx].u.chat->su_nick) {
  1231. #endif /* LEAF */
  1232. char s[1024];
  1233. struct list_type *q;
  1234. s[0] = 0;
  1235. strcpy(s, " HOSTS: ");
  1236. for (q = e->u.list; q; q = q->next) {
  1237. if (s[0] && !s[9])
  1238. strcat(s, q->extra);
  1239. else if (!s[0])
  1240. sprintf(s, " %s", q->extra);
  1241. else {
  1242. if (strlen(s) + strlen(q->extra) + 2 > 65) {
  1243. dprintf(idx, "%s\n", s);
  1244. sprintf(s, " %s", q->extra);
  1245. } else {
  1246. strcat(s, ", ");
  1247. strcat(s, q->extra);
  1248. }
  1249. }
  1250. }
  1251. if (s[0])
  1252. dprintf(idx, "%s\n", s);
  1253. #ifdef LEAF
  1254. } else {
  1255. dprintf(idx, " HOSTS: Hidden on leaf bots.");
  1256. if (dcc[idx].u.chat->su_nick)
  1257. dprintf(idx, " Nice try, %s.", dcc[idx].u.chat->su_nick);
  1258. dprintf(idx, "\n");
  1259. }
  1260. #endif /* LEAF */
  1261. }
  1262. static int hosts_set(struct userrec *u, struct user_entry *e, void *buf)
  1263. {
  1264. if (!buf || !egg_strcasecmp(buf, "none")) {
  1265. /* When the bot crashes, it's in this part, not in the 'else' part */
  1266. list_type_kill(e->u.list);
  1267. e->u.list = NULL;
  1268. } else {
  1269. char *host = buf, *p = strchr(host, ',');
  1270. struct list_type **t;
  1271. /* Can't have ,'s in hostmasks */
  1272. while (p) {
  1273. *p = '?';
  1274. p = strchr(host, ',');
  1275. }
  1276. /* fred1: check for redundant hostmasks with
  1277. * controversial "superpenis" algorithm ;) */
  1278. /* I'm surprised Raistlin hasn't gotten involved in this controversy */
  1279. t = &(e->u.list);
  1280. while (*t) {
  1281. if (wild_match(host, (*t)->extra)) {
  1282. struct list_type *u;
  1283. u = *t;
  1284. *t = (*t)->next;
  1285. if (u->extra)
  1286. nfree(u->extra);
  1287. nfree(u);
  1288. } else
  1289. t = &((*t)->next);
  1290. }
  1291. *t = user_malloc(sizeof(struct list_type));
  1292. (*t)->next = NULL;
  1293. (*t)->extra = user_malloc(strlen(host) + 1);
  1294. strcpy((*t)->extra, host);
  1295. }
  1296. return 1;
  1297. }
  1298. static int hosts_tcl_get(Tcl_Interp *irp, struct userrec *u,
  1299. struct user_entry *e, int argc, char **argv)
  1300. {
  1301. struct list_type *x;
  1302. BADARGS(3, 3, " handle HOSTS");
  1303. for (x = e->u.list; x; x = x->next)
  1304. Tcl_AppendElement(irp, x->extra);
  1305. return TCL_OK;
  1306. }
  1307. static int hosts_tcl_set(Tcl_Interp * irp, struct userrec *u,
  1308. struct user_entry *e, int argc, char **argv)
  1309. {
  1310. BADARGS(3, 4, " handle HOSTS ?host?");
  1311. if (argc == 4)
  1312. addhost_by_handle(u->handle, argv[3]);
  1313. else
  1314. addhost_by_handle(u->handle, "none"); /* drummer */
  1315. return TCL_OK;
  1316. }
  1317. static int hosts_gotshare(struct userrec *u, struct user_entry *e,
  1318. char *buf, int idx)
  1319. {
  1320. /* doh, try to be too clever and it bites your butt */
  1321. return 0;
  1322. }
  1323. struct user_entry_type USERENTRY_HOSTS =
  1324. {
  1325. 0,
  1326. hosts_gotshare,
  1327. hosts_dupuser,
  1328. hosts_null,
  1329. hosts_null,
  1330. hosts_write_userfile,
  1331. hosts_kill,
  1332. def_get,
  1333. hosts_set,
  1334. hosts_tcl_get,
  1335. hosts_tcl_set,
  1336. hosts_expmem,
  1337. hosts_display,
  1338. "HOSTS"
  1339. };
  1340. int list_append(struct list_type **h, struct list_type *i)
  1341. {
  1342. for (; *h; h = &((*h)->next));
  1343. *h = i;
  1344. return 1;
  1345. }
  1346. int list_delete(struct list_type **h, struct list_type *i)
  1347. {
  1348. for (; *h; h = &((*h)->next))
  1349. if (*h == i) {
  1350. *h = i->next;
  1351. return 1;
  1352. }
  1353. return 0;
  1354. }
  1355. int list_contains(struct list_type *h, struct list_type *i)
  1356. {
  1357. for (; h; h = h->next)
  1358. if (h == i) {
  1359. return 1;
  1360. }
  1361. return 0;
  1362. }
  1363. int add_entry_type(struct user_entry_type *type)
  1364. {
  1365. struct userrec *u;
  1366. list_insert(&entry_type_list, type);
  1367. for (u = userlist; u; u = u->next) {
  1368. struct user_entry *e = find_user_entry(type, u);
  1369. if (e && e->name) {
  1370. e->type = type;
  1371. e->type->unpack(u, e);
  1372. nfree(e->name);
  1373. e->name = NULL;
  1374. }
  1375. }
  1376. return 1;
  1377. }
  1378. int del_entry_type(struct user_entry_type *type)
  1379. {
  1380. struct userrec *u;
  1381. for (u = userlist; u; u = u->next) {
  1382. struct user_entry *e = find_user_entry(type, u);
  1383. if (e && !e->name) {
  1384. e->type->pack(u, e);
  1385. e->name = user_malloc(strlen(e->type->name) + 1);
  1386. strcpy(e->name, e->type->name);
  1387. e->type = NULL;
  1388. }
  1389. }
  1390. return list_delete((struct list_type **) &entry_type_list,
  1391. (struct list_type *) type);
  1392. }
  1393. struct user_entry_type *find_entry_type(char *name)
  1394. {
  1395. struct user_entry_type *p;
  1396. for (p = entry_type_list; p; p = p->next) {
  1397. if (!egg_strcasecmp(name, p->name))
  1398. return p;
  1399. }
  1400. return NULL;
  1401. }
  1402. struct user_entry *find_user_entry(struct user_entry_type *et,
  1403. struct userrec *u)
  1404. {
  1405. struct user_entry **e, *t;
  1406. for (e = &(u->entries); *e; e = &((*e)->next)) {
  1407. if (((*e)->type == et) ||
  1408. ((*e)->name && !egg_strcasecmp((*e)->name, et->name))) {
  1409. t = *e;
  1410. *e = t->next;
  1411. t->next = u->entries;
  1412. u->entries = t;
  1413. return t;
  1414. }
  1415. }
  1416. return NULL;
  1417. }
  1418. void *get_user(struct user_entry_type *et, struct userrec *u)
  1419. {
  1420. struct user_entry *e;
  1421. if (u && (e = find_user_entry(et, u)))
  1422. return et->get(u, e);
  1423. return 0;
  1424. }
  1425. int set_user(struct user_entry_type *et, struct userrec *u, void *d)
  1426. {
  1427. struct user_entry *e;
  1428. int r;
  1429. if (!u || !et)
  1430. return 0;
  1431. if (!(e = find_user_entry(et, u))) {
  1432. e = user_malloc(sizeof(struct user_entry));
  1433. e->type = et;
  1434. e->name = NULL;
  1435. e->u.list = NULL;
  1436. list_insert((&(u->entries)), e);
  1437. }
  1438. r = et->set(u, e, d);
  1439. if (!e->u.list) {
  1440. list_delete((struct list_type **) &(u->entries), (struct list_type *) e);
  1441. nfree(e);
  1442. }
  1443. return r;
  1444. }