server.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024
  1. #ifdef LEAF
  2. #define MODULE_NAME "server"
  3. #define MAKING_SERVER
  4. #include "src/mod/module.h"
  5. #include "server.h"
  6. static Function *global = NULL, *encryption_funcs;
  7. extern struct cfg_entry CFG_OPTIMESLACK;
  8. static int ctcp_mode;
  9. static int serv;
  10. static int strict_host;
  11. static char newserver[121];
  12. static int newserverport;
  13. static char newserverpass[121];
  14. static time_t trying_server;
  15. static int server_lag;
  16. static char altnick[NICKLEN];
  17. static char raltnick[NICKLEN];
  18. static int curserv;
  19. static int flud_thr;
  20. static int flud_time;
  21. static int flud_ctcp_thr;
  22. static int flud_ctcp_time;
  23. static char initserver[121];
  24. static char botuserhost[121];
  25. static int keepnick;
  26. static int nick_juped = 0;
  27. static int check_stoned;
  28. static int serverror_quit;
  29. static int quiet_reject;
  30. static int waiting_for_awake;
  31. static time_t server_online;
  32. static time_t server_cycle_wait;
  33. static char botrealname[121];
  34. static int min_servs;
  35. static int server_timeout;
  36. static int never_give_up;
  37. static int strict_servernames;
  38. static struct server_list *serverlist;
  39. static int cycle_time;
  40. static int default_port;
  41. static char oldnick[NICKLEN];
  42. static int trigger_on_ignore;
  43. static int answer_ctcp;
  44. static int lowercase_ctcp;
  45. static int check_mode_r;
  46. static int net_type;
  47. static char connectserver[121];
  48. static int resolvserv;
  49. static int double_mode;
  50. static int double_server;
  51. static int double_help;
  52. static int double_warned;
  53. static int lastpingtime;
  54. static char stackablecmds[511];
  55. static char stackable2cmds[511];
  56. static time_t last_time;
  57. static int use_penalties;
  58. static int use_fastdeq;
  59. static int nick_len;
  60. static int kick_method;
  61. static int optimize_kicks;
  62. static p_tcl_bind_list H_wall, H_raw, H_notc, H_msgm, H_msg, H_flud, H_ctcr,
  63. H_ctcp;
  64. static void empty_msgq (void);
  65. static void next_server (int *, char *, unsigned int *, char *);
  66. static void disconnect_server (int);
  67. static char *get_altbotnick (void);
  68. static int calc_penalty (char *);
  69. static int fast_deq (int);
  70. static char *splitnicks (char **);
  71. static void check_queues (char *, char *);
  72. static void parse_q (struct msgq_head *, char *, char *);
  73. static void purge_kicks (struct msgq_head *);
  74. static int deq_kick (int);
  75. static void msgq_clear (struct msgq_head *qh);
  76. static int stack_limit;
  77. #include "servmsg.c"
  78. #define MAXPENALTY 10
  79. #define msgrate 2
  80. static int maxqmsg;
  81. static struct msgq_head mq, hq, modeq;
  82. static int burst;
  83. #include "cmdsserv.c"
  84. #include "tclserv.c"
  85. static void
  86. deq_msg ()
  87. {
  88. struct msgq *q;
  89. int ok = 0;
  90. if ((now - last_time) >= msgrate || now < (last_time - 90))
  91. {
  92. last_time = now;
  93. if (burst > 0)
  94. burst--;
  95. ok = 1;
  96. }
  97. if (serv < 0)
  98. return;
  99. if (modeq.head)
  100. {
  101. while (modeq.head && (burst < 4) && ((last_time - now) < MAXPENALTY))
  102. {
  103. if (deq_kick (DP_MODE))
  104. {
  105. burst++;
  106. continue;
  107. }
  108. if (!modeq.head)
  109. break;
  110. if (fast_deq (DP_MODE))
  111. {
  112. burst++;
  113. continue;
  114. }
  115. tputs (serv, modeq.head->msg, modeq.head->len);
  116. if (debug_output)
  117. {
  118. modeq.head->msg[strlen (modeq.head->msg) - 1] = 0;
  119. putlog (LOG_SRVOUT, "@", "[m->] %s", modeq.head->msg);
  120. }
  121. modeq.tot--;
  122. last_time += calc_penalty (modeq.head->msg);
  123. q = modeq.head->next;
  124. nfree (modeq.head->msg);
  125. nfree (modeq.head);
  126. modeq.head = q;
  127. burst++;
  128. }
  129. if (!modeq.head)
  130. modeq.last = 0;
  131. return;
  132. }
  133. if (burst > 1)
  134. return;
  135. if (mq.head)
  136. {
  137. burst++;
  138. if (deq_kick (DP_SERVER))
  139. return;
  140. if (fast_deq (DP_SERVER))
  141. return;
  142. tputs (serv, mq.head->msg, mq.head->len);
  143. if (debug_output)
  144. {
  145. mq.head->msg[strlen (mq.head->msg) - 1] = 0;
  146. putlog (LOG_SRVOUT, "@", "[s->] %s", mq.head->msg);
  147. }
  148. mq.tot--;
  149. last_time += calc_penalty (mq.head->msg);
  150. q = mq.head->next;
  151. nfree (mq.head->msg);
  152. nfree (mq.head);
  153. mq.head = q;
  154. if (!mq.head)
  155. mq.last = NULL;
  156. return;
  157. }
  158. if (!hq.head || burst || !ok)
  159. return;
  160. if (deq_kick (DP_HELP))
  161. return;
  162. if (fast_deq (DP_HELP))
  163. return;
  164. tputs (serv, hq.head->msg, hq.head->len);
  165. if (debug_output)
  166. {
  167. hq.head->msg[strlen (hq.head->msg) - 1] = 0;
  168. putlog (LOG_SRVOUT, "*", "[h->] %s", hq.head->msg);
  169. }
  170. hq.tot--;
  171. last_time += calc_penalty (hq.head->msg);
  172. q = hq.head->next;
  173. nfree (hq.head->msg);
  174. nfree (hq.head);
  175. hq.head = q;
  176. if (!hq.head)
  177. hq.last = NULL;
  178. }
  179. static int
  180. calc_penalty (char *msg)
  181. {
  182. char *cmd, *par1, *par2, *par3;
  183. register int penalty, i, ii;
  184. if (!use_penalties && net_type != NETT_UNDERNET
  185. && net_type != NETT_HYBRID_EFNET)
  186. return 0;
  187. if (msg[strlen (msg) - 1] == '\n')
  188. msg[strlen (msg) - 1] = '\0';
  189. cmd = newsplit (&msg);
  190. if (msg)
  191. i = strlen (msg);
  192. else
  193. i = strlen (cmd);
  194. last_time -= 2;
  195. if (net_type == NETT_UNDERNET || net_type == NETT_HYBRID_EFNET)
  196. {
  197. last_time += (2 + i / 120);
  198. return 0;
  199. }
  200. penalty = (1 + i / 100);
  201. if (!egg_strcasecmp (cmd, "KICK"))
  202. {
  203. par1 = newsplit (&msg);
  204. par2 = newsplit (&msg);
  205. par3 = splitnicks (&par2);
  206. penalty++;
  207. while (strlen (par3) > 0)
  208. {
  209. par3 = splitnicks (&par2);
  210. penalty++;
  211. }
  212. ii = penalty;
  213. par3 = splitnicks (&par1);
  214. while (strlen (par1) > 0)
  215. {
  216. par3 = splitnicks (&par1);
  217. penalty += ii;
  218. }
  219. }
  220. else if (!egg_strcasecmp (cmd, "MODE"))
  221. {
  222. i = 0;
  223. par1 = newsplit (&msg);
  224. par2 = newsplit (&msg);
  225. if (!strlen (par2))
  226. i++;
  227. while (strlen (par2) > 0)
  228. {
  229. if (strchr ("ntimps", par2[0]))
  230. i += 3;
  231. else if (!strchr ("+-", par2[0]))
  232. i += 1;
  233. par2++;
  234. }
  235. while (strlen (msg) > 0)
  236. {
  237. newsplit (&msg);
  238. i += 2;
  239. }
  240. ii = 0;
  241. while (strlen (par1) > 0)
  242. {
  243. splitnicks (&par1);
  244. ii++;
  245. }
  246. penalty += (ii * i);
  247. }
  248. else if (!egg_strcasecmp (cmd, "TOPIC"))
  249. {
  250. penalty++;
  251. par1 = newsplit (&msg);
  252. par2 = newsplit (&msg);
  253. if (strlen (par2) > 0)
  254. {
  255. penalty += 2;
  256. par3 = splitnicks (&par1);
  257. while (strlen (par1) > 0)
  258. {
  259. par3 = splitnicks (&par1);
  260. penalty += 2;
  261. }
  262. }
  263. }
  264. else if (!egg_strcasecmp (cmd, "PRIVMSG")
  265. || !egg_strcasecmp (cmd, "NOTICE"))
  266. {
  267. par1 = newsplit (&msg);
  268. while (strlen (par1) > 0)
  269. {
  270. splitnicks (&par1);
  271. penalty++;
  272. }
  273. }
  274. else if (!egg_strcasecmp (cmd, "WHO"))
  275. {
  276. par1 = newsplit (&msg);
  277. par2 = par1;
  278. while (strlen (par1) > 0)
  279. {
  280. par2 = splitnicks (&par1);
  281. if (strlen (par2) > 4)
  282. penalty += 3;
  283. else
  284. penalty += 5;
  285. }
  286. }
  287. else if (!egg_strcasecmp (cmd, "AWAY"))
  288. {
  289. if (strlen (msg) > 0)
  290. penalty += 2;
  291. else
  292. penalty += 1;
  293. }
  294. else if (!egg_strcasecmp (cmd, "INVITE"))
  295. {
  296. penalty += 3;
  297. }
  298. else if (!egg_strcasecmp (cmd, "JOIN"))
  299. {
  300. penalty += 2;
  301. }
  302. else if (!egg_strcasecmp (cmd, "PART"))
  303. {
  304. penalty += 4;
  305. }
  306. else if (!egg_strcasecmp (cmd, "VERSION"))
  307. {
  308. penalty += 2;
  309. }
  310. else if (!egg_strcasecmp (cmd, "TIME"))
  311. {
  312. penalty += 2;
  313. }
  314. else if (!egg_strcasecmp (cmd, "TRACE"))
  315. {
  316. penalty += 2;
  317. }
  318. else if (!egg_strcasecmp (cmd, "NICK"))
  319. {
  320. penalty += 3;
  321. }
  322. else if (!egg_strcasecmp (cmd, "ISON"))
  323. {
  324. penalty += 1;
  325. }
  326. else if (!egg_strcasecmp (cmd, "WHOIS"))
  327. {
  328. penalty += 2;
  329. }
  330. else if (!egg_strcasecmp (cmd, "DNS"))
  331. {
  332. penalty += 2;
  333. }
  334. else
  335. penalty++;
  336. if (penalty > 99)
  337. penalty = 99;
  338. if (penalty < 2)
  339. {
  340. putlog (LOG_SRVOUT, "*", "Penalty < 2sec, that's impossible!");
  341. penalty = 2;
  342. }
  343. if (debug_output && penalty != 0)
  344. putlog (LOG_SRVOUT, "*", "Adding penalty: %i", penalty);
  345. return penalty;
  346. }
  347. char *
  348. splitnicks (char **rest)
  349. {
  350. register char *o, *r;
  351. if (!rest)
  352. return *rest = "";
  353. o = *rest;
  354. while (*o == ' ')
  355. o++;
  356. r = o;
  357. while (*o && *o != ',')
  358. o++;
  359. if (*o)
  360. *o++ = 0;
  361. *rest = o;
  362. return r;
  363. }
  364. static int
  365. fast_deq (int which)
  366. {
  367. struct msgq_head *h;
  368. struct msgq *m, *nm;
  369. char msgstr[511], nextmsgstr[511], tosend[511], victims[511],
  370. stackable[511], *msg, *nextmsg, *cmd, *nextcmd, *to, *nextto, *stckbl;
  371. int len, doit = 0, found = 0, cmd_count = 0, stack_method = 1;
  372. if (!use_fastdeq)
  373. return 0;
  374. switch (which)
  375. {
  376. case DP_MODE:
  377. h = &modeq;
  378. break;
  379. case DP_SERVER:
  380. h = &mq;
  381. break;
  382. case DP_HELP:
  383. h = &hq;
  384. break;
  385. default:
  386. return 0;
  387. }
  388. m = h->head;
  389. strncpyz (msgstr, m->msg, sizeof msgstr);
  390. msg = msgstr;
  391. cmd = newsplit (&msg);
  392. if (use_fastdeq > 1)
  393. {
  394. strncpyz (stackable, stackablecmds, sizeof stackable);
  395. stckbl = stackable;
  396. while (strlen (stckbl) > 0)
  397. if (!egg_strcasecmp (newsplit (&stckbl), cmd))
  398. {
  399. found = 1;
  400. break;
  401. }
  402. if (use_fastdeq == 2 && !found)
  403. return 0;
  404. if (use_fastdeq == 3 && found)
  405. return 0;
  406. strncpyz (stackable, stackable2cmds, sizeof stackable);
  407. stckbl = stackable;
  408. while (strlen (stckbl) > 0)
  409. if (!egg_strcasecmp (newsplit (&stckbl), cmd))
  410. {
  411. stack_method = 2;
  412. break;
  413. }
  414. }
  415. to = newsplit (&msg);
  416. len = strlen (to);
  417. if (to[len - 1] == '\n')
  418. to[len - 1] = 0;
  419. simple_sprintf (victims, "%s", to);
  420. while (m)
  421. {
  422. nm = m->next;
  423. if (!nm)
  424. break;
  425. strncpyz (nextmsgstr, nm->msg, sizeof nextmsgstr);
  426. nextmsg = nextmsgstr;
  427. nextcmd = newsplit (&nextmsg);
  428. nextto = newsplit (&nextmsg);
  429. len = strlen (nextto);
  430. if (nextto[len - 1] == '\n')
  431. nextto[len - 1] = 0;
  432. if (strcmp (to, nextto) && !strcmp (cmd, nextcmd)
  433. && !strcmp (msg, nextmsg)
  434. &&
  435. ((strlen (cmd) + strlen (victims) + strlen (nextto) + strlen (msg) +
  436. 2) < 510) && (!stack_limit || cmd_count < stack_limit - 1))
  437. {
  438. cmd_count++;
  439. if (stack_method == 1)
  440. simple_sprintf (victims, "%s,%s", victims, nextto);
  441. else
  442. simple_sprintf (victims, "%s %s", victims, nextto);
  443. doit = 1;
  444. m->next = nm->next;
  445. if (!nm->next)
  446. h->last = m;
  447. nfree (nm->msg);
  448. nfree (nm);
  449. h->tot--;
  450. }
  451. else
  452. m = m->next;
  453. }
  454. if (doit)
  455. {
  456. simple_sprintf (tosend, "%s %s %s", cmd, victims, msg);
  457. len = strlen (tosend);
  458. tosend[len - 1] = '\n';
  459. tputs (serv, tosend, len);
  460. m = h->head->next;
  461. nfree (h->head->msg);
  462. nfree (h->head);
  463. h->head = m;
  464. if (!h->head)
  465. h->last = 0;
  466. h->tot--;
  467. if (debug_output)
  468. {
  469. tosend[len - 1] = 0;
  470. switch (which)
  471. {
  472. case DP_MODE:
  473. putlog (LOG_SRVOUT, "*", "[m=>] %s", tosend);
  474. break;
  475. case DP_SERVER:
  476. putlog (LOG_SRVOUT, "*", "[s=>] %s", tosend);
  477. break;
  478. case DP_HELP:
  479. putlog (LOG_SRVOUT, "*", "[h=>] %s", tosend);
  480. break;
  481. }
  482. }
  483. last_time += calc_penalty (tosend);
  484. return 1;
  485. }
  486. return 0;
  487. }
  488. static void
  489. check_queues (char *oldnick, char *newnick)
  490. {
  491. if (optimize_kicks == 2)
  492. {
  493. if (modeq.head)
  494. parse_q (&modeq, oldnick, newnick);
  495. if (mq.head)
  496. parse_q (&mq, oldnick, newnick);
  497. if (hq.head)
  498. parse_q (&hq, oldnick, newnick);
  499. }
  500. }
  501. static void
  502. parse_q (struct msgq_head *q, char *oldnick, char *newnick)
  503. {
  504. struct msgq *m, *lm = NULL;
  505. char buf[511], *msg, *nicks, *nick, *chan, newnicks[511], newmsg[511];
  506. int changed;
  507. for (m = q->head; m;)
  508. {
  509. changed = 0;
  510. if (optimize_kicks == 2 && !egg_strncasecmp (m->msg, "KICK ", 5))
  511. {
  512. newnicks[0] = 0;
  513. strncpyz (buf, m->msg, sizeof buf);
  514. if (buf[0] && (buf[strlen (buf) - 1] == '\n'))
  515. buf[strlen (buf) - 1] = '\0';
  516. msg = buf;
  517. newsplit (&msg);
  518. chan = newsplit (&msg);
  519. nicks = newsplit (&msg);
  520. while (strlen (nicks) > 0)
  521. {
  522. nick = splitnicks (&nicks);
  523. if (!egg_strcasecmp (nick, oldnick)
  524. &&
  525. ((9 + strlen (chan) + strlen (newnicks) + strlen (newnick) +
  526. strlen (nicks) + strlen (msg)) < 510))
  527. {
  528. if (newnick)
  529. egg_snprintf (newnicks, sizeof newnicks, "%s,%s",
  530. newnicks, newnick);
  531. changed = 1;
  532. }
  533. else
  534. egg_snprintf (newnicks, sizeof newnicks, ",%s", nick);
  535. }
  536. egg_snprintf (newmsg, sizeof newmsg, "KICK %s %s %s\n", chan,
  537. newnicks + 1, msg);
  538. }
  539. if (changed)
  540. {
  541. if (newnicks[0] == 0)
  542. {
  543. if (!lm)
  544. q->head = m->next;
  545. else
  546. lm->next = m->next;
  547. nfree (m->msg);
  548. nfree (m);
  549. m = lm;
  550. q->tot--;
  551. if (!q->head)
  552. q->last = 0;
  553. }
  554. else
  555. {
  556. nfree (m->msg);
  557. m->msg = nmalloc (strlen (newmsg) + 1);
  558. m->len = strlen (newmsg);
  559. strcpy (m->msg, newmsg);
  560. }
  561. }
  562. lm = m;
  563. if (m)
  564. m = m->next;
  565. else
  566. m = q->head;
  567. }
  568. }
  569. static void
  570. purge_kicks (struct msgq_head *q)
  571. {
  572. struct msgq *m, *lm = NULL;
  573. char buf[511], *reason, *nicks, *nick, *chan, newnicks[511], newmsg[511],
  574. chans[511], *chns, *ch;
  575. int changed, found;
  576. struct chanset_t *cs;
  577. for (m = q->head; m;)
  578. {
  579. if (!egg_strncasecmp (m->msg, "KICK", 4))
  580. {
  581. newnicks[0] = 0;
  582. changed = 0;
  583. strncpyz (buf, m->msg, sizeof buf);
  584. if (buf[0] && (buf[strlen (buf) - 1] == '\n'))
  585. buf[strlen (buf) - 1] = '\0';
  586. reason = buf;
  587. newsplit (&reason);
  588. chan = newsplit (&reason);
  589. nicks = newsplit (&reason);
  590. while (strlen (nicks) > 0)
  591. {
  592. found = 0;
  593. nick = splitnicks (&nicks);
  594. strncpyz (chans, chan, sizeof chans);
  595. chns = chans;
  596. while (strlen (chns) > 0)
  597. {
  598. ch = newsplit (&chns);
  599. cs = findchan (ch);
  600. if (!cs)
  601. continue;
  602. if (ismember (cs, nick))
  603. found = 1;
  604. }
  605. if (found)
  606. egg_snprintf (newnicks, sizeof newnicks, "%s,%s", newnicks,
  607. nick);
  608. else
  609. {
  610. putlog (LOG_SRVOUT, "*",
  611. "%s isn't on any target channel, removing "
  612. "kick...", nick);
  613. changed = 1;
  614. }
  615. }
  616. if (changed)
  617. {
  618. if (newnicks[0] == 0)
  619. {
  620. if (!lm)
  621. q->head = m->next;
  622. else
  623. lm->next = m->next;
  624. nfree (m->msg);
  625. nfree (m);
  626. m = lm;
  627. q->tot--;
  628. if (!q->head)
  629. q->last = 0;
  630. }
  631. else
  632. {
  633. nfree (m->msg);
  634. egg_snprintf (newmsg, sizeof newmsg, "KICK %s %s %s\n",
  635. chan, newnicks + 1, reason);
  636. m->msg = nmalloc (strlen (newmsg) + 1);
  637. m->len = strlen (newmsg);
  638. strcpy (m->msg, newmsg);
  639. }
  640. }
  641. }
  642. lm = m;
  643. if (m)
  644. m = m->next;
  645. else
  646. m = q->head;
  647. }
  648. }
  649. static int
  650. deq_kick (int which)
  651. {
  652. struct msgq_head *h;
  653. struct msgq *msg, *m, *lm;
  654. char buf[511], buf2[511], *reason2, *nicks, *chan, *chan2, *reason, *nick,
  655. newnicks[511], newnicks2[511], newmsg[511];
  656. int changed = 0, nr = 0;
  657. if (!optimize_kicks)
  658. return 0;
  659. newnicks[0] = 0;
  660. switch (which)
  661. {
  662. case DP_MODE:
  663. h = &modeq;
  664. break;
  665. case DP_SERVER:
  666. h = &mq;
  667. break;
  668. case DP_HELP:
  669. h = &hq;
  670. break;
  671. default:
  672. return 0;
  673. }
  674. if (egg_strncasecmp (h->head->msg, "KICK", 4))
  675. return 0;
  676. if (optimize_kicks == 2)
  677. {
  678. purge_kicks (h);
  679. if (!h->head)
  680. return 1;
  681. }
  682. if (egg_strncasecmp (h->head->msg, "KICK", 4))
  683. return 0;
  684. msg = h->head;
  685. strncpyz (buf, msg->msg, sizeof buf);
  686. reason = buf;
  687. newsplit (&reason);
  688. chan = newsplit (&reason);
  689. nicks = newsplit (&reason);
  690. while (strlen (nicks) > 0)
  691. {
  692. egg_snprintf (newnicks, sizeof newnicks, "%s,%s", newnicks,
  693. newsplit (&nicks));
  694. nr++;
  695. }
  696. for (m = msg->next, lm = NULL; m && (nr < kick_method);)
  697. {
  698. if (!egg_strncasecmp (m->msg, "KICK", 4))
  699. {
  700. changed = 0;
  701. newnicks2[0] = 0;
  702. strncpyz (buf2, m->msg, sizeof buf2);
  703. if (buf2[0] && (buf2[strlen (buf2) - 1] == '\n'))
  704. buf2[strlen (buf2) - 1] = '\0';
  705. reason2 = buf2;
  706. newsplit (&reason2);
  707. chan2 = newsplit (&reason2);
  708. nicks = newsplit (&reason2);
  709. if (!egg_strcasecmp (chan, chan2)
  710. && !egg_strcasecmp (reason, reason2))
  711. {
  712. while (strlen (nicks) > 0)
  713. {
  714. nick = splitnicks (&nicks);
  715. if ((nr < kick_method)
  716. &&
  717. ((9 + strlen (chan) + strlen (newnicks) +
  718. strlen (nick) + strlen (reason)) < 510))
  719. {
  720. egg_snprintf (newnicks, sizeof newnicks, "%s,%s",
  721. newnicks, nick);
  722. nr++;
  723. changed = 1;
  724. }
  725. else
  726. egg_snprintf (newnicks2, sizeof newnicks2, "%s,%s",
  727. newnicks2, nick);
  728. }
  729. }
  730. if (changed)
  731. {
  732. if (newnicks2[0] == 0)
  733. {
  734. if (!lm)
  735. h->head->next = m->next;
  736. else
  737. lm->next = m->next;
  738. nfree (m->msg);
  739. nfree (m);
  740. m = lm;
  741. h->tot--;
  742. if (!h->head)
  743. h->last = 0;
  744. }
  745. else
  746. {
  747. nfree (m->msg);
  748. egg_snprintf (newmsg, sizeof newmsg, "KICK %s %s %s\n",
  749. chan2, newnicks2 + 1, reason);
  750. m->msg = nmalloc (strlen (newmsg) + 1);
  751. m->len = strlen (newmsg);
  752. strcpy (m->msg, newmsg);
  753. }
  754. }
  755. }
  756. lm = m;
  757. if (m)
  758. m = m->next;
  759. else
  760. m = h->head->next;
  761. }
  762. egg_snprintf (newmsg, sizeof newmsg, "KICK %s %s %s\n", chan, newnicks + 1,
  763. reason);
  764. tputs (serv, newmsg, strlen (newmsg));
  765. if (debug_output)
  766. {
  767. newmsg[strlen (newmsg) - 1] = 0;
  768. switch (which)
  769. {
  770. case DP_MODE:
  771. putlog (LOG_SRVOUT, "@", "[m->] %s", newmsg);
  772. break;
  773. case DP_SERVER:
  774. putlog (LOG_SRVOUT, "@", "[s->] %s", newmsg);
  775. break;
  776. case DP_HELP:
  777. putlog (LOG_SRVOUT, "@", "[h->] %s", newmsg);
  778. break;
  779. }
  780. debug3 ("Changed: %d, kick-method: %d, nr: %d", changed, kick_method,
  781. nr);
  782. }
  783. h->tot--;
  784. last_time += calc_penalty (newmsg);
  785. m = h->head->next;
  786. nfree (h->head->msg);
  787. nfree (h->head);
  788. h->head = m;
  789. if (!h->head)
  790. h->last = 0;
  791. return 1;
  792. }
  793. static void
  794. empty_msgq ()
  795. {
  796. msgq_clear (&modeq);
  797. msgq_clear (&mq);
  798. msgq_clear (&hq);
  799. burst = 0;
  800. } static void
  801. queue_server (int which, char *buf, int len)
  802. {
  803. struct msgq_head *h = NULL, tempq;
  804. struct msgq *q, *tq, *tqq;
  805. int doublemsg = 0, qnext = 0;
  806. if (serv < 0)
  807. return;
  808. if (!egg_strncasecmp (buf, "PING", 4) || !egg_strncasecmp (buf, "PONG", 4))
  809. {
  810. if (buf[1] == 'I' || buf[1] == 'i')
  811. lastpingtime = now;
  812. tputs (serv, buf, len);
  813. if (debug_output)
  814. {
  815. if (buf[len - 1] == '\n')
  816. buf[len - 1] = 0;
  817. putlog (LOG_SRVOUT, "@", "[m->] %s", buf);
  818. }
  819. return;
  820. }
  821. switch (which)
  822. {
  823. case DP_MODE_NEXT:
  824. qnext = 1;
  825. case DP_MODE:
  826. h = &modeq;
  827. tempq = modeq;
  828. if (double_mode)
  829. doublemsg = 1;
  830. break;
  831. case DP_SERVER_NEXT:
  832. qnext = 1;
  833. case DP_SERVER:
  834. h = &mq;
  835. tempq = mq;
  836. if (double_server)
  837. doublemsg = 1;
  838. break;
  839. case DP_HELP_NEXT:
  840. qnext = 1;
  841. case DP_HELP:
  842. h = &hq;
  843. tempq = hq;
  844. if (double_help)
  845. doublemsg = 1;
  846. break;
  847. default:
  848. putlog (LOG_MISC, "*", "!!! queuing unknown type to server!!");
  849. return;
  850. }
  851. if (h->tot < maxqmsg)
  852. {
  853. if (!doublemsg)
  854. for (tq = tempq.head; tq; tq = tqq)
  855. {
  856. tqq = tq->next;
  857. if (!egg_strcasecmp (tq->msg, buf))
  858. {
  859. if (!double_warned)
  860. {
  861. if (buf[len - 1] == '\n')
  862. buf[len - 1] = 0;
  863. debug1 ("msg already queued. skipping: %s", buf);
  864. double_warned = 1;
  865. }
  866. return;
  867. }
  868. }
  869. q = nmalloc (sizeof (struct msgq));
  870. if (qnext)
  871. q->next = h->head;
  872. else
  873. q->next = NULL;
  874. if (h->head)
  875. {
  876. if (!qnext)
  877. h->last->next = q;
  878. }
  879. else
  880. h->head = q;
  881. if (qnext)
  882. h->head = q;
  883. h->last = q;
  884. q->len = len;
  885. q->msg = nmalloc (len + 1);
  886. strncpyz (q->msg, buf, len + 1);
  887. h->tot++;
  888. h->warned = 0;
  889. double_warned = 0;
  890. }
  891. else
  892. {
  893. if (!h->warned)
  894. {
  895. switch (which)
  896. {
  897. case DP_MODE_NEXT:
  898. case DP_MODE:
  899. putlog (LOG_MISC, "*", "!!! OVER MAXIMUM MODE QUEUE");
  900. break;
  901. case DP_SERVER_NEXT:
  902. case DP_SERVER:
  903. putlog (LOG_MISC, "*", "!!! OVER MAXIMUM SERVER QUEUE");
  904. break;
  905. case DP_HELP_NEXT:
  906. case DP_HELP:
  907. putlog (LOG_MISC, "*", "!!! OVER MAXIMUM HELP QUEUE");
  908. break;
  909. }
  910. }
  911. h->warned = 1;
  912. }
  913. if (debug_output && !h->warned)
  914. {
  915. if (buf[len - 1] == '\n')
  916. buf[len - 1] = 0;
  917. switch (which)
  918. {
  919. case DP_MODE:
  920. putlog (LOG_SRVOUT, "@", "[!m] %s", buf);
  921. break;
  922. case DP_SERVER:
  923. putlog (LOG_SRVOUT, "@", "[!s] %s", buf);
  924. break;
  925. case DP_HELP:
  926. putlog (LOG_SRVOUT, "@", "[!h] %s", buf);
  927. break;
  928. case DP_MODE_NEXT:
  929. putlog (LOG_SRVOUT, "@", "[!!m] %s", buf);
  930. break;
  931. case DP_SERVER_NEXT:
  932. putlog (LOG_SRVOUT, "@", "[!!s] %s", buf);
  933. break;
  934. case DP_HELP_NEXT:
  935. putlog (LOG_SRVOUT, "@", "[!!h] %s", buf);
  936. break;
  937. }
  938. }
  939. if (which == DP_MODE || which == DP_MODE_NEXT)
  940. deq_msg ();
  941. }
  942. static void
  943. add_server (char *ss)
  944. {
  945. struct server_list *x, *z;
  946. char *p, *q;
  947. for (z = serverlist; z && z->next; z = z->next);
  948. while (ss)
  949. {
  950. p = strchr (ss, ',');
  951. if (p)
  952. *p++ = 0;
  953. x = nmalloc (sizeof (struct server_list));
  954. x->next = 0;
  955. x->realname = 0;
  956. x->port = 0;
  957. if (z)
  958. z->next = x;
  959. else
  960. serverlist = x;
  961. z = x;
  962. q = strchr (ss, ':');
  963. if (!q)
  964. {
  965. x->port = default_port;
  966. x->pass = 0;
  967. x->name = nmalloc (strlen (ss) + 1);
  968. strcpy (x->name, ss);
  969. }
  970. else
  971. {
  972. *q++ = 0;
  973. x->name = nmalloc (q - ss);
  974. strcpy (x->name, ss);
  975. ss = q;
  976. q = strchr (ss, ':');
  977. if (!q)
  978. {
  979. x->pass = 0;
  980. }
  981. else
  982. {
  983. *q++ = 0;
  984. x->pass = nmalloc (strlen (q) + 1);
  985. strcpy (x->pass, q);
  986. }
  987. x->port = atoi (ss);
  988. }
  989. ss = p;
  990. }
  991. }
  992. static void
  993. clearq (struct server_list *xx)
  994. {
  995. struct server_list *x;
  996. while (xx)
  997. {
  998. x = xx->next;
  999. if (xx->name)
  1000. nfree (xx->name);
  1001. if (xx->pass)
  1002. nfree (xx->pass);
  1003. if (xx->realname)
  1004. nfree (xx->realname);
  1005. nfree (xx);
  1006. xx = x;
  1007. }
  1008. }
  1009. void
  1010. servers_describe (struct cfg_entry *entry, int idx)
  1011. {
  1012. } void
  1013. servers6_describe (struct cfg_entry *entry, int idx)
  1014. {
  1015. } int
  1016. count (const char *s)
  1017. {
  1018. char *ele;
  1019. int i = 0;
  1020. char count[1000];
  1021. strcpy (count, s);
  1022. ele = strtok (count, ",");
  1023. while (ele && *ele)
  1024. {
  1025. i++;
  1026. ele = strtok ((char *) NULL, ",");
  1027. } return i - 1;
  1028. }
  1029. int
  1030. rrand (int a, int b)
  1031. {
  1032. b++;
  1033. return ((random () % (b - a)) + a);
  1034. }
  1035. char *
  1036. randomize (char *line, char **new)
  1037. {
  1038. char *str, *words[1000], *bak;
  1039. int i, o, b, r, u = 0;
  1040. Context;
  1041. bak = line;
  1042. i = count (line);
  1043. b = i + 1;
  1044. str = strtok (line, ",");
  1045. o = 0;
  1046. while (str && *str)
  1047. {
  1048. words[o] = str;
  1049. o++;
  1050. str = strtok ((char *) NULL, ",");
  1051. } while (b)
  1052. {
  1053. if (u > 200)
  1054. {
  1055. sprintf (*new, "%s", bak);
  1056. return *new;
  1057. }
  1058. r = rrand (0, i);
  1059. if (strstr (*new, words[r]) == NULL)
  1060. {
  1061. if (b == i + 1)
  1062. sprintf (*new, "%s", words[r]);
  1063. else
  1064. sprintf (*new, "%s,%s", *new, words[r]);
  1065. b--;
  1066. }
  1067. else
  1068. u++;
  1069. }
  1070. return *new;
  1071. }
  1072. void
  1073. servers_changed (struct cfg_entry *entry, char *olddata, int *valid)
  1074. {
  1075. #ifdef LEAF
  1076. char *slist, *p;
  1077. #ifdef S_RANDSERVERS
  1078. char *new;
  1079. if (hostname6[0])
  1080. return;
  1081. #endif
  1082. slist =
  1083. (char *) (entry->ldata ? entry->
  1084. ldata : (entry->gdata ? entry->gdata : ""));
  1085. if (serverlist)
  1086. {
  1087. clearq (serverlist);
  1088. serverlist = NULL;
  1089. }
  1090. p = nmalloc (strlen (slist) + 1);
  1091. strcpy (p, slist);
  1092. #ifdef S_RANDSERVERS
  1093. new = nmalloc (strlen (slist) + 1);
  1094. randomize (p, &new);
  1095. strcpy (p, new);
  1096. #endif
  1097. add_server (p);
  1098. nfree (p);
  1099. nfree (new);
  1100. #endif
  1101. }
  1102. void
  1103. servers6_changed (struct cfg_entry *entry, char *olddata, int *valid)
  1104. {
  1105. #ifdef LEAF
  1106. char *slist, *p;
  1107. #ifdef S_RANDSERVERS
  1108. char *new;
  1109. if (!hostname6[0])
  1110. return;
  1111. #endif
  1112. slist =
  1113. (char *) (entry->ldata ? entry->
  1114. ldata : (entry->gdata ? entry->gdata : ""));
  1115. if (serverlist)
  1116. {
  1117. clearq (serverlist);
  1118. serverlist = NULL;
  1119. }
  1120. p = nmalloc (strlen (slist) + 1);
  1121. strcpy (p, slist);
  1122. #ifdef S_RANDSERVERS
  1123. new = nmalloc (strlen (slist) + 1);
  1124. randomize (p, &new);
  1125. strcpy (p, new);
  1126. #endif
  1127. add_server (p);
  1128. nfree (p);
  1129. nfree (new);
  1130. #endif
  1131. }
  1132. void
  1133. nick_describe (struct cfg_entry *entry, int idx)
  1134. {
  1135. } void
  1136. nick_changed (struct cfg_entry *entry, char *olddata, int *valid)
  1137. {
  1138. #ifdef LEAF
  1139. char *p;
  1140. if (entry->ldata)
  1141. p = entry->ldata;
  1142. else if (entry->gdata)
  1143. p = entry->gdata;
  1144. else
  1145. p = NULL;
  1146. if (p && p[0])
  1147. {
  1148. strncpy0 (origbotname, p, NICKMAX + 1);
  1149. }
  1150. else
  1151. {
  1152. strncpy0 (origbotname, botnetnick, NICKMAX + 1);
  1153. }
  1154. #endif
  1155. }
  1156. void
  1157. realname_describe (struct cfg_entry *entry, int idx)
  1158. {
  1159. } void
  1160. realname_changed (struct cfg_entry *entry, char *olddata, int *valid)
  1161. {
  1162. #ifdef LEAF
  1163. if (entry->ldata)
  1164. {
  1165. strncpy0 (botrealname, (char *) entry->ldata, 120);
  1166. }
  1167. else if (entry->gdata)
  1168. {
  1169. strncpy0 (botrealname, (char *) entry->gdata, 120);
  1170. }
  1171. #endif
  1172. } struct cfg_entry CFG_SERVERS =
  1173. { "servers", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL, servers_changed,
  1174. servers_changed, servers_describe };
  1175. struct cfg_entry CFG_SERVERS6 =
  1176. { "servers6", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL, servers6_changed,
  1177. servers6_changed, servers6_describe };
  1178. struct cfg_entry CFG_NICK =
  1179. { "nick", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL, nick_changed, nick_changed,
  1180. nick_describe };
  1181. struct cfg_entry CFG_REALNAME =
  1182. { "realname", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL, realname_changed,
  1183. realname_changed, realname_describe };
  1184. static void
  1185. next_server (int *ptr, char *serv, unsigned int *port, char *pass)
  1186. {
  1187. struct server_list *x = serverlist;
  1188. int i = 0;
  1189. if (x == NULL)
  1190. return;
  1191. if (*ptr == (-1))
  1192. {
  1193. for (; x; x = x->next)
  1194. {
  1195. if (x->port == *port)
  1196. {
  1197. if (!egg_strcasecmp (x->name, serv))
  1198. {
  1199. *ptr = i;
  1200. return;
  1201. }
  1202. else if (x->realname && !egg_strcasecmp (x->realname, serv))
  1203. {
  1204. *ptr = i;
  1205. strncpyz (serv, x->realname, sizeof serv);
  1206. return;
  1207. }
  1208. }
  1209. i++;
  1210. }
  1211. x = nmalloc (sizeof (struct server_list));
  1212. x->next = 0;
  1213. x->realname = 0;
  1214. x->name = nmalloc (strlen (serv) + 1);
  1215. strcpy (x->name, serv);
  1216. x->port = *port ? *port : default_port;
  1217. if (pass && pass[0])
  1218. {
  1219. x->pass = nmalloc (strlen (pass) + 1);
  1220. strcpy (x->pass, pass);
  1221. }
  1222. else
  1223. x->pass = NULL;
  1224. list_append ((struct list_type **) (&serverlist),
  1225. (struct list_type *) x);
  1226. *ptr = i;
  1227. return;
  1228. }
  1229. i = (*ptr);
  1230. while (i > 0 && x != NULL)
  1231. {
  1232. x = x->next;
  1233. i--;
  1234. }
  1235. if (x != NULL)
  1236. {
  1237. x = x->next;
  1238. (*ptr)++;
  1239. }
  1240. if (x == NULL)
  1241. {
  1242. x = serverlist;
  1243. *ptr = 0;
  1244. }
  1245. strcpy (serv, x->name);
  1246. *port = x->port ? x->port : default_port;
  1247. if (x->pass)
  1248. strcpy (pass, x->pass);
  1249. else
  1250. pass[0] = 0;
  1251. }
  1252. static int server_6char STDVAR
  1253. {
  1254. Function F = (Function) cd;
  1255. char x[20];
  1256. BADARGS (7, 7, " nick user@host handle desto/chan keyword/nick text");
  1257. CHECKVALIDITY (server_6char);
  1258. egg_snprintf (x, sizeof x, "%d",
  1259. F (argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]));
  1260. Tcl_AppendResult (irp, x, NULL);
  1261. return TCL_OK;
  1262. }
  1263. static int server_5char STDVAR
  1264. {
  1265. Function F = (Function) cd;
  1266. BADARGS (6, 6, " nick user@host handle channel text");
  1267. CHECKVALIDITY (server_5char);
  1268. F (argv[1], argv[2], argv[3], argv[4], argv[5]);
  1269. return TCL_OK;
  1270. }
  1271. static int server_2char STDVAR
  1272. {
  1273. Function F = (Function) cd;
  1274. BADARGS (3, 3, " nick msg");
  1275. CHECKVALIDITY (server_2char);
  1276. F (argv[1], argv[2]);
  1277. return TCL_OK;
  1278. }
  1279. static int server_msg STDVAR
  1280. {
  1281. Function F = (Function) cd;
  1282. BADARGS (5, 5, " nick uhost hand buffer");
  1283. CHECKVALIDITY (server_msg);
  1284. F (argv[1], argv[2], get_user_by_handle (userlist, argv[3]), argv[4]);
  1285. return TCL_OK;
  1286. }
  1287. static int server_raw STDVAR
  1288. {
  1289. Function F = (Function) cd;
  1290. BADARGS (4, 4, " from code args");
  1291. CHECKVALIDITY (server_raw);
  1292. Tcl_AppendResult (irp, int_to_base10 (F (argv[1], argv[3])), NULL);
  1293. return TCL_OK;
  1294. }
  1295. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1296. static char *
  1297. nick_change (ClientData cdata, Tcl_Interp * irp, CONST char *name1,
  1298. CONST char *name2, int flags)
  1299. #else
  1300. static char *
  1301. nick_change (ClientData cdata, Tcl_Interp * irp, char *name1, char *name2,
  1302. int flags)
  1303. #endif
  1304. {
  1305. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1306. CONST char *new;
  1307. #else
  1308. char *new;
  1309. #endif
  1310. if (flags & (TCL_TRACE_READS | TCL_TRACE_UNSETS))
  1311. {
  1312. Tcl_SetVar2 (interp, name1, name2, origbotname, TCL_GLOBAL_ONLY);
  1313. if (flags & TCL_TRACE_UNSETS)
  1314. Tcl_TraceVar (irp, name1,
  1315. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1316. nick_change, cdata);
  1317. }
  1318. else
  1319. {
  1320. new = Tcl_GetVar2 (interp, name1, name2, TCL_GLOBAL_ONLY);
  1321. if (rfc_casecmp (origbotname, (char *) new))
  1322. {
  1323. if (origbotname[0])
  1324. {
  1325. putlog (LOG_MISC, "*", "* IRC NICK CHANGE: %s -> %s",
  1326. origbotname, new);
  1327. nick_juped = 0;
  1328. }
  1329. strncpyz (origbotname, new, NICKLEN);
  1330. if (server_online)
  1331. dprintf (DP_SERVER, "NICK %s\n", origbotname);
  1332. }
  1333. }
  1334. return NULL;
  1335. }
  1336. static void
  1337. rand_nick (char *nick)
  1338. {
  1339. register char *p = nick;
  1340. while ((p = strchr (p, '?')) != NULL)
  1341. {
  1342. *p = '0' + random () % 10;
  1343. p++;
  1344. }
  1345. }
  1346. static char *
  1347. get_altbotnick (void)
  1348. {
  1349. if (strchr (altnick, '?'))
  1350. {
  1351. if (!raltnick[0])
  1352. {
  1353. strncpyz (raltnick, altnick, NICKLEN);
  1354. rand_nick (raltnick);
  1355. }
  1356. return raltnick;
  1357. }
  1358. else
  1359. return altnick;
  1360. }
  1361. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1362. static char *
  1363. altnick_change (ClientData cdata, Tcl_Interp * irp, CONST char *name1,
  1364. CONST char *name2, int flags)
  1365. #else
  1366. static char *
  1367. altnick_change (ClientData cdata, Tcl_Interp * irp, char *name1, char *name2,
  1368. int flags)
  1369. #endif
  1370. {
  1371. raltnick[0] = 0;
  1372. return NULL;
  1373. }
  1374. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1375. static char *
  1376. traced_server (ClientData cdata, Tcl_Interp * irp, CONST char *name1,
  1377. CONST char *name2, int flags)
  1378. #else
  1379. static char *
  1380. traced_server (ClientData cdata, Tcl_Interp * irp, char *name1, char *name2,
  1381. int flags)
  1382. #endif
  1383. {
  1384. char s[1024];
  1385. if (server_online)
  1386. {
  1387. int servidx = findanyidx (serv);
  1388. simple_sprintf (s, "%s:%u", dcc[servidx].host, dcc[servidx].port);
  1389. }
  1390. else
  1391. s[0] = 0;
  1392. Tcl_SetVar2 (interp, name1, name2, s, TCL_GLOBAL_ONLY);
  1393. if (flags & TCL_TRACE_UNSETS)
  1394. Tcl_TraceVar (irp, name1,
  1395. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1396. traced_server, cdata);
  1397. return NULL;
  1398. }
  1399. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1400. static char *
  1401. traced_botname (ClientData cdata, Tcl_Interp * irp, CONST char *name1,
  1402. CONST char *name2, int flags)
  1403. #else
  1404. static char *
  1405. traced_botname (ClientData cdata, Tcl_Interp * irp, char *name1, char *name2,
  1406. int flags)
  1407. #endif
  1408. {
  1409. char s[1024];
  1410. simple_sprintf (s, "%s%s%s", botname, botuserhost[0] ? "!" : "",
  1411. botuserhost[0] ? botuserhost : "");
  1412. Tcl_SetVar2 (interp, name1, name2, s, TCL_GLOBAL_ONLY);
  1413. if (flags & TCL_TRACE_UNSETS)
  1414. Tcl_TraceVar (irp, name1,
  1415. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1416. traced_botname, cdata);
  1417. return NULL;
  1418. }
  1419. static void
  1420. do_nettype (void)
  1421. {
  1422. switch (net_type)
  1423. {
  1424. case NETT_EFNET:
  1425. check_mode_r = 0;
  1426. nick_len = 9;
  1427. break;
  1428. case NETT_IRCNET:
  1429. check_mode_r = 1;
  1430. use_penalties = 1;
  1431. use_fastdeq = 3;
  1432. nick_len = 9;
  1433. simple_sprintf (stackablecmds, "INVITE AWAY VERSION NICK");
  1434. kick_method = 4;
  1435. break;
  1436. case NETT_UNDERNET:
  1437. check_mode_r = 0;
  1438. use_fastdeq = 2;
  1439. nick_len = 9;
  1440. simple_sprintf (stackablecmds,
  1441. "PRIVMSG NOTICE TOPIC PART WHOIS USERHOST USERIP ISON");
  1442. simple_sprintf (stackable2cmds, "USERHOST USERIP ISON");
  1443. break;
  1444. case NETT_DALNET:
  1445. check_mode_r = 0;
  1446. use_fastdeq = 2;
  1447. nick_len = 32;
  1448. simple_sprintf (stackablecmds,
  1449. "PRIVMSG NOTICE PART WHOIS WHOWAS USERHOST ISON WATCH DCCALLOW");
  1450. simple_sprintf (stackable2cmds, "USERHOST ISON WATCH");
  1451. break;
  1452. case NETT_HYBRID_EFNET:
  1453. check_mode_r = 0;
  1454. nick_len = 9;
  1455. break;
  1456. }
  1457. }
  1458. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1459. static char *
  1460. traced_nettype (ClientData cdata, Tcl_Interp * irp, CONST char *name1,
  1461. CONST char *name2, int flags)
  1462. #else
  1463. static char *
  1464. traced_nettype (ClientData cdata, Tcl_Interp * irp, char *name1, char *name2,
  1465. int flags)
  1466. #endif
  1467. {
  1468. do_nettype ();
  1469. return NULL;
  1470. }
  1471. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1472. static char *
  1473. traced_nicklen (ClientData cdata, Tcl_Interp * irp, CONST char *name1,
  1474. CONST char *name2, int flags)
  1475. #else
  1476. static char *
  1477. traced_nicklen (ClientData cdata, Tcl_Interp * irp, char *name1, char *name2,
  1478. int flags)
  1479. #endif
  1480. {
  1481. if (flags & (TCL_TRACE_READS | TCL_TRACE_UNSETS))
  1482. {
  1483. char s[40];
  1484. egg_snprintf (s, sizeof s, "%d", nick_len);
  1485. Tcl_SetVar2 (interp, name1, name2, s, TCL_GLOBAL_ONLY);
  1486. if (flags & TCL_TRACE_UNSETS)
  1487. Tcl_TraceVar (irp, name1, TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1488. traced_nicklen, cdata);
  1489. }
  1490. else
  1491. {
  1492. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1493. CONST char *cval = Tcl_GetVar2 (interp, name1, name2, TCL_GLOBAL_ONLY);
  1494. #else
  1495. char *cval = Tcl_GetVar2 (interp, name1, name2, TCL_GLOBAL_ONLY);
  1496. #endif
  1497. long lval = 0;
  1498. Context;
  1499. if (cval && Tcl_ExprLong (interp, cval, &lval) != TCL_ERROR)
  1500. {
  1501. if (lval > NICKMAX)
  1502. lval = NICKMAX;
  1503. nick_len = (int) lval;
  1504. }
  1505. } return NULL;
  1506. }
  1507. static tcl_strings my_tcl_strings[] =
  1508. { {"botnick", NULL, 0, STR_PROTECT}, {"altnick", altnick, NICKMAX, 0},
  1509. {"realname", botrealname, 80, 0}, {"init-server", initserver, 120, 0},
  1510. {"connect-server", connectserver, 120, 0}, {"stackable-commands",
  1511. stackablecmds, 510, 0},
  1512. {"stackable2-commands", stackable2cmds, 510, 0}, {NULL, NULL, 0, 0} };
  1513. static tcl_coups my_tcl_coups[] =
  1514. { {"flood-msg", &flud_thr, &flud_time}, {"flood-ctcp", &flud_ctcp_thr,
  1515. &flud_ctcp_time}, {NULL, NULL,
  1516. NULL} };
  1517. static tcl_ints my_tcl_ints[] =
  1518. { {"use-console-r", NULL, 1}, {"servlimit", &min_servs, 0},
  1519. {"server-timeout", &server_timeout, 0}, {"lowercase-ctcp", &lowercase_ctcp,
  1520. 0}, {"server-online",
  1521. (int *) &server_online, 2},
  1522. {"never-give-up", &never_give_up, 0}, {"keep-nick", &keepnick, 0},
  1523. {"strict-servernames", &strict_servernames, 0}, {"check-stoned",
  1524. &check_stoned, 0},
  1525. {"serverror-quit", &serverror_quit, 0}, {"quiet-reject", &quiet_reject, 0},
  1526. {"max-queue-msg", &maxqmsg, 0}, {"trigger-on-ignore", &trigger_on_ignore,
  1527. 0}, {"answer-ctcp", &answer_ctcp, 0},
  1528. {"server-cycle-wait", (int *) &server_cycle_wait, 0}, {"default-port",
  1529. &default_port, 0},
  1530. {"check-mode-r", &check_mode_r, 0}, {"net-type", &net_type, 0},
  1531. {"ctcp-mode", &ctcp_mode, 0}, {"double-mode", &double_mode, 0},
  1532. {"double-server", &double_server, 0}, {"double-help", &double_help, 0},
  1533. {"use-penalties", &use_penalties, 0}, {"use-fastdeq", &use_fastdeq, 0},
  1534. {"nicklen", &nick_len, 0}, {"nick-len", &nick_len, 0}, {"optimize-kicks",
  1535. &optimize_kicks, 0},
  1536. {"isjuped", &nick_juped, 0}, {"stack-limit", &stack_limit, 0}, {NULL, NULL,
  1537. 0} };
  1538. static void dcc_chat_hostresolved (int);
  1539. static int
  1540. ctcp_DCC_CHAT (char *nick, char *from, char *handle, char *object,
  1541. char *keyword, char *text)
  1542. {
  1543. char *action, *param, *ip, *prt, buf[512], *msg = buf;
  1544. int i, ok;
  1545. struct userrec *u = get_user_by_handle (userlist, handle);
  1546. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
  1547. if (!ischanhub () && !issechub ())
  1548. return 0;
  1549. strcpy (msg, text);
  1550. action = newsplit (&msg);
  1551. param = newsplit (&msg);
  1552. ip = newsplit (&msg);
  1553. prt = newsplit (&msg);
  1554. if (egg_strcasecmp (action, "CHAT") || egg_strcasecmp (object, botname)
  1555. || !u)
  1556. return 0;
  1557. get_user_flagrec (u, &fr, 0);
  1558. ok = 1;
  1559. if (issechub () && !glob_huba (fr))
  1560. ok = 0;
  1561. if (ischanhub () && !glob_chuba (fr))
  1562. ok = 0;
  1563. if (dcc_total == max_dcc)
  1564. {
  1565. if (!quiet_reject)
  1566. dprintf (DP_HELP, "NOTICE %s :%s\n", nick, DCC_TOOMANYDCCS1);
  1567. putlog (LOG_MISC, "*", DCC_TOOMANYDCCS2, "CHAT", param, nick, from);
  1568. }
  1569. else if (!ok)
  1570. {
  1571. if (!quiet_reject)
  1572. dprintf (DP_HELP, "NOTICE %s :%s\n", nick, DCC_REFUSED2);
  1573. putlog (LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED, nick, from);
  1574. }
  1575. else if (u_pass_match (u, "-"))
  1576. {
  1577. if (!quiet_reject)
  1578. dprintf (DP_HELP, "NOTICE %s :%s\n", nick, DCC_REFUSED3);
  1579. putlog (LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED4, nick, from);
  1580. }
  1581. else if (atoi (prt) < 1024 || atoi (prt) > 65535)
  1582. {
  1583. if (!quiet_reject)
  1584. dprintf (DP_HELP, "NOTICE %s :%s (invalid port)\n", nick,
  1585. DCC_CONNECTFAILED1);
  1586. putlog (LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED3, nick,
  1587. from);
  1588. }
  1589. else
  1590. {
  1591. if (!sanitycheck_dcc (nick, from, ip, prt))
  1592. return 1;
  1593. i = new_dcc (&DCC_DNSWAIT, sizeof (struct dns_info));
  1594. if (i < 0)
  1595. {
  1596. putlog (LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick,
  1597. ip);
  1598. return 1;
  1599. }
  1600. dcc[i].addr = my_atoul (ip);
  1601. dcc[i].port = atoi (prt);
  1602. dcc[i].sock = -1;
  1603. strcpy (dcc[i].nick, u->handle);
  1604. strcpy (dcc[i].host, from);
  1605. dcc[i].timeval = now;
  1606. dcc[i].user = u;
  1607. dcc[i].u.dns->ip = dcc[i].addr;
  1608. dcc[i].u.dns->dns_type = RES_HOSTBYIP;
  1609. dcc[i].u.dns->dns_success = dcc_chat_hostresolved;
  1610. dcc[i].u.dns->dns_failure = dcc_chat_hostresolved;
  1611. dcc[i].u.dns->type = &DCC_CHAT_PASS;
  1612. dcc_dnshostbyip (dcc[i].addr);
  1613. }
  1614. return 1;
  1615. }
  1616. static void
  1617. dcc_chat_hostresolved (int i)
  1618. {
  1619. char buf[512], ip[512];
  1620. int ok;
  1621. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
  1622. egg_snprintf (buf, sizeof buf, "%d", dcc[i].port);
  1623. if (!hostsanitycheck_dcc
  1624. (dcc[i].nick, dcc[i].host, dcc[i].addr, dcc[i].u.dns->host, buf))
  1625. {
  1626. lostdcc (i);
  1627. return;
  1628. }
  1629. egg_snprintf (ip, sizeof ip, "%lu", iptolong (htonl (dcc[i].addr)));
  1630. dcc[i].sock = getsock (0, getprotocol (ip));
  1631. if (dcc[i].sock < 0 || open_telnet_dcc (dcc[i].sock, ip, buf) < 0)
  1632. {
  1633. neterror (buf);
  1634. if (!quiet_reject)
  1635. dprintf (DP_HELP, "NOTICE %s :%s (%s)\n", dcc[i].nick,
  1636. DCC_CONNECTFAILED1, buf);
  1637. putlog (LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED2,
  1638. dcc[i].nick, dcc[i].host);
  1639. putlog (LOG_MISC, "*", " (%s)", buf);
  1640. killsock (dcc[i].sock);
  1641. lostdcc (i);
  1642. }
  1643. else
  1644. {
  1645. changeover_dcc (i, &DCC_CHAT_PASS, sizeof (struct chat_info));
  1646. dcc[i].status = STAT_ECHO;
  1647. get_user_flagrec (dcc[i].user, &fr, 0);
  1648. ok = 1;
  1649. if (issechub () && !glob_huba (fr))
  1650. ok = 0;
  1651. if (ischanhub () && !glob_chuba (fr))
  1652. ok = 0;
  1653. if (ok)
  1654. dcc[i].status |= STAT_PARTY;
  1655. strcpy (dcc[i].u.chat->con_chan, (chanset) ? chanset->dname : "*");
  1656. dcc[i].timeval = now;
  1657. putlog (LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick,
  1658. dcc[i].host);
  1659. dprintf (i, "%s", rand_dccresp ());
  1660. }
  1661. return;
  1662. }
  1663. static void
  1664. server_secondly ()
  1665. {
  1666. if (cycle_time)
  1667. cycle_time--;
  1668. deq_msg ();
  1669. if (!resolvserv && serv < 0)
  1670. connect_server ();
  1671. }
  1672. static void
  1673. server_5minutely ()
  1674. {
  1675. if (check_stoned && server_online)
  1676. {
  1677. if (waiting_for_awake)
  1678. {
  1679. int servidx = findanyidx (serv);
  1680. disconnect_server (servidx);
  1681. lostdcc (servidx);
  1682. putlog (LOG_SERV, "*", IRC_SERVERSTONED);
  1683. }
  1684. else if (!trying_server)
  1685. {
  1686. dprintf (DP_MODE, "PING :%lu\n", (unsigned long) now);
  1687. waiting_for_awake = 1;
  1688. }
  1689. }
  1690. } static void
  1691. server_prerehash ()
  1692. {
  1693. strcpy (oldnick, botname);
  1694. } static void
  1695. server_postrehash ()
  1696. {
  1697. strncpyz (botname, origbotname, NICKLEN);
  1698. if (oldnick[0] && !rfc_casecmp (oldnick, botname)
  1699. && !rfc_casecmp (oldnick, get_altbotnick ()))
  1700. {
  1701. strcpy (botname, oldnick);
  1702. dprintf (DP_SERVER, "NICK %s\n", origbotname);
  1703. }
  1704. else if (oldnick[0])
  1705. strcpy (botname, oldnick);
  1706. }
  1707. static void
  1708. server_die ()
  1709. {
  1710. cycle_time = 100;
  1711. if (server_online)
  1712. {
  1713. dprintf (-serv, "QUIT :%s\n", quit_msg[0] ? quit_msg : "");
  1714. sleep (3);
  1715. }
  1716. nuke_server (NULL);
  1717. }
  1718. static void
  1719. server_report (int idx, int details)
  1720. {
  1721. char s1[64], s[128];
  1722. int servidx;
  1723. if (server_online)
  1724. {
  1725. dprintf (idx, " Online as: %s%s%s (%s)\n", botname,
  1726. botuserhost[0] ? "!" : "", botuserhost[0] ? botuserhost : "",
  1727. botrealname);
  1728. if (nick_juped)
  1729. dprintf (idx, " NICK IS JUPED: %s %s\n", origbotname,
  1730. keepnick ? "(trying)" : "");
  1731. nick_juped = 0;
  1732. daysdur (now, server_online, s1);
  1733. egg_snprintf (s, sizeof s, "(connected %s)", s1);
  1734. if (server_lag && !waiting_for_awake)
  1735. {
  1736. if (server_lag == (-1))
  1737. egg_snprintf (s1, sizeof s1, " (bad pong replies)");
  1738. else
  1739. egg_snprintf (s1, sizeof s1, " (lag: %ds)", server_lag);
  1740. strcat (s, s1);
  1741. }
  1742. }
  1743. if ((trying_server || server_online)
  1744. && ((servidx = findanyidx (serv)) != (-1)))
  1745. {
  1746. dprintf (idx, " Server %s:%d %s\n", dcc[servidx].host,
  1747. dcc[servidx].port, trying_server ? "(trying)" : s);
  1748. }
  1749. else
  1750. dprintf (idx, " %s\n", IRC_NOSERVER);
  1751. if (modeq.tot)
  1752. dprintf (idx, " %s %d%%, %d msgs\n", IRC_MODEQUEUE,
  1753. (int) ((float) (modeq.tot * 100.0) / (float) maxqmsg),
  1754. (int) modeq.tot);
  1755. if (mq.tot)
  1756. dprintf (idx, " %s %d%%, %d msgs\n", IRC_SERVERQUEUE,
  1757. (int) ((float) (mq.tot * 100.0) / (float) maxqmsg),
  1758. (int) mq.tot);
  1759. if (hq.tot)
  1760. dprintf (idx, " %s %d%%, %d msgs\n", IRC_HELPQUEUE,
  1761. (int) ((float) (hq.tot * 100.0) / (float) maxqmsg),
  1762. (int) hq.tot);
  1763. if (details)
  1764. {
  1765. if (min_servs)
  1766. dprintf (idx, " Requiring a net of at least %d server(s)\n",
  1767. min_servs);
  1768. if (initserver[0])
  1769. dprintf (idx, " On connect, I do: %s\n", initserver);
  1770. if (connectserver[0])
  1771. dprintf (idx, " Before connect, I do: %s\n", connectserver);
  1772. dprintf (idx, " Flood is: %d msg/%ds, %d ctcp/%ds\n", flud_thr,
  1773. flud_time, flud_ctcp_thr, flud_ctcp_time);
  1774. }
  1775. }
  1776. static void
  1777. msgq_clear (struct msgq_head *qh)
  1778. {
  1779. register struct msgq *q, *qq;
  1780. for (q = qh->head; q; q = qq)
  1781. {
  1782. qq = q->next;
  1783. nfree (q->msg);
  1784. nfree (q);
  1785. }
  1786. qh->head = qh->last = NULL;
  1787. qh->tot = qh->warned = 0;
  1788. }
  1789. static int
  1790. msgq_expmem (struct msgq_head *qh)
  1791. {
  1792. register int tot = 0;
  1793. register struct msgq *m;
  1794. for (m = qh->head; m; m = m->next)
  1795. {
  1796. tot += m->len + 1;
  1797. tot += sizeof (struct msgq);
  1798. } return tot;
  1799. }
  1800. static int
  1801. server_expmem ()
  1802. {
  1803. int tot = 0;
  1804. struct server_list *s = serverlist;
  1805. for (; s; s = s->next)
  1806. {
  1807. if (s->name)
  1808. tot += strlen (s->name) + 1;
  1809. if (s->pass)
  1810. tot += strlen (s->pass) + 1;
  1811. if (s->realname)
  1812. tot += strlen (s->realname) + 1;
  1813. tot += sizeof (struct server_list);
  1814. } tot += msgq_expmem (&mq) + msgq_expmem (&hq) + msgq_expmem (&modeq);
  1815. return tot;
  1816. }
  1817. static cmd_t my_ctcps[] =
  1818. { {"DCC", "", ctcp_DCC_CHAT, "server:DCC"}, {NULL, NULL, NULL, NULL} };
  1819. static char *
  1820. server_close ()
  1821. {
  1822. cycle_time = 100;
  1823. nuke_server ("Connection reset by peer");
  1824. clearq (serverlist);
  1825. rem_builtins_dcc (H_dcc, C_dcc_serv);
  1826. rem_builtins (H_raw, my_raw_binds);
  1827. rem_builtins (H_ctcp, my_ctcps);
  1828. del_bind_table (H_wall);
  1829. del_bind_table (H_raw);
  1830. del_bind_table (H_notc);
  1831. del_bind_table (H_msgm);
  1832. del_bind_table (H_msg);
  1833. del_bind_table (H_flud);
  1834. del_bind_table (H_ctcr);
  1835. del_bind_table (H_ctcp);
  1836. rem_tcl_coups (my_tcl_coups);
  1837. rem_tcl_strings (my_tcl_strings);
  1838. rem_tcl_ints (my_tcl_ints);
  1839. rem_tcl_commands (my_tcl_cmds);
  1840. Tcl_UntraceVar (interp, "nick",
  1841. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1842. nick_change, NULL);
  1843. Tcl_UntraceVar (interp, "altnick", TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1844. altnick_change, NULL);
  1845. Tcl_UntraceVar (interp, "botname",
  1846. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1847. traced_botname, NULL);
  1848. Tcl_UntraceVar (interp, "server",
  1849. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1850. traced_server, NULL);
  1851. Tcl_UntraceVar (interp, "net-type",
  1852. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1853. traced_nettype, NULL);
  1854. Tcl_UntraceVar (interp, "nick-len",
  1855. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1856. traced_nicklen, NULL);
  1857. empty_msgq ();
  1858. del_hook (HOOK_SECONDLY, (Function) server_secondly);
  1859. del_hook (HOOK_5MINUTELY, (Function) server_5minutely);
  1860. del_hook (HOOK_QSERV, (Function) queue_server);
  1861. del_hook (HOOK_MINUTELY, (Function) minutely_checks);
  1862. del_hook (HOOK_PRE_REHASH, (Function) server_prerehash);
  1863. del_hook (HOOK_REHASH, (Function) server_postrehash);
  1864. del_hook (HOOK_DIE, (Function) server_die);
  1865. module_undepend (MODULE_NAME);
  1866. return NULL;
  1867. }
  1868. EXPORT_SCOPE char *server_start ();
  1869. static Function server_table[] =
  1870. { (Function) server_start, (Function) server_close,
  1871. (Function) server_expmem, (Function) server_report, (Function) NULL, (Function) botuserhost,
  1872. (Function) & quiet_reject, (Function) & serv, (Function) & flud_thr, (Function) & flud_time,
  1873. (Function) & flud_ctcp_thr, (Function) & flud_ctcp_time, (Function) match_my_nick,
  1874. (Function) check_tcl_flud, (Function) NULL, (Function) & answer_ctcp, (Function) & trigger_on_ignore,
  1875. (Function) check_tcl_ctcpr, (Function) detect_avalanche, (Function) nuke_server, (Function) newserver,
  1876. (Function) & newserverport, (Function) newserverpass, (Function) & cycle_time, (Function) & default_port,
  1877. (Function) & server_online, (Function) & min_servs, (Function) & H_raw, (Function) & H_wall,
  1878. (Function) & H_msg, (Function) & H_msgm, (Function) & H_notc, (Function) & H_flud, (Function) & H_ctcp,
  1879. (Function) & H_ctcr, (Function) ctcp_reply, (Function) get_altbotnick, (Function) & nick_len,
  1880. (Function) check_tcl_notc, (Function) & server_lag, (Function) & curserv, (Function) cursrvname,
  1881. (Function) botrealname, };
  1882. char *
  1883. server_start (Function * global_funcs)
  1884. {
  1885. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  1886. CONST char *s;
  1887. #else
  1888. char *s;
  1889. #endif
  1890. global = global_funcs;
  1891. serv = -1;
  1892. strict_host = 1;
  1893. botname[0] = 0;
  1894. trying_server = 0L;
  1895. server_lag = 0;
  1896. altnick[0] = 0;
  1897. raltnick[0] = 0;
  1898. curserv = 0;
  1899. flud_thr = 5;
  1900. flud_time = 60;
  1901. flud_ctcp_thr = 3;
  1902. flud_ctcp_time = 60;
  1903. initserver[0] = 0;
  1904. connectserver[0] = 0;
  1905. botuserhost[0] = 0;
  1906. keepnick = 1;
  1907. check_stoned = 1;
  1908. serverror_quit = 1;
  1909. quiet_reject = 1;
  1910. waiting_for_awake = 0;
  1911. server_online = 0;
  1912. server_cycle_wait = 15;
  1913. strcpy (botrealname, "A deranged product of evil coders");
  1914. min_servs = 0;
  1915. server_timeout = 15;
  1916. never_give_up = 1;
  1917. strict_servernames = 1;
  1918. serverlist = NULL;
  1919. cycle_time = 0;
  1920. default_port = 6667;
  1921. oldnick[0] = 0;
  1922. trigger_on_ignore = 0;
  1923. answer_ctcp = 1;
  1924. lowercase_ctcp = 0;
  1925. check_mode_r = 0;
  1926. maxqmsg = 300;
  1927. burst = 0;
  1928. net_type = NETT_EFNET;
  1929. double_mode = 0;
  1930. double_server = 0;
  1931. double_help = 0;
  1932. use_penalties = 0;
  1933. use_fastdeq = 0;
  1934. stackablecmds[0] = 0;
  1935. strcpy (stackable2cmds, "USERHOST ISON");
  1936. resolvserv = 0;
  1937. lastpingtime = 0;
  1938. last_time = 0;
  1939. nick_len = 9;
  1940. kick_method = 1;
  1941. optimize_kicks = 0;
  1942. stack_limit = 4;
  1943. server_table[4] = (Function) botname;
  1944. module_register (MODULE_NAME, server_table, 1, 2);
  1945. if (!(encryption_funcs = module_depend (MODULE_NAME, "encryption", 0, 0)))
  1946. {
  1947. module_undepend (MODULE_NAME);
  1948. return "This module requires an encryption modules.";
  1949. }
  1950. s = Tcl_GetVar (interp, "nick", TCL_GLOBAL_ONLY);
  1951. if (s)
  1952. strncpyz (origbotname, s, NICKLEN);
  1953. Tcl_TraceVar (interp, "nick",
  1954. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1955. nick_change, NULL);
  1956. Tcl_TraceVar (interp, "altnick", TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1957. altnick_change, NULL);
  1958. Tcl_TraceVar (interp, "botname",
  1959. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1960. traced_botname, NULL);
  1961. Tcl_TraceVar (interp, "server",
  1962. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1963. traced_server, NULL);
  1964. Tcl_TraceVar (interp, "net-type",
  1965. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1966. traced_nettype, NULL);
  1967. Tcl_TraceVar (interp, "nick-len",
  1968. TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
  1969. traced_nicklen, NULL);
  1970. H_wall = add_bind_table ("wall", HT_STACKABLE, server_2char);
  1971. H_raw = add_bind_table ("raw", HT_STACKABLE, server_raw);
  1972. H_notc = add_bind_table ("notc", HT_STACKABLE, server_6char);
  1973. H_msgm = add_bind_table ("msgm", HT_STACKABLE, server_msg);
  1974. H_msg = add_bind_table ("msg", 0, server_msg);
  1975. H_flud = add_bind_table ("flud", HT_STACKABLE, server_5char);
  1976. H_ctcr = add_bind_table ("ctcr", HT_STACKABLE, server_6char);
  1977. H_ctcp = add_bind_table ("ctcp", HT_STACKABLE, server_6char);
  1978. add_builtins (H_raw, my_raw_binds);
  1979. add_builtins_dcc (H_dcc, C_dcc_serv);
  1980. add_builtins (H_ctcp, my_ctcps);
  1981. my_tcl_strings[0].buf = botname;
  1982. add_tcl_strings (my_tcl_strings);
  1983. my_tcl_ints[0].val = &use_console_r;
  1984. add_tcl_ints (my_tcl_ints);
  1985. add_tcl_commands (my_tcl_cmds);
  1986. add_tcl_coups (my_tcl_coups);
  1987. add_hook (HOOK_SECONDLY, (Function) server_secondly);
  1988. add_hook (HOOK_10SECONDLY, (Function) server_10secondly);
  1989. add_hook (HOOK_5MINUTELY, (Function) server_5minutely);
  1990. add_hook (HOOK_MINUTELY, (Function) minutely_checks);
  1991. add_hook (HOOK_QSERV, (Function) queue_server);
  1992. add_hook (HOOK_PRE_REHASH, (Function) server_prerehash);
  1993. add_hook (HOOK_REHASH, (Function) server_postrehash);
  1994. add_hook (HOOK_DIE, (Function) server_die);
  1995. mq.head = hq.head = modeq.head = NULL;
  1996. mq.last = hq.last = modeq.last = NULL;
  1997. mq.tot = hq.tot = modeq.tot = 0;
  1998. mq.warned = hq.warned = modeq.warned = 0;
  1999. double_warned = 0;
  2000. newserver[0] = 0;
  2001. newserverport = 0;
  2002. curserv = 999;
  2003. do_nettype ();
  2004. add_cfg (&CFG_NICK);
  2005. add_cfg (&CFG_SERVERS);
  2006. add_cfg (&CFG_SERVERS6);
  2007. add_cfg (&CFG_REALNAME);
  2008. set_cfg_str (NULL, STR ("realname"), "A deranged product of evil coders");
  2009. return NULL;
  2010. }
  2011. #endif