tclchan.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116
  1. /*
  2. * tclchan.c -- part of channels.mod
  3. *
  4. */
  5. static int tcl_channel_info(Tcl_Interp * irp, struct chanset_t *chan)
  6. {
  7. char a[121], b[121], s[121];
  8. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  9. CONST char *args[2];
  10. #else
  11. char *args[2];
  12. #endif
  13. struct udef_struct *ul;
  14. get_mode_protect(chan, s);
  15. Tcl_AppendElement(irp, s);
  16. simple_sprintf(s, "%d", chan->idle_kick);
  17. Tcl_AppendElement(irp, s);
  18. simple_sprintf(s, "%d", chan->limitraise);
  19. Tcl_AppendElement(irp, s);
  20. simple_sprintf(s, "%d", chan->stopnethack_mode);
  21. Tcl_AppendElement(irp, s);
  22. simple_sprintf(s, "%d", chan->revenge_mode);
  23. Tcl_AppendElement(irp, s);
  24. simple_sprintf(s, "%d:%d", chan->flood_pub_thr, chan->flood_pub_time);
  25. Tcl_AppendElement(irp, s);
  26. simple_sprintf(s, "%d:%d", chan->flood_ctcp_thr, chan->flood_ctcp_time);
  27. Tcl_AppendElement(irp, s);
  28. simple_sprintf(s, "%d:%d", chan->flood_join_thr, chan->flood_join_time);
  29. Tcl_AppendElement(irp, s);
  30. simple_sprintf(s, "%d:%d", chan->flood_kick_thr, chan->flood_kick_time);
  31. Tcl_AppendElement(irp, s);
  32. simple_sprintf(s, "%d:%d", chan->flood_deop_thr, chan->flood_deop_time);
  33. Tcl_AppendElement(irp, s);
  34. simple_sprintf(s, "%d:%d", chan->flood_nick_thr, chan->flood_nick_time);
  35. Tcl_AppendElement(irp, s);
  36. simple_sprintf(s, "%d", chan->ban_time);
  37. Tcl_AppendElement(irp, s);
  38. simple_sprintf(s, "%s", chan->closed_ban);
  39. Tcl_AppendElement(irp, s);
  40. /* Chanint template
  41. *simple_sprintf(s, "%s", chan->temp);
  42. *Tcl_AppendElement(irp, s);
  43. */
  44. simple_sprintf(s, "%d", chan->exempt_time);
  45. Tcl_AppendElement(irp, s);
  46. simple_sprintf(s, "%d", chan->invite_time);
  47. Tcl_AppendElement(irp, s);
  48. if (chan->status & CHAN_ENFORCEBANS)
  49. Tcl_AppendElement(irp, "+enforcebans");
  50. else
  51. Tcl_AppendElement(irp, "-enforcebans");
  52. if (chan->status & CHAN_DYNAMICBANS)
  53. Tcl_AppendElement(irp, "+dynamicbans");
  54. else
  55. Tcl_AppendElement(irp, "-dynamicbans");
  56. if (chan->status & CHAN_NOUSERBANS)
  57. Tcl_AppendElement(irp, "-userbans");
  58. else
  59. Tcl_AppendElement(irp, "+userbans");
  60. if (chan->status & CHAN_BITCH)
  61. Tcl_AppendElement(irp, "+bitch");
  62. else
  63. Tcl_AppendElement(irp, "-bitch");
  64. if (chan->status & CHAN_PROTECTOPS)
  65. Tcl_AppendElement(irp, "+protectops");
  66. else
  67. Tcl_AppendElement(irp, "-protectops");
  68. if (chan->status & CHAN_INACTIVE)
  69. Tcl_AppendElement(irp, "+inactive");
  70. else
  71. Tcl_AppendElement(irp, "-inactive");
  72. if (chan->status & CHAN_REVENGE)
  73. Tcl_AppendElement(irp, "+revenge");
  74. else
  75. Tcl_AppendElement(irp, "-revenge");
  76. if (chan->status & CHAN_REVENGEBOT)
  77. Tcl_AppendElement(irp, "+revengebot");
  78. else
  79. Tcl_AppendElement(irp, "-revengebot");
  80. if (chan->status & CHAN_SECRET)
  81. Tcl_AppendElement(irp, "+secret");
  82. else
  83. Tcl_AppendElement(irp, "-secret");
  84. if (chan->status & CHAN_CYCLE)
  85. Tcl_AppendElement(irp, "+cycle");
  86. else
  87. Tcl_AppendElement(irp, "-cycle");
  88. if (chan->ircnet_status& CHAN_DYNAMICEXEMPTS)
  89. Tcl_AppendElement(irp, "+dynamicexempts");
  90. else
  91. Tcl_AppendElement(irp, "-dynamicexempts");
  92. if (chan->ircnet_status& CHAN_NOUSEREXEMPTS)
  93. Tcl_AppendElement(irp, "-userexempts");
  94. else
  95. Tcl_AppendElement(irp, "+userexempts");
  96. if (chan->ircnet_status& CHAN_DYNAMICINVITES)
  97. Tcl_AppendElement(irp, "+dynamicinvites");
  98. else
  99. Tcl_AppendElement(irp, "-dynamicinvites");
  100. if (chan->ircnet_status& CHAN_NOUSERINVITES)
  101. Tcl_AppendElement(irp, "-userinvites");
  102. else
  103. Tcl_AppendElement(irp, "+userinvites");
  104. if (chan->status & CHAN_NODESYNCH)
  105. Tcl_AppendElement(irp, "+nodesynch");
  106. else
  107. Tcl_AppendElement(irp, "-nodesynch");
  108. if (chan->status & CHAN_CLOSED)
  109. Tcl_AppendElement(irp, "+closed");
  110. else
  111. Tcl_AppendElement(irp, "-closed");
  112. if (chan->status & CHAN_TAKE)
  113. Tcl_AppendElement(irp, "+take");
  114. else
  115. Tcl_AppendElement(irp, "-take");
  116. if (chan->status & CHAN_NOMOP)
  117. Tcl_AppendElement(irp, "+nomop");
  118. else
  119. Tcl_AppendElement(irp, "-nomop");
  120. if (chan->status & CHAN_MANOP)
  121. Tcl_AppendElement(irp, "+manop");
  122. else
  123. Tcl_AppendElement(irp, "-manop");
  124. if (chan->status & CHAN_VOICE)
  125. Tcl_AppendElement(irp, "+voice");
  126. else
  127. Tcl_AppendElement(irp, "-voice");
  128. /* Chanflag template
  129. *if (chan->status & CHAN_TEMP)
  130. * Tcl_AppendElement(irp, "+temp");
  131. *else
  132. * Tcl_AppendElement(irp, "-temp");
  133. */
  134. if (chan->status & CHAN_FASTOP)
  135. Tcl_AppendElement(irp, "+fastop");
  136. else
  137. Tcl_AppendElement(irp, "-fastop");
  138. if (chan->status & CHAN_PRIVATE)
  139. Tcl_AppendElement(irp, "+private");
  140. else
  141. Tcl_AppendElement(irp, "-private");
  142. for (ul = udef; ul; ul = ul->next) {
  143. /* If it's undefined, skip it. */
  144. if (!ul->defined || !ul->name) continue;
  145. if (ul->type == UDEF_FLAG) {
  146. simple_sprintf(s, "%c%s", getudef(ul->values, chan->dname) ? '+' : '-',
  147. ul->name);
  148. Tcl_AppendElement(irp, s);
  149. } else if (ul->type == UDEF_INT) {
  150. char *x;
  151. egg_snprintf(a, sizeof a, "%s", ul->name);
  152. egg_snprintf(b, sizeof b, "%d", getudef(ul->values, chan->dname));
  153. args[0] = a;
  154. args[1] = b;
  155. x = Tcl_Merge(2, args);
  156. egg_snprintf(s, sizeof s, "%s", x);
  157. Tcl_Free((char *) x);
  158. Tcl_AppendElement(irp, s);
  159. } else
  160. debug1("UDEF-ERROR: unknown type %d", ul->type);
  161. }
  162. return TCL_OK;
  163. }
  164. static int tcl_channel_get(Tcl_Interp * irp, struct chanset_t *chan, char *setting)
  165. {
  166. char s[121];
  167. struct udef_struct *ul;
  168. #define CHECK(x) !strcmp(setting, x)
  169. #define CHKFLAG_POS(x,y,z) (!strcmp(setting, y)) { \
  170. if(z & x) simple_sprintf(s, "%d", 1); \
  171. else simple_sprintf(s, "%d", 0); }
  172. #define CHKFLAG_NEG(x,y,z) (!strcmp(setting, y)) { \
  173. if (z & x) simple_sprintf(s, "%d", 0); \
  174. else simple_sprintf(s, "%d", 1); }
  175. if (CHECK("chanmode")) get_mode_protect(chan, s);
  176. else if (CHECK("addedby")) simple_sprintf(s, "%s", chan->added_by);
  177. else if (CHECK("addedts")) simple_sprintf(s, "%lu", chan->added_ts);
  178. else if (CHECK("idle-kick")) simple_sprintf(s, "%d", chan->idle_kick);
  179. else if (CHECK("limit")) simple_sprintf(s, "%d", chan->limitraise);
  180. else if (CHECK("stop-net-hack")) simple_sprintf(s, "%d", chan->stopnethack_mode);
  181. else if (CHECK("revenge-mode")) simple_sprintf(s, "%d", chan->revenge_mode);
  182. else if (CHECK("flood-chan")) simple_sprintf(s, "%d %d", chan->flood_pub_thr, chan->flood_pub_time);
  183. else if (CHECK("flood-ctcp")) simple_sprintf(s, "%d %d", chan->flood_ctcp_thr, chan->flood_ctcp_time);
  184. else if (CHECK("flood-join")) simple_sprintf(s, "%d %d", chan->flood_join_thr, chan->flood_join_time);
  185. else if (CHECK("flood-kick")) simple_sprintf(s, "%d %d", chan->flood_kick_thr, chan->flood_kick_time);
  186. else if (CHECK("flood-deop")) simple_sprintf(s, "%d %d", chan->flood_deop_thr, chan->flood_deop_time);
  187. else if (CHECK("flood-nick")) simple_sprintf(s, "%d %d", chan->flood_nick_thr, chan->flood_nick_time);
  188. /* Chanint template
  189. *else if (CHECK("temp")) simple_sprintf(s, "%s", chan->temp);
  190. */
  191. else if (CHECK("closed-ban")) simple_sprintf(s, "%d", chan->closed_ban);
  192. else if (CHECK("ban-time")) simple_sprintf(s, "%d", chan->ban_time);
  193. else if (CHECK("exempt-time")) simple_sprintf(s, "%d", chan->exempt_time);
  194. else if (CHECK("invite-time")) simple_sprintf(s, "%d", chan->invite_time);
  195. else if CHKFLAG_POS(CHAN_ENFORCEBANS, "enforcebans", chan->status)
  196. else if CHKFLAG_POS(CHAN_DYNAMICBANS, "dynamicbans", chan->status)
  197. else if CHKFLAG_NEG(CHAN_NOUSERBANS, "userbans", chan->status)
  198. else if CHKFLAG_POS(CHAN_BITCH, "bitch", chan->status)
  199. else if CHKFLAG_POS(CHAN_PROTECTOPS, "protectops", chan->status)
  200. else if CHKFLAG_POS(CHAN_INACTIVE, "inactive", chan->status)
  201. else if CHKFLAG_POS(CHAN_REVENGE, "revenge", chan->status)
  202. else if CHKFLAG_POS(CHAN_REVENGEBOT, "revengebot", chan->status)
  203. else if CHKFLAG_POS(CHAN_SECRET, "secret", chan->status)
  204. else if CHKFLAG_POS(CHAN_CYCLE, "cycle", chan->status)
  205. else if CHKFLAG_POS(CHAN_NODESYNCH, "nodesynch", chan->status)
  206. else if CHKFLAG_POS(CHAN_DYNAMICEXEMPTS, "dynamicexempts", chan->ircnet_status)
  207. else if CHKFLAG_NEG(CHAN_NOUSEREXEMPTS, "userexempts", chan->ircnet_status)
  208. else if CHKFLAG_POS(CHAN_DYNAMICINVITES, "dynamicinvites", chan->ircnet_status)
  209. else if CHKFLAG_NEG(CHAN_NOUSERINVITES, "userinvites", chan->ircnet_status)
  210. else if CHKFLAG_POS(CHAN_CLOSED, "closed", chan->status)
  211. else if CHKFLAG_POS(CHAN_TAKE, "take", chan->status)
  212. else if CHKFLAG_POS(CHAN_NOMOP, "nomop", chan->status)
  213. else if CHKFLAG_POS(CHAN_MANOP, "manop", chan->status)
  214. else if CHKFLAG_POS(CHAN_VOICE, "voice", chan->status)
  215. else if CHKFLAG_POS(CHAN_FASTOP, "fastop", chan->status)
  216. else if CHKFLAG_POS(CHAN_PRIVATE, "private", chan->status)
  217. /* Chanflag template
  218. *else if CHKFLAG_POS(CHAN_TEMP, "temp", chan->status)
  219. */
  220. else {
  221. /* Hopefully it's a user-defined flag. */
  222. for (ul = udef; ul && ul->name; ul = ul->next) {
  223. if (!strcmp(setting, ul->name)) break;
  224. }
  225. if (!ul || !ul->name) {
  226. /* Error if it wasn't found. */
  227. Tcl_AppendResult(irp, "Unknown channel setting.", NULL);
  228. return(TCL_ERROR);
  229. }
  230. /* Flag or int, all the same. */
  231. simple_sprintf(s, "%d", getudef(ul->values, chan->dname));
  232. Tcl_AppendResult(irp, s, NULL);
  233. return(TCL_OK);
  234. }
  235. /* Ok, if we make it this far, the result is "s". */
  236. Tcl_AppendResult(irp, s, NULL);
  237. return(TCL_OK);
  238. }
  239. static int tcl_channel STDVAR
  240. {
  241. struct chanset_t *chan;
  242. char buf2[1024];
  243. BADARGS(2, 999, " command ?options?");
  244. if (!strcmp(argv[1], "add")) {
  245. BADARGS(3, 4, " add channel-name ?options-list?");
  246. if (argc == 3) {
  247. egg_snprintf(buf2, sizeof buf2, "cjoin %s", argv[2]);
  248. if (!loading)
  249. putallbots(buf2);
  250. return tcl_channel_add(irp, argv[2], "");
  251. }
  252. egg_snprintf(buf2, sizeof buf2, "cjoin %s %s", argv[2], argv[3]);
  253. if (!loading)
  254. putallbots(buf2);
  255. return tcl_channel_add(irp, argv[2], argv[3]);
  256. }
  257. if (!strcmp(argv[1], "set")) {
  258. BADARGS(3, 999, " set channel-name ?options?");
  259. chan = findchan_by_dname(argv[2]);
  260. if (chan == NULL) {
  261. if (loading == 1)
  262. return TCL_OK; /* Ignore channel settings for a static
  263. * channel which has been removed from
  264. * the config */
  265. Tcl_AppendResult(irp, "no such channel record", NULL);
  266. return TCL_ERROR;
  267. }
  268. do_chanset(chan, argv[3], 0);
  269. return tcl_channel_modify(irp, chan, argc - 3, &argv[3]);
  270. }
  271. if (!strcmp(argv[1], "get")) {
  272. BADARGS(4, 4, " get channel-name setting-name");
  273. chan = findchan_by_dname(argv[2]);
  274. if (chan == NULL) {
  275. Tcl_AppendResult(irp, "no such channel record", NULL);
  276. return TCL_ERROR;
  277. }
  278. return(tcl_channel_get(irp, chan, argv[3]));
  279. }
  280. if (!strcmp(argv[1], "info")) {
  281. BADARGS(3, 3, " info channel-name");
  282. chan = findchan_by_dname(argv[2]);
  283. if (chan == NULL) {
  284. Tcl_AppendResult(irp, "no such channel record", NULL);
  285. return TCL_ERROR;
  286. }
  287. return tcl_channel_info(irp, chan);
  288. }
  289. if (!strcmp(argv[1], "remove")) {
  290. BADARGS(3, 3, " remove channel-name");
  291. chan = findchan_by_dname(argv[2]);
  292. if (chan == NULL) {
  293. Tcl_AppendResult(irp, "no such channel record", NULL);
  294. return TCL_ERROR;
  295. }
  296. egg_snprintf(buf2, sizeof buf2, "cpart %s", argv[2]);
  297. putallbots(buf2);
  298. remove_channel(chan);
  299. return TCL_OK;
  300. }
  301. Tcl_AppendResult(irp, "unknown channel command: should be one of: ",
  302. "add, set, get, info, remove", NULL);
  303. return TCL_ERROR;
  304. }
  305. /* Parse options for a channel.
  306. */
  307. static int tcl_channel_modify(Tcl_Interp * irp, struct chanset_t *chan,
  308. int items, char **item)
  309. {
  310. int i, x = 0, found;
  311. #ifdef LEAF
  312. int old_status = chan->status,
  313. old_mode_mns_prot = chan->mode_mns_prot,
  314. old_mode_pls_prot = chan->mode_pls_prot;
  315. module_entry *me;
  316. #endif /* LEAF */
  317. struct udef_struct *ul = udef;
  318. char s[121];
  319. for (i = 0; i < items; i++) {
  320. if (!strcmp(item[i], "chanmode")) {
  321. i++;
  322. if (i >= items) {
  323. if (irp)
  324. Tcl_AppendResult(irp, "channel chanmode needs argument", NULL);
  325. return TCL_ERROR;
  326. }
  327. strncpy(s, item[i], 120);
  328. s[120] = 0;
  329. set_mode_protect(chan, s);
  330. } else if (!strcmp(item[i], "addedby")) {
  331. i++;
  332. if (i >= items) {
  333. if (irp)
  334. Tcl_AppendResult(irp, "addedby chanmode needs argument", NULL);
  335. return TCL_ERROR;
  336. }
  337. strncpyz(chan->added_by, item[i], NICKLEN);
  338. } else if (!strcmp(item[i], "addedts")) {
  339. i++;
  340. if (i >= items) {
  341. if (irp)
  342. Tcl_AppendResult(irp, "addedts chanmode needs argument", NULL);
  343. return TCL_ERROR;
  344. }
  345. chan->added_ts = atoi(item[i]);
  346. } else if (!strcmp(item[i], "idle-kick")) {
  347. i++;
  348. if (i >= items) {
  349. if (irp)
  350. Tcl_AppendResult(irp, "channel idle-kick needs argument", NULL);
  351. return TCL_ERROR;
  352. }
  353. chan->idle_kick = atoi(item[i]);
  354. } else if (!strcmp(item[i], "limit")) {
  355. i++;
  356. if (i >= items) {
  357. if (irp)
  358. Tcl_AppendResult(irp, "channel limit needs argument", NULL);
  359. return TCL_ERROR;
  360. }
  361. chan->limitraise = atoi(item[i]);
  362. chan->limit_prot = 0;
  363. } else if (!strcmp(item[i], "dont-idle-kick"))
  364. chan->idle_kick = 0;
  365. else if (!strcmp(item[i], "stopnethack-mode")) {
  366. i++;
  367. if (i >= items) {
  368. if (irp)
  369. Tcl_AppendResult(irp, "channel stopnethack-mode needs argument", NULL);
  370. return TCL_ERROR;
  371. }
  372. chan->stopnethack_mode = atoi(item[i]);
  373. } else if (!strcmp(item[i], "revenge-mode")) {
  374. i++;
  375. if (i >= items) {
  376. if (irp)
  377. Tcl_AppendResult(irp, "channel revenge-mode needs argument", NULL);
  378. return TCL_ERROR;
  379. }
  380. chan->revenge_mode = atoi(item[i]);
  381. } else if (!strcmp(item[i], "ban-time")) {
  382. i++;
  383. if (i >= items) {
  384. if (irp)
  385. Tcl_AppendResult(irp, "channel ban-time needs argument", NULL);
  386. return TCL_ERROR;
  387. }
  388. chan->ban_time = atoi(item[i]);
  389. } else if (!strcmp(item[i], "exempt-time")) {
  390. i++;
  391. if (i >= items) {
  392. if (irp)
  393. Tcl_AppendResult(irp, "channel exempt-time needs argument", NULL);
  394. return TCL_ERROR;
  395. }
  396. chan->exempt_time = atoi(item[i]);
  397. } else if (!strcmp(item[i], "invite-time")) {
  398. i++;
  399. if (i >= items) {
  400. if (irp)
  401. Tcl_AppendResult(irp, "channel invite-time needs argument", NULL);
  402. return TCL_ERROR;
  403. }
  404. chan->invite_time = atoi(item[i]);
  405. } else if (!strcmp(item[i], "closed-ban")) {
  406. i++;
  407. if (i >= items) {
  408. if (irp)
  409. Tcl_AppendResult(irp, "channel closed-ban needs argument", NULL);
  410. return TCL_ERROR;
  411. }
  412. chan->closed_ban = atoi(item[i]);
  413. /* Chanint template
  414. * } else if (!strcmp(item[i], "temp")) {
  415. * i++;
  416. * if (i >= items) {
  417. * if (irp)
  418. * Tcl_AppendResult(irp, "channel temp needs argument", NULL);
  419. * return TCL_ERROR;
  420. * }
  421. * chan->temp = atoi(item[i]);
  422. */
  423. /* Chanchar template
  424. } else if (!strcmp(item[i], "temp")) {
  425. i++;
  426. if (i >= items) {
  427. if (irp)
  428. Tcl_AppendResult(irp, "channel temp needs argument", NULL);
  429. return TCL_ERROR;
  430. }
  431. strncpyz(chan->temp, item[i], sizeof(chan->temp));
  432. //Entry just changed so update/recheck it's purpose?
  433. check_temp(chan);
  434. */
  435. } else if (!strcmp(item[i], "topic")) { //this is here for compatability
  436. i++;
  437. if (i >= items) {
  438. if (irp)
  439. Tcl_AppendResult(irp, "channel topic needs argument", NULL);
  440. return TCL_ERROR;
  441. }
  442. }
  443. else if (!strcmp(item[i], "+enforcebans"))
  444. chan->status |= CHAN_ENFORCEBANS;
  445. else if (!strcmp(item[i], "-enforcebans"))
  446. chan->status &= ~CHAN_ENFORCEBANS;
  447. else if (!strcmp(item[i], "+dynamicbans"))
  448. chan->status |= CHAN_DYNAMICBANS;
  449. else if (!strcmp(item[i], "-dynamicbans"))
  450. chan->status &= ~CHAN_DYNAMICBANS;
  451. else if (!strcmp(item[i], "-userbans"))
  452. chan->status |= CHAN_NOUSERBANS;
  453. else if (!strcmp(item[i], "+userbans"))
  454. chan->status &= ~CHAN_NOUSERBANS;
  455. else if (!strcmp(item[i], "+bitch"))
  456. chan->status |= CHAN_BITCH;
  457. else if (!strcmp(item[i], "-bitch"))
  458. chan->status &= ~CHAN_BITCH;
  459. else if (!strcmp(item[i], "+nodesynch"))
  460. chan->status |= CHAN_NODESYNCH;
  461. else if (!strcmp(item[i], "-nodesynch"))
  462. chan->status &= ~CHAN_NODESYNCH;
  463. else if (!strcmp(item[i], "+protectops"))
  464. chan->status |= CHAN_PROTECTOPS;
  465. else if (!strcmp(item[i], "-protectops"))
  466. chan->status &= ~CHAN_PROTECTOPS;
  467. else if (!strcmp(item[i], "+inactive"))
  468. chan->status |= CHAN_INACTIVE;
  469. else if (!strcmp(item[i], "-inactive"))
  470. chan->status&= ~CHAN_INACTIVE;
  471. else if (!strcmp(item[i], "+revenge"))
  472. chan->status |= CHAN_REVENGE;
  473. else if (!strcmp(item[i], "-revenge"))
  474. chan->status &= ~CHAN_REVENGE;
  475. else if (!strcmp(item[i], "+revengebot"))
  476. chan->status |= CHAN_REVENGEBOT;
  477. else if (!strcmp(item[i], "-revengebot"))
  478. chan->status &= ~CHAN_REVENGEBOT;
  479. else if (!strcmp(item[i], "+secret"))
  480. chan->status |= CHAN_SECRET;
  481. else if (!strcmp(item[i], "-secret"))
  482. chan->status &= ~CHAN_SECRET;
  483. else if (!strcmp(item[i], "+cycle"))
  484. chan->status |= CHAN_CYCLE;
  485. else if (!strcmp(item[i], "-cycle"))
  486. chan->status &= ~CHAN_CYCLE;
  487. else if (!strcmp(item[i], "+dynamicexempts"))
  488. chan->ircnet_status|= CHAN_DYNAMICEXEMPTS;
  489. else if (!strcmp(item[i], "-dynamicexempts"))
  490. chan->ircnet_status&= ~CHAN_DYNAMICEXEMPTS;
  491. else if (!strcmp(item[i], "-userexempts"))
  492. chan->ircnet_status|= CHAN_NOUSEREXEMPTS;
  493. else if (!strcmp(item[i], "+userexempts"))
  494. chan->ircnet_status&= ~CHAN_NOUSEREXEMPTS;
  495. else if (!strcmp(item[i], "+dynamicinvites"))
  496. chan->ircnet_status|= CHAN_DYNAMICINVITES;
  497. else if (!strcmp(item[i], "-dynamicinvites"))
  498. chan->ircnet_status&= ~CHAN_DYNAMICINVITES;
  499. else if (!strcmp(item[i], "-userinvites"))
  500. chan->ircnet_status|= CHAN_NOUSERINVITES;
  501. else if (!strcmp(item[i], "+userinvites"))
  502. chan->ircnet_status&= ~CHAN_NOUSERINVITES;
  503. else if (!strcmp(item[i], "+closed"))
  504. chan->status |= CHAN_CLOSED;
  505. else if (!strcmp(item[i], "-closed"))
  506. chan->status &= ~CHAN_CLOSED;
  507. else if (!strcmp(item[i], "+take"))
  508. chan->status |= CHAN_TAKE;
  509. else if (!strcmp(item[i], "-take"))
  510. chan->status &= ~CHAN_TAKE;
  511. else if (!strcmp(item[i], "+nomop"))
  512. chan->status |= CHAN_NOMOP;
  513. else if (!strcmp(item[i], "-nomop"))
  514. chan->status &= ~CHAN_NOMOP;
  515. else if (!strcmp(item[i], "+manop"))
  516. chan->status |= CHAN_MANOP;
  517. else if (!strcmp(item[i], "-manop"))
  518. chan->status &= ~CHAN_MANOP;
  519. else if (!strcmp(item[i], "+voice"))
  520. chan->status |= CHAN_VOICE;
  521. else if (!strcmp(item[i], "-voice"))
  522. chan->status &= ~CHAN_VOICE;
  523. /* Chanflag template
  524. * else if (!strcmp(item[i], "+temp"))
  525. * chan->status |= CHAN_TEMP;
  526. * else if (!strcmp(item[i], "-temp"))
  527. * chan->status &= ~CHAN_TEMP;
  528. */
  529. else if (!strcmp(item[i], "+fastop")) {
  530. chan->status |= CHAN_FASTOP;
  531. }
  532. else if (!strcmp(item[i], "-fastop"))
  533. chan->status &= ~(CHAN_FASTOP | CHAN_PROTECTOPS);
  534. else if (!strcmp(item[i], "+private")) {
  535. chan->status |= CHAN_PRIVATE;
  536. }
  537. else if (!strcmp(item[i], "-private"))
  538. chan->status &= ~CHAN_PRIVATE;
  539. /* ignore wasoptest, stopnethack and clearbans in chanfile, remove
  540. this later */
  541. else if (!strcmp(item[i], "+dontkickops")) ;
  542. else if (!strcmp(item[i], "-dontkickops")) ;
  543. else if (!strcmp(item[i], "+nomdop")) ;
  544. else if (!strcmp(item[i], "-nomdop")) ;
  545. else if (!strcmp(item[i], "+protectfriends")) ;
  546. else if (!strcmp(item[i], "-protectfriends")) ;
  547. else if (!strcmp(item[i], "+punish")) ;
  548. else if (!strcmp(item[i], "-punish")) ;
  549. else if (!strcmp(item[i], "+seen")) ;
  550. else if (!strcmp(item[i], "-seen")) ;
  551. else if (!strcmp(item[i], "+secret")) ;
  552. else if (!strcmp(item[i], "-secret")) ;
  553. else if (!strcmp(item[i], "-stopnethack")) ;
  554. else if (!strcmp(item[i], "+stopnethack")) ;
  555. else if (!strcmp(item[i], "-wasoptest")) ;
  556. else if (!strcmp(item[i], "+wasoptest")) ; /* Eule 01.2000 */
  557. else if (!strcmp(item[i], "+clearbans")) ;
  558. else if (!strcmp(item[i], "-clearbans")) ;
  559. else if (!strncmp(item[i], "need-", 5)) ;
  560. else if (!strncmp(item[i], "flood-", 6)) {
  561. int *pthr = 0, *ptime;
  562. char *p;
  563. if (!strcmp(item[i] + 6, "chan")) {
  564. pthr = &chan->flood_pub_thr;
  565. ptime = &chan->flood_pub_time;
  566. } else if (!strcmp(item[i] + 6, "join")) {
  567. pthr = &chan->flood_join_thr;
  568. ptime = &chan->flood_join_time;
  569. } else if (!strcmp(item[i] + 6, "ctcp")) {
  570. pthr = &chan->flood_ctcp_thr;
  571. ptime = &chan->flood_ctcp_time;
  572. } else if (!strcmp(item[i] + 6, "kick")) {
  573. pthr = &chan->flood_kick_thr;
  574. ptime = &chan->flood_kick_time;
  575. } else if (!strcmp(item[i] + 6, "deop")) {
  576. pthr = &chan->flood_deop_thr;
  577. ptime = &chan->flood_deop_time;
  578. } else if (!strcmp(item[i] + 6, "nick")) {
  579. pthr = &chan->flood_nick_thr;
  580. ptime = &chan->flood_nick_time;
  581. } else {
  582. if (irp)
  583. Tcl_AppendResult(irp, "illegal channel flood type: ", item[i], NULL);
  584. return TCL_ERROR;
  585. }
  586. i++;
  587. if (i >= items) {
  588. if (irp)
  589. Tcl_AppendResult(irp, item[i - 1], " needs argument", NULL);
  590. return TCL_ERROR;
  591. }
  592. p = strchr(item[i], ':');
  593. if (p) {
  594. *p++ = 0;
  595. *pthr = atoi(item[i]);
  596. *ptime = atoi(p);
  597. *--p = ':';
  598. } else {
  599. *pthr = atoi(item[i]);
  600. *ptime = 1;
  601. }
  602. } else {
  603. if (!strncmp(item[i] + 1, "udef-flag-", 10))
  604. initudef(UDEF_FLAG, item[i] + 11, 0);
  605. else if (!strncmp(item[i], "udef-int-", 9))
  606. initudef(UDEF_INT, item[i] + 9, 0);
  607. found = 0;
  608. for (ul = udef; ul; ul = ul->next) {
  609. if (ul->type == UDEF_FLAG &&
  610. /* Direct match when set during .chanset ... */
  611. (!egg_strcasecmp(item[i] + 1, ul->name) ||
  612. /* ... or with prefix when set during chanfile load. */
  613. (!strncmp(item[i] + 1, "udef-flag-", 10) &&
  614. !egg_strcasecmp(item[i] + 11, ul->name)))) {
  615. if (item[i][0] == '+')
  616. setudef(ul, chan->dname, 1);
  617. else
  618. setudef(ul, chan->dname, 0);
  619. found = 1;
  620. break;
  621. } else if (ul->type == UDEF_INT &&
  622. /* Direct match when set during .chanset ... */
  623. (!egg_strcasecmp(item[i], ul->name) ||
  624. /* ... or with prefix when set during chanfile load. */
  625. (!strncmp(item[i], "udef-int-", 9) &&
  626. !egg_strcasecmp(item[i] + 9, ul->name)))) {
  627. i++;
  628. if (i >= items) {
  629. if (irp)
  630. Tcl_AppendResult(irp, "this setting needs an argument", NULL);
  631. return TCL_ERROR;
  632. }
  633. setudef(ul, chan->dname, atoi(item[i]));
  634. found = 1;
  635. break;
  636. }
  637. }
  638. if (!found) {
  639. if (irp && item[i][0]) /* ignore "" */
  640. Tcl_AppendResult(irp, "illegal channel option: ", item[i], NULL);
  641. x++;
  642. }
  643. }
  644. }
  645. /* If protect_readonly == 0 and loading == 0 then
  646. * bot is now processing the configfile, so dont do anything,
  647. * we've to wait the channelfile that maybe override these settings
  648. * (note: it may cause problems if there is no chanfile!)
  649. * <drummer/1999/10/21>
  650. */
  651. #ifdef LEAF
  652. if (protect_readonly || loading) {
  653. if (((old_status ^ chan->status) & CHAN_INACTIVE) &&
  654. module_find("irc", 0, 0)) {
  655. if (!shouldjoin(chan) &&
  656. (chan->status & (CHAN_ACTIVE | CHAN_PEND)))
  657. dprintf(DP_SERVER, "PART %s\n", chan->name);
  658. if (shouldjoin(chan) &&
  659. !(chan->status & (CHAN_ACTIVE | CHAN_PEND)))
  660. dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ?
  661. chan->name : chan->dname,
  662. chan->channel.key[0] ?
  663. chan->channel.key : chan->key_prot);
  664. }
  665. if ((old_status ^ chan->status) & (CHAN_ENFORCEBANS |
  666. CHAN_BITCH)) {
  667. if ((me = module_find("irc", 0, 0)))
  668. (me->funcs[IRC_RECHECK_CHANNEL])(chan, 1);
  669. } else if (old_mode_pls_prot != chan->mode_pls_prot ||
  670. old_mode_mns_prot != chan->mode_mns_prot)
  671. if ((me = module_find("irc", 0, 0)))
  672. (me->funcs[IRC_RECHECK_CHANNEL_MODES])(chan);
  673. }
  674. #endif /* LEAF */
  675. if (x > 0)
  676. return TCL_ERROR;
  677. return TCL_OK;
  678. }
  679. static int tcl_do_masklist(maskrec *m, Tcl_Interp *irp)
  680. {
  681. char ts[21], ts1[21], ts2[21], *p;
  682. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  683. CONST char *list[6];
  684. #else
  685. char *list[6];
  686. #endif
  687. for (; m; m = m->next) {
  688. list[0] = m->mask;
  689. list[1] = m->desc;
  690. sprintf(ts, "%lu", m->expire);
  691. list[2] = ts;
  692. sprintf(ts1, "%lu", m->added);
  693. list[3] = ts1;
  694. sprintf(ts2, "%lu", m->lastactive);
  695. list[4] = ts2;
  696. list[5] = m->user;
  697. p = Tcl_Merge(6, list);
  698. Tcl_AppendElement(irp, p);
  699. Tcl_Free((char *) p);
  700. }
  701. return TCL_OK;
  702. }
  703. static int tcl_banlist STDVAR
  704. {
  705. struct chanset_t *chan;
  706. BADARGS(1, 2, " ?channel?");
  707. if (argc == 2) {
  708. chan = findchan_by_dname(argv[1]);
  709. if (chan == NULL) {
  710. Tcl_AppendResult(irp, "invalid channel: ", argv[1], NULL);
  711. return TCL_ERROR;
  712. }
  713. return tcl_do_masklist(chan->bans, irp);
  714. }
  715. return tcl_do_masklist(global_bans, irp);
  716. }
  717. static int tcl_exemptlist STDVAR
  718. {
  719. struct chanset_t *chan;
  720. BADARGS(1, 2, " ?channel?");
  721. if (argc == 2) {
  722. chan = findchan_by_dname(argv[1]);
  723. if (chan == NULL) {
  724. Tcl_AppendResult(irp, "invalid channel: ", argv[1], NULL);
  725. return TCL_ERROR;
  726. }
  727. return tcl_do_masklist(chan->exempts, irp);
  728. }
  729. return tcl_do_masklist(global_exempts, irp);
  730. }
  731. static int tcl_invitelist STDVAR
  732. {
  733. struct chanset_t *chan;
  734. BADARGS(1, 2, " ?channel?");
  735. if (argc == 2) {
  736. chan = findchan_by_dname(argv[1]);
  737. if (chan == NULL) {
  738. Tcl_AppendResult(irp, "invalid channel: ", argv[1], NULL);
  739. return TCL_ERROR;
  740. }
  741. return tcl_do_masklist(chan->invites, irp);
  742. }
  743. return tcl_do_masklist(global_invites, irp);
  744. }
  745. static int tcl_channels STDVAR
  746. {
  747. struct chanset_t *chan;
  748. BADARGS(1, 1, "");
  749. for (chan = chanset; chan; chan = chan->next)
  750. Tcl_AppendElement(irp, chan->dname);
  751. return TCL_OK;
  752. }
  753. static int tcl_validchan STDVAR
  754. {
  755. struct chanset_t *chan;
  756. BADARGS(2, 2, " channel");
  757. chan = findchan_by_dname(argv[1]);
  758. if (chan == NULL)
  759. Tcl_AppendResult(irp, "0", NULL);
  760. else
  761. Tcl_AppendResult(irp, "1", NULL);
  762. return TCL_OK;
  763. }
  764. static int tcl_getchaninfo STDVAR
  765. {
  766. char s[161];
  767. struct userrec *u;
  768. BADARGS(3, 3, " handle channel");
  769. u = get_user_by_handle(userlist, argv[1]);
  770. if (!u || (u->flags & USER_BOT))
  771. return TCL_OK;
  772. get_handle_chaninfo(argv[1], argv[2], s);
  773. Tcl_AppendResult(irp, s, NULL);
  774. return TCL_OK;
  775. }
  776. static int tcl_setchaninfo STDVAR
  777. {
  778. struct chanset_t *chan;
  779. BADARGS(4, 4, " handle channel info");
  780. chan = findchan_by_dname(argv[2]);
  781. if (chan == NULL) {
  782. Tcl_AppendResult(irp, "illegal channel: ", argv[2], NULL);
  783. return TCL_ERROR;
  784. }
  785. if (!egg_strcasecmp(argv[3], "none")) {
  786. set_handle_chaninfo(userlist, argv[1], argv[2], NULL);
  787. return TCL_OK;
  788. }
  789. set_handle_chaninfo(userlist, argv[1], argv[2], argv[3]);
  790. return TCL_OK;
  791. }
  792. static void init_masklist(masklist *m)
  793. {
  794. m->mask = (char *)nmalloc(1);
  795. m->mask[0] = 0;
  796. m->who = NULL;
  797. m->next = NULL;
  798. }
  799. /* Initialize out the channel record.
  800. */
  801. static void init_channel(struct chanset_t *chan, int reset)
  802. {
  803. chan->channel.maxmembers = 0;
  804. chan->channel.mode = 0;
  805. chan->channel.members = 0;
  806. if (!reset) {
  807. chan->channel.key = (char *) nmalloc(1);
  808. chan->channel.key[0] = 0;
  809. }
  810. chan->channel.ban = (masklist *) nmalloc(sizeof(masklist));
  811. init_masklist(chan->channel.ban);
  812. chan->channel.exempt = (masklist *) nmalloc(sizeof(masklist));
  813. init_masklist(chan->channel.exempt);
  814. chan->channel.invite = (masklist *) nmalloc(sizeof(masklist));
  815. init_masklist(chan->channel.invite);
  816. chan->channel.member = (memberlist *) nmalloc(sizeof(memberlist));
  817. chan->channel.member->nick[0] = 0;
  818. chan->channel.member->next = NULL;
  819. chan->channel.topic = NULL;
  820. }
  821. static void clear_masklist(masklist *m)
  822. {
  823. masklist *temp;
  824. for (; m; m = temp) {
  825. temp = m->next;
  826. if (m->mask)
  827. nfree(m->mask);
  828. if (m->who)
  829. nfree(m->who);
  830. nfree(m);
  831. }
  832. }
  833. /* Clear out channel data from memory.
  834. */
  835. static void clear_channel(struct chanset_t *chan, int reset)
  836. {
  837. memberlist *m, *m1;
  838. if (chan->channel.topic)
  839. nfree(chan->channel.topic);
  840. for (m = chan->channel.member; m; m = m1) {
  841. m1 = m->next;
  842. nfree(m);
  843. }
  844. clear_masklist(chan->channel.ban);
  845. chan->channel.ban = NULL;
  846. clear_masklist(chan->channel.exempt);
  847. chan->channel.exempt = NULL;
  848. clear_masklist(chan->channel.invite);
  849. chan->channel.invite = NULL;
  850. if (reset)
  851. init_channel(chan, 1);
  852. }
  853. /* Create new channel and parse commands.
  854. */
  855. static int tcl_channel_add(Tcl_Interp *irp, char *newname, char *options)
  856. {
  857. struct chanset_t *chan;
  858. int items;
  859. int ret = TCL_OK;
  860. int join = 0;
  861. char buf[2048], buf2[256];
  862. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  863. CONST char **item;
  864. #else
  865. char **item;
  866. #endif
  867. if (!newname || !newname[0] || !strchr(CHANMETA, newname[0])) {
  868. if (irp)
  869. Tcl_AppendResult(irp, "invalid channel prefix", NULL);
  870. return TCL_ERROR;
  871. }
  872. if (strchr(newname, ',') != NULL) {
  873. if (irp)
  874. Tcl_AppendResult(irp, "invalid channel name", NULL);
  875. return TCL_ERROR;
  876. }
  877. convert_element(glob_chanmode, buf2);
  878. simple_sprintf(buf, "chanmode %s ", buf2);
  879. strncat(buf, glob_chanset, 2047 - strlen(buf));
  880. strncat(buf, options, 2047 - strlen(buf));
  881. buf[2047] = 0;
  882. if (Tcl_SplitList(NULL, buf, &items, &item) != TCL_OK)
  883. return TCL_ERROR;
  884. if ((chan = findchan_by_dname(newname))) {
  885. /* Already existing channel, maybe a reload of the channel file */
  886. chan->status &= ~CHAN_FLAGGED; /* don't delete me! :) */
  887. } else {
  888. chan = (struct chanset_t *) nmalloc(sizeof(struct chanset_t));
  889. /* Hells bells, why set *every* variable to 0 when we have bzero? */
  890. egg_bzero(chan, sizeof(struct chanset_t));
  891. /* These are defaults, bzero already set them 0, but we set them for future reference */
  892. chan->limit_prot = 0;
  893. chan->limit = 0;
  894. chan->closed_ban = 0;
  895. /* Chanint template
  896. * chan->temp = 0;
  897. */
  898. chan->flood_pub_thr = gfld_chan_thr;
  899. chan->flood_pub_time = gfld_chan_time;
  900. chan->flood_ctcp_thr = gfld_ctcp_thr;
  901. chan->flood_ctcp_time = gfld_ctcp_time;
  902. chan->flood_join_thr = gfld_join_thr;
  903. chan->flood_join_time = gfld_join_time;
  904. chan->flood_deop_thr = gfld_deop_thr;
  905. chan->flood_deop_time = gfld_deop_time;
  906. chan->flood_kick_thr = gfld_kick_thr;
  907. chan->flood_kick_time = gfld_kick_time;
  908. chan->flood_nick_thr = gfld_nick_thr;
  909. chan->flood_nick_time = gfld_nick_time;
  910. chan->stopnethack_mode = global_stopnethack_mode;
  911. chan->revenge_mode = global_revenge_mode;
  912. chan->idle_kick = global_idle_kick;
  913. chan->limitraise = 20;
  914. chan->ban_time = global_ban_time;
  915. chan->exempt_time = global_exempt_time;
  916. chan->invite_time = global_invite_time;
  917. /* let's initialize this stuff for shits & giggles */
  918. chan->channel.jointime = 0;
  919. chan->channel.parttime = 0;
  920. #ifdef S_AUTOLOCK
  921. chan->channel.fighting = 0;
  922. #endif /* S_AUTOLOCK */
  923. /* We _only_ put the dname (display name) in here so as not to confuse
  924. * any code later on. chan->name gets updated with the channel name as
  925. * the server knows it, when we join the channel. <cybah>
  926. */
  927. strncpy(chan->dname, newname, 81);
  928. chan->dname[80] = 0;
  929. /* Initialize chan->channel info */
  930. init_channel(chan, 0);
  931. list_append((struct list_type **) &chanset, (struct list_type *) chan);
  932. /* Channel name is stored in xtra field for sharebot stuff */
  933. join = 1;
  934. }
  935. /* If loading is set, we're loading the userfile. Ignore errors while
  936. * reading userfile and just return TCL_OK. This is for compatability
  937. * if a user goes back to an eggdrop that no-longer supports certain
  938. * (channel) options.
  939. */
  940. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  941. if ((tcl_channel_modify(irp, chan, items, (char **)item) != TCL_OK) && !loading) {
  942. #else
  943. if ((tcl_channel_modify(irp, chan, items, item) != TCL_OK) && !loading) {
  944. #endif
  945. ret = TCL_ERROR;
  946. }
  947. Tcl_Free((char *) item);
  948. #ifdef LEAF
  949. if (join && shouldjoin(chan) && module_find("irc", 0, 0))
  950. dprintf(DP_SERVER, "JOIN %s %s\n", chan->dname, chan->key_prot);
  951. #endif
  952. return ret;
  953. }
  954. static int tcl_setudef STDVAR
  955. {
  956. int type;
  957. BADARGS(3, 3, " type name");
  958. if (!egg_strcasecmp(argv[1], "flag"))
  959. type = UDEF_FLAG;
  960. else if (!egg_strcasecmp(argv[1], "int"))
  961. type = UDEF_INT;
  962. else {
  963. Tcl_AppendResult(irp, "invalid type. Must be one of: flag, int", NULL);
  964. return TCL_ERROR;
  965. }
  966. initudef(type, argv[2], 1);
  967. return TCL_OK;
  968. }
  969. static int tcl_renudef STDVAR
  970. {
  971. struct udef_struct *ul;
  972. int type, found = 0;
  973. BADARGS(4, 4, " type oldname newname");
  974. if (!egg_strcasecmp(argv[1], "flag"))
  975. type = UDEF_FLAG;
  976. else if (!egg_strcasecmp(argv[1], "int"))
  977. type = UDEF_INT;
  978. else {
  979. Tcl_AppendResult(irp, "invalid type. Must be one of: flag, int", NULL);
  980. return TCL_ERROR;
  981. }
  982. for (ul = udef; ul; ul = ul->next) {
  983. if (ul->type == type && !egg_strcasecmp(ul->name, argv[2])) {
  984. nfree(ul->name);
  985. ul->name = nmalloc(strlen(argv[3]) + 1);
  986. strcpy(ul->name, argv[3]);
  987. found = 1;
  988. }
  989. }
  990. if (!found) {
  991. Tcl_AppendResult(irp, "not found", NULL);
  992. return TCL_ERROR;
  993. } else
  994. return TCL_OK;
  995. }
  996. static int tcl_deludef STDVAR
  997. {
  998. struct udef_struct *ul, *ull;
  999. int type, found = 0;
  1000. BADARGS(3, 3, " type name");
  1001. if (!egg_strcasecmp(argv[1], "flag"))
  1002. type = UDEF_FLAG;
  1003. else if (!egg_strcasecmp(argv[1], "int"))
  1004. type = UDEF_INT;
  1005. else {
  1006. Tcl_AppendResult(irp, "invalid type. Must be one of: flag, int", NULL);
  1007. return TCL_ERROR;
  1008. }
  1009. for (ul = udef; ul; ul = ul->next) {
  1010. ull = ul->next;
  1011. if (!ull)
  1012. break;
  1013. if (ull->type == type && !egg_strcasecmp(ull->name, argv[2])) {
  1014. ul->next = ull->next;
  1015. nfree(ull->name);
  1016. free_udef_chans(ull->values);
  1017. nfree(ull);
  1018. found = 1;
  1019. }
  1020. }
  1021. if (udef) {
  1022. if (udef->type == type && !egg_strcasecmp(udef->name, argv[2])) {
  1023. ul = udef->next;
  1024. nfree(udef->name);
  1025. free_udef_chans(udef->values);
  1026. nfree(udef);
  1027. udef = ul;
  1028. found = 1;
  1029. }
  1030. }
  1031. if (!found) {
  1032. Tcl_AppendResult(irp, "not found", NULL);
  1033. return TCL_ERROR;
  1034. } else
  1035. return TCL_OK;
  1036. }
  1037. static tcl_cmds channels_cmds[] =
  1038. {
  1039. {"channel", tcl_channel},
  1040. {"channels", tcl_channels},
  1041. {"exemptlist", tcl_exemptlist},
  1042. {"invitelist", tcl_invitelist},
  1043. {"banlist", tcl_banlist},
  1044. {"validchan", tcl_validchan},
  1045. {"getchaninfo", tcl_getchaninfo},
  1046. {"setchaninfo", tcl_setchaninfo},
  1047. {"setudef", tcl_setudef},
  1048. {"renudef", tcl_renudef},
  1049. {"deludef", tcl_deludef},
  1050. {NULL, NULL}
  1051. };