chanprog.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /*
  2. * chanprog.c -- handles:
  3. * rmspace()
  4. * maintaining the server list
  5. * revenge punishment
  6. * timers, utimers
  7. * telling the current programmed settings
  8. * initializing a lot of stuff and loading the tcl scripts
  9. *
  10. */
  11. #include "main.h"
  12. #if HAVE_GETRUSAGE
  13. #include <sys/resource.h>
  14. #if HAVE_SYS_RUSAGE_H
  15. #include <sys/rusage.h>
  16. #endif
  17. #endif
  18. #ifdef HAVE_UNAME
  19. #include <sys/utsname.h>
  20. #endif
  21. #include "modules.h"
  22. extern struct userrec *userlist;
  23. extern Tcl_Interp *interp;
  24. extern char ver[], botnetnick[], firewall[], myip[],
  25. motdfile[], userfile[], tempdir[],
  26. notify_new[], owner[],
  27. botuser[], *owners, *hubs;
  28. extern time_t now, online_since;
  29. extern int backgrd, term_z, con_chan, cache_hit, cache_miss,
  30. firewallport, default_flags, conmask,
  31. protect_readonly, noshare,
  32. #ifdef HUB
  33. my_port,
  34. #endif /* HUB */
  35. ignore_time, loading;
  36. tcl_timer_t *timer = NULL; /* Minutely timer */
  37. tcl_timer_t *utimer = NULL; /* Secondly timer */
  38. unsigned long timer_id = 1; /* Next timer of any sort will
  39. have this number */
  40. struct chanset_t *chanset = NULL; /* Channel list */
  41. char admin[121] = ""; /* Admin info */
  42. char origbotname[NICKLEN + 1];
  43. char botname[NICKLEN + 1]; /* Primary botname */
  44. /* Remove space characters from beginning and end of string
  45. * (more efficent by Fred1)
  46. */
  47. void rmspace(char *s)
  48. {
  49. #define whitespace(c) (((c) == 32) || ((c) == 9) || ((c) == 13) || ((c) == 10))
  50. char *p;
  51. if (*s == '\0')
  52. return;
  53. /* Wipe end of string */
  54. for (p = s + strlen(s) - 1; ((whitespace(*p)) && (p >= s)); p--);
  55. if (p != s + strlen(s) - 1)
  56. *(p + 1) = 0;
  57. for (p = s; ((whitespace(*p)) && (*p)); p++);
  58. if (p != s)
  59. strcpy(s, p);
  60. }
  61. /* Returns memberfields if the nick is in the member list.
  62. */
  63. memberlist *ismember(struct chanset_t *chan, char *nick)
  64. {
  65. register memberlist *x;
  66. for (x = chan->channel.member; x && x->nick[0]; x = x->next)
  67. if (!rfc_casecmp(x->nick, nick))
  68. return x;
  69. return NULL;
  70. }
  71. /* Find a chanset by channel name as the server knows it (ie !ABCDEchannel)
  72. */
  73. struct chanset_t *findchan(const char *name)
  74. {
  75. register struct chanset_t *chan;
  76. for (chan = chanset; chan; chan = chan->next)
  77. if (!rfc_casecmp(chan->name, name))
  78. return chan;
  79. return NULL;
  80. }
  81. /* Find a chanset by display name (ie !channel)
  82. */
  83. struct chanset_t *findchan_by_dname(const char *name)
  84. {
  85. register struct chanset_t *chan;
  86. for (chan = chanset; chan; chan = chan->next)
  87. if (!rfc_casecmp(chan->dname, name))
  88. return chan;
  89. return NULL;
  90. }
  91. /*
  92. * "caching" functions
  93. */
  94. /* Shortcut for get_user_by_host -- might have user record in one
  95. * of the channel caches.
  96. */
  97. struct userrec *check_chanlist(const char *host)
  98. {
  99. char *nick, *uhost, buf[UHOSTLEN];
  100. register memberlist *m;
  101. register struct chanset_t *chan;
  102. strncpyz(buf, host, sizeof buf);
  103. uhost = buf;
  104. nick = splitnick(&uhost);
  105. for (chan = chanset; chan; chan = chan->next)
  106. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  107. if (!rfc_casecmp(nick, m->nick) && !egg_strcasecmp(uhost, m->userhost))
  108. return m->user;
  109. return NULL;
  110. }
  111. /* Shortcut for get_user_by_handle -- might have user record in channels
  112. */
  113. struct userrec *check_chanlist_hand(const char *hand)
  114. {
  115. register struct chanset_t *chan;
  116. register memberlist *m;
  117. for (chan = chanset; chan; chan = chan->next)
  118. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  119. if (m->user && !egg_strcasecmp(m->user->handle, hand))
  120. return m->user;
  121. return NULL;
  122. }
  123. /* Clear the user pointers in the chanlists.
  124. *
  125. * Necessary when a hostmask is added/removed, a user is added or a new
  126. * userfile is loaded.
  127. */
  128. void clear_chanlist(void)
  129. {
  130. register memberlist *m;
  131. register struct chanset_t *chan;
  132. for (chan = chanset; chan; chan = chan->next)
  133. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  134. m->user = NULL;
  135. m->tried_getuser = 0;
  136. }
  137. }
  138. /* Clear the user pointer of a specific nick in the chanlists.
  139. *
  140. * Necessary when a hostmask is added/removed, a nick changes, etc.
  141. * Does not completely invalidate the channel cache like clear_chanlist().
  142. */
  143. void clear_chanlist_member(const char *nick)
  144. {
  145. register memberlist *m;
  146. register struct chanset_t *chan;
  147. for (chan = chanset; chan; chan = chan->next)
  148. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  149. if (!rfc_casecmp(m->nick, nick)) {
  150. m->user = NULL;
  151. m->tried_getuser = 0;
  152. break;
  153. }
  154. }
  155. /* If this user@host is in a channel, set it (it was null)
  156. */
  157. void set_chanlist(const char *host, struct userrec *rec)
  158. {
  159. char *nick, *uhost, buf[UHOSTLEN];
  160. register memberlist *m;
  161. register struct chanset_t *chan;
  162. strncpyz(buf, host, sizeof buf);
  163. uhost = buf;
  164. nick = splitnick(&uhost);
  165. for (chan = chanset; chan; chan = chan->next)
  166. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  167. if (!rfc_casecmp(nick, m->nick) && !egg_strcasecmp(uhost, m->userhost))
  168. m->user = rec;
  169. }
  170. /* Calculate the memory we should be using
  171. */
  172. int expmem_chanprog()
  173. {
  174. register int tot = 0;
  175. register tcl_timer_t *t;
  176. for (t = timer; t; t = t->next)
  177. tot += sizeof(tcl_timer_t) + strlen(t->cmd) + 1;
  178. for (t = utimer; t; t = t->next)
  179. tot += sizeof(tcl_timer_t) + strlen(t->cmd) + 1;
  180. return tot;
  181. }
  182. /* 0 marks all channels
  183. * 1 removes marked channels
  184. * 2 unmarks all channels
  185. */
  186. void checkchans(int which)
  187. {
  188. struct chanset_t *chan, *chan_next;
  189. sdprintf(STR("checkchans(%d)"), which);
  190. if (which == 0 || which == 2) {
  191. for (chan = chanset; chan; chan = chan->next) {
  192. if (which == 0) {
  193. chan->status |= CHAN_FLAGGED;
  194. } else if (which == 2) {
  195. chan->status &= ~CHAN_FLAGGED;
  196. }
  197. }
  198. } else if (which == 1) {
  199. module_entry *me;
  200. for (chan = chanset; chan; chan = chan_next) {
  201. chan_next = chan->next;
  202. if (chan->status & CHAN_FLAGGED) {
  203. putlog(LOG_MISC, "*", "No longer supporting channel %s", chan->dname);
  204. /* remove_channel(chan); */
  205. if ((me = module_find("channels", 0, 0))) {
  206. Function *func = me->funcs;
  207. (func[CHANNEL_REMOVE]) (chan);
  208. }
  209. }
  210. }
  211. }
  212. }
  213. /* Dump uptime info out to dcc (guppy 9Jan99)
  214. */
  215. void tell_verbose_uptime(int idx)
  216. {
  217. char s[256], s1[121];
  218. time_t now2, hr, min;
  219. now2 = now - online_since;
  220. s[0] = 0;
  221. if (now2 > 86400) {
  222. /* days */
  223. sprintf(s, "%d day", (int) (now2 / 86400));
  224. if ((int) (now2 / 86400) >= 2)
  225. strcat(s, "s");
  226. strcat(s, ", ");
  227. now2 -= (((int) (now2 / 86400)) * 86400);
  228. }
  229. hr = (time_t) ((int) now2 / 3600);
  230. now2 -= (hr * 3600);
  231. min = (time_t) ((int) now2 / 60);
  232. sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
  233. s1[0] = 0;
  234. if (backgrd)
  235. strcpy(s1, MISC_BACKGROUND);
  236. else {
  237. if (term_z)
  238. strcpy(s1, MISC_TERMMODE);
  239. else if (con_chan)
  240. strcpy(s1, MISC_STATMODE);
  241. else
  242. strcpy(s1, MISC_LOGMODE);
  243. }
  244. dprintf(idx, "%s %s (%s)\n", MISC_ONLINEFOR, s, s1);
  245. }
  246. /* Dump status info out to dcc
  247. */
  248. void tell_verbose_status(int idx)
  249. {
  250. char s[256], s1[121], s2[81];
  251. char *vers_t, *uni_t;
  252. #ifdef HUB
  253. int i;
  254. #endif /* HUB */
  255. time_t now2, hr, min;
  256. #if HAVE_GETRUSAGE
  257. struct rusage ru;
  258. #else
  259. # if HAVE_CLOCK
  260. clock_t cl;
  261. # endif
  262. #endif /* HAVE_GETRUSAGE */
  263. #ifdef HAVE_UNAME
  264. struct utsname un;
  265. if (!uname(&un) < 0) {
  266. #endif /* HAVE_UNAME */
  267. vers_t = " ";
  268. uni_t = "*unknown*";
  269. #ifdef HAVE_UNAME
  270. } else {
  271. vers_t = un.release;
  272. uni_t = un.sysname;
  273. }
  274. #endif /* HAVE_UNAME */
  275. #ifdef HUB
  276. i = count_users(userlist);
  277. dprintf(idx, "I am %s, running %s: %d user%s (mem: %uk)\n",
  278. botnetnick, ver, i, i == 1 ? "" : "s",
  279. (int) (expected_memory() / 1024));
  280. #endif /* HUB */
  281. now2 = now - online_since;
  282. s[0] = 0;
  283. if (now2 > 86400) {
  284. /* days */
  285. sprintf(s, "%d day", (int) (now2 / 86400));
  286. if ((int) (now2 / 86400) >= 2)
  287. strcat(s, "s");
  288. strcat(s, ", ");
  289. now2 -= (((int) (now2 / 86400)) * 86400);
  290. }
  291. hr = (time_t) ((int) now2 / 3600);
  292. now2 -= (hr * 3600);
  293. min = (time_t) ((int) now2 / 60);
  294. sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
  295. s1[0] = 0;
  296. if (backgrd)
  297. strcpy(s1, MISC_BACKGROUND);
  298. else {
  299. if (term_z)
  300. strcpy(s1, MISC_TERMMODE);
  301. else if (con_chan)
  302. strcpy(s1, MISC_STATMODE);
  303. else
  304. strcpy(s1, MISC_LOGMODE);
  305. }
  306. #if HAVE_GETRUSAGE
  307. getrusage(RUSAGE_SELF, &ru);
  308. hr = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) / 60);
  309. min = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) - (hr * 60));
  310. sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min); /* Actally min/sec */
  311. #else
  312. # if HAVE_CLOCK
  313. cl = (clock() / CLOCKS_PER_SEC);
  314. hr = (int) (cl / 60);
  315. min = (int) (cl - (hr * 60));
  316. sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min); /* Actually min/sec */
  317. # else
  318. sprintf(s2, "CPU ???");
  319. # endif
  320. #endif /* HAVE_GETRUSAGE */
  321. dprintf(idx, "%s %s (%s) %s %s %4.1f%%\n", MISC_ONLINEFOR,
  322. s, s1, s2, MISC_CACHEHIT,
  323. 100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
  324. if (admin[0])
  325. dprintf(idx, "Admin: %s\n", admin);
  326. dprintf(idx, "OS: %s %s\n", uni_t, vers_t);
  327. /* info library */
  328. dprintf(idx, "%s %s\n", MISC_TCLLIBRARY,
  329. ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
  330. interp->result : "*unknown*");
  331. /* info tclversion/patchlevel */
  332. dprintf(idx, "%s %s (%s %s)\n", MISC_TCLVERSION,
  333. ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
  334. interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
  335. interp->result : "*unknown*", MISC_TCLHVERSION,
  336. TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL : "*unknown*");
  337. #if HAVE_TCL_THREADS
  338. dprintf(idx, "Tcl is threaded\n");
  339. #endif /* HAVE_TCL_THREADS */
  340. }
  341. /* Show all internal state variables
  342. */
  343. void tell_settings(int idx)
  344. {
  345. char s[1024];
  346. struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
  347. dprintf(idx, "Botnet Nickname: %s\n", botnetnick);
  348. if (firewall[0])
  349. dprintf(idx, "Firewall: %s, port %d\n", firewall, firewallport);
  350. #ifdef HUB
  351. dprintf(idx, "Userfile: %s \n", userfile);
  352. #endif /* HUB */
  353. dprintf(idx, "Directories:\n");
  354. dprintf(idx, " Temp : %s\n", tempdir);
  355. fr.global = default_flags;
  356. build_flags(s, &fr, NULL);
  357. dprintf(idx, "%s [%s], %s: %s\n", MISC_NEWUSERFLAGS, s, MISC_NOTIFY, notify_new);
  358. #ifdef HUB
  359. if (owner[0])
  360. dprintf(idx, "%s: %s\n", MISC_PERMOWNER, owner);
  361. #endif /* HUB */
  362. dprintf(idx, "Ignores last %d mins\n", ignore_time);
  363. }
  364. void reaffirm_owners()
  365. {
  366. char *p, *q, s[121];
  367. struct userrec *u;
  368. /* Make sure default owners are +a */
  369. if (owner[0]) {
  370. q = owner;
  371. p = strchr(q, ',');
  372. while (p) {
  373. strncpyz(s, q, (p - q) + 1);
  374. rmspace(s);
  375. u = get_user_by_handle(userlist, s);
  376. if (u)
  377. u->flags = sanity_check(u->flags | USER_ADMIN);
  378. q = p + 1;
  379. p = strchr(q, ',');
  380. }
  381. strcpy(s, q);
  382. rmspace(s);
  383. u = get_user_by_handle(userlist, s);
  384. if (u)
  385. u->flags = sanity_check(u->flags | USER_ADMIN);
  386. }
  387. }
  388. void load_internal_users()
  389. {
  390. char *p = NULL,
  391. *ln,
  392. *hand,
  393. *ip,
  394. *port,
  395. *pass,
  396. *hosts,
  397. host[250],
  398. buf[2048];
  399. char *attr;
  400. int i, hublevel = 0;
  401. struct bot_addr *bi;
  402. struct userrec *u;
  403. //struct flag_record fr = {FR_BOT, 0, 0, 0, 0, 0};
  404. /* hubs */
  405. sprintf(buf, "%s", hubs);
  406. p = buf;
  407. while (p) {
  408. ln = p;
  409. p = strchr(p, ',');
  410. if (p)
  411. *p++ = 0;
  412. hand = ln;
  413. ip = NULL;
  414. port = NULL;
  415. hosts = NULL;
  416. for (i = 0; ln; i++) {
  417. switch (i) {
  418. case 0:
  419. hand = ln;
  420. break;
  421. case 1:
  422. ip = ln;
  423. break;
  424. case 2:
  425. port = ln;
  426. break;
  427. case 3:
  428. hublevel++; /* We must increment this even if it is already added */
  429. if (!get_user_by_handle(userlist, hand)) {
  430. userlist = adduser(userlist, hand, "none", "-", USER_BOT | USER_OP);
  431. bi = user_malloc(sizeof(struct bot_addr));
  432. bi->address = user_malloc(strlen(ip) + 1);
  433. strcpy(bi->address, ip);
  434. bi->telnet_port = atoi(port) ? atoi(port) : 0;
  435. bi->relay_port = bi->telnet_port;
  436. bi->hublevel = hublevel;
  437. #ifdef HUB
  438. if ((!bi->hublevel) && (!strcmp(hand, botnetnick)))
  439. bi->hublevel = 99;
  440. #endif /* HUB */
  441. bi->uplink = user_malloc(1);
  442. bi->uplink[0] = 0;
  443. set_user(&USERENTRY_BOTADDR, get_user_by_handle(userlist, hand), bi);
  444. /* set_user(&USERENTRY_PASS, get_user_by_handle(userlist, hand), SALT2); */
  445. }
  446. default:
  447. // ln = userids for hostlist, add them all
  448. hosts = ln;
  449. ln = strchr(ln, ' ');
  450. if (ln)
  451. *ln++ = 0;
  452. while (hosts) {
  453. sprintf(host, "*!%s@%s", hosts, ip);
  454. set_user(&USERENTRY_HOSTS, get_user_by_handle(userlist, hand), host);
  455. hosts = ln;
  456. if (ln)
  457. ln = strchr(ln, ' ');
  458. if (ln)
  459. *ln++ = 0;
  460. }
  461. break;
  462. }
  463. if (ln)
  464. ln = strchr(ln, ' ');
  465. if (ln) {
  466. *ln++ = 0;
  467. }
  468. }
  469. }
  470. /* perm owners */
  471. owner[0] = 0;
  472. sprintf(buf, "%s", owners);
  473. p = buf;
  474. while (p) {
  475. ln = p;
  476. p = strchr(p, ',');
  477. if (p)
  478. *p++ = 0;
  479. hand = ln;
  480. pass = NULL;
  481. attr = NULL;
  482. hosts = NULL;
  483. for (i = 0; ln; i++) {
  484. switch (i) {
  485. case 0:
  486. hand = ln;
  487. break;
  488. case 1:
  489. pass = ln;
  490. break;
  491. case 2:
  492. hosts = ln;
  493. if (owner[0])
  494. strncat(owner, ",", 120);
  495. strncat(owner, hand, 120);
  496. if (!get_user_by_handle(userlist, hand)) {
  497. userlist = adduser(userlist, hand, "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_OP | USER_PARTY | USER_HUBA | USER_CHUBA);
  498. u = get_user_by_handle(userlist, hand);
  499. set_user(&USERENTRY_PASS, u, pass);
  500. while (hosts) {
  501. ln = strchr(ln, ' ');
  502. if (ln)
  503. *ln++ = 0;
  504. set_user(&USERENTRY_HOSTS, u, hosts);
  505. hosts = ln;
  506. }
  507. }
  508. break;
  509. }
  510. if (ln)
  511. ln = strchr(ln, ' ');
  512. if (ln)
  513. *ln++ = 0;
  514. }
  515. }
  516. }
  517. void chanprog()
  518. {
  519. char buf[2048];
  520. struct bot_addr *bi;
  521. struct userrec *u;
  522. admin[0] = 0;
  523. /* cache our ip on load instead of every 30 seconds -zip */
  524. cache_my_ip();
  525. sdprintf("ip4: %s", myipstr(4));
  526. sdprintf("ip6: %s", myipstr(6));
  527. conmask = 0;
  528. /* Turn off read-only variables (make them write-able) for rehash */
  529. protect_readonly = 0;
  530. /* now this only checks server shit. (no channels) */
  531. call_hook(HOOK_REHASH);
  532. protect_readonly = 1;
  533. if (!botnetnick[0]) {
  534. strncpyz(botnetnick, origbotname, HANDLEN + 1);
  535. }
  536. strcpy(botuser, origbotname);
  537. if (!botnetnick[0])
  538. fatal("I don't have a botnet nick!!\n", 0);
  539. #ifdef HUB
  540. loading = 1;
  541. checkchans(0);
  542. readuserfile(userfile, &userlist);
  543. checkchans(1);
  544. loading = 0;
  545. #endif /* HUB */
  546. load_internal_users();
  547. if (!(u = get_user_by_handle(userlist, botnetnick))) {
  548. /* I need to be on the userlist... doh. */
  549. userlist = adduser(userlist, botnetnick, STR("none"), "-", USER_BOT | USER_OP );
  550. u = get_user_by_handle(userlist, botnetnick);
  551. bi = user_malloc(sizeof(struct bot_addr));
  552. bi->address = user_malloc(strlen(myip) + 1);
  553. strcpy(bi->address, myip);
  554. bi->telnet_port = atoi(buf) ? atoi(buf) : 3333;
  555. bi->relay_port = bi->telnet_port;
  556. #ifdef HUB
  557. bi->hublevel = 99;
  558. #else
  559. bi->hublevel = 0;
  560. #endif /* HUB */
  561. bi->uplink = user_malloc(1);
  562. bi->uplink[0] = 0;
  563. set_user(&USERENTRY_BOTADDR, u, bi);
  564. } else {
  565. bi = get_user(&USERENTRY_BOTADDR, u);
  566. }
  567. bi = get_user(&USERENTRY_BOTADDR, get_user_by_handle(userlist, botnetnick));
  568. if (!bi)
  569. fatal(STR("I'm added to userlist but without a bot record!"), 0);
  570. if (bi->telnet_port != 3333) {
  571. #ifdef HUB
  572. listen_all(bi->telnet_port, 0);
  573. my_port = bi->telnet_port;
  574. #endif /* HUB */
  575. }
  576. trigger_cfg_changed();
  577. /* We should be safe now */
  578. if (tempdir[0])
  579. if (tempdir[strlen(tempdir) - 1] != '/')
  580. strcat(tempdir, "/");
  581. /* test tempdir: it's vital */
  582. {
  583. FILE *f;
  584. char s[161];
  585. int fd;
  586. /* possible file race condition solved by using a random string
  587. * and the process id in the filename */
  588. /* Let's not even dare to hope... use mkstemp() -dizz */
  589. sprintf(s, STR("%s.test-XXXXXX"), tempdir);
  590. if ((fd = mkstemp(s)) == -1 || (f = fdopen(fd, "w")) == NULL) {
  591. if (fd != -1) {
  592. unlink(s);
  593. close(fd);
  594. }
  595. fatal(STR("Can't write to tempdir!"), 0);
  596. }
  597. unlink(s);
  598. }
  599. reaffirm_owners();
  600. }
  601. #ifdef HUB
  602. /* Reload the user file from disk
  603. */
  604. void reload()
  605. {
  606. FILE *f;
  607. f = fopen(userfile, "r");
  608. if (f == NULL) {
  609. putlog(LOG_MISC, "*", MISC_CANTRELOADUSER);
  610. return;
  611. }
  612. fclose(f);
  613. noshare = 1;
  614. clear_userlist(userlist);
  615. noshare = 0;
  616. userlist = NULL;
  617. loading = 1;
  618. checkchans(0);
  619. if (!readuserfile(userfile, &userlist))
  620. fatal(MISC_MISSINGUSERF, 0);
  621. checkchans(1);
  622. loading = 0;
  623. reaffirm_owners();
  624. call_hook(HOOK_READ_USERFILE);
  625. }
  626. #endif /* HUB */
  627. void rehash()
  628. {
  629. call_hook(HOOK_PRE_REHASH);
  630. noshare = 1;
  631. clear_userlist(userlist);
  632. noshare = 0;
  633. userlist = NULL;
  634. chanprog();
  635. }
  636. /*
  637. * Brief venture into timers
  638. */
  639. /* Add a timer
  640. */
  641. unsigned long add_timer(tcl_timer_t **stack, int elapse, char *cmd,
  642. unsigned long prev_id)
  643. {
  644. tcl_timer_t *old = (*stack);
  645. *stack = (tcl_timer_t *) nmalloc(sizeof(tcl_timer_t));
  646. (*stack)->next = old;
  647. (*stack)->mins = elapse;
  648. (*stack)->cmd = (char *) nmalloc(strlen(cmd) + 1);
  649. strcpy((*stack)->cmd, cmd);
  650. /* If it's just being added back and already had an id,
  651. * don't create a new one.
  652. */
  653. if (prev_id > 0)
  654. (*stack)->id = prev_id;
  655. else
  656. (*stack)->id = timer_id++;
  657. return (*stack)->id;
  658. }
  659. /* Remove a timer, by id
  660. */
  661. int remove_timer(tcl_timer_t **stack, unsigned long id)
  662. {
  663. tcl_timer_t *old;
  664. int ok = 0;
  665. while (*stack) {
  666. if ((*stack)->id == id) {
  667. ok++;
  668. old = *stack;
  669. *stack = ((*stack)->next);
  670. nfree(old->cmd);
  671. nfree(old);
  672. } else
  673. stack = &((*stack)->next);
  674. }
  675. return ok;
  676. }
  677. /* Check timers, execute the ones that have expired.
  678. */
  679. void do_check_timers(tcl_timer_t **stack)
  680. {
  681. tcl_timer_t *mark = *stack, *old = NULL;
  682. char x[16];
  683. /* New timers could be added by a Tcl script inside a current timer
  684. * so i'll just clear out the timer list completely, and add any
  685. * unexpired timers back on.
  686. */
  687. *stack = NULL;
  688. while (mark) {
  689. if (mark->mins > 0)
  690. mark->mins--;
  691. old = mark;
  692. mark = mark->next;
  693. if (!old->mins) {
  694. egg_snprintf(x, sizeof x, "timer%lu", old->id);
  695. do_tcl(x, old->cmd);
  696. nfree(old->cmd);
  697. nfree(old);
  698. } else {
  699. old->next = *stack;
  700. *stack = old;
  701. }
  702. }
  703. }
  704. /* Wipe all timers.
  705. */
  706. void wipe_timers(Tcl_Interp *irp, tcl_timer_t **stack)
  707. {
  708. tcl_timer_t *mark = *stack, *old;
  709. while (mark) {
  710. old = mark;
  711. mark = mark->next;
  712. nfree(old->cmd);
  713. nfree(old);
  714. }
  715. *stack = NULL;
  716. }
  717. /* Return list of timers
  718. */
  719. void list_timers(Tcl_Interp *irp, tcl_timer_t *stack)
  720. {
  721. tcl_timer_t *mark;
  722. char mins[10], id[16], *x;
  723. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  724. CONST char *argv[3];
  725. #else
  726. char *argv[3];
  727. #endif
  728. for (mark = stack; mark; mark = mark->next) {
  729. egg_snprintf(mins, sizeof mins, "%u", mark->mins);
  730. egg_snprintf(id, sizeof id, "timer%lu", mark->id);
  731. argv[0] = mins;
  732. argv[1] = mark->cmd;
  733. argv[2] = id;
  734. x = Tcl_Merge(3, argv);
  735. Tcl_AppendElement(irp, x);
  736. Tcl_Free((char *) x);
  737. }
  738. }
  739. /* Oddly enough, written by proton (Emech's coder)
  740. */
  741. int isowner(char *name)
  742. {
  743. char *pa, *pb;
  744. char nl, pl;
  745. if (!owner || !*owner)
  746. return (0);
  747. if (!name || !*name)
  748. return (0);
  749. nl = strlen(name);
  750. pa = owner;
  751. pb = owner;
  752. while (1) {
  753. while (1) {
  754. if ((*pb == 0) || (*pb == ',') || (*pb == ' '))
  755. break;
  756. pb++;
  757. }
  758. pl = (unsigned int) pb - (unsigned int) pa;
  759. if (pl == nl && !egg_strncasecmp(pa, name, nl))
  760. return (1);
  761. while (1) {
  762. if ((*pb == 0) || ((*pb != ',') && (*pb != ' ')))
  763. break;
  764. pb++;
  765. }
  766. if (*pb == 0)
  767. return (0);
  768. pa = pb;
  769. }
  770. }
  771. int shouldjoin(struct chanset_t *chan)
  772. {
  773. if (!strcmp(chan->dname, "#wraith"))
  774. return 1;
  775. else
  776. return 0;
  777. #ifdef G_BACKUP
  778. struct flag_record fr = { FR_CHAN | FR_ANYWH | FR_GLOBAL, 0, 0, 0, 0 };
  779. get_user_flagrec(get_user_by_handle(userlist, botnetnick), &fr, chan->name);
  780. return (!channel_inactive(chan)
  781. && (channel_backup(chan) || !glob_backupbot(fr)));
  782. #else /* !G_BACKUP */
  783. return !channel_inactive(chan);
  784. #endif /* G_BACKUP */
  785. }
  786. /* do_chanset() set (options) on (chan)
  787. * local: 0 - send out over botnet only
  788. * local: 1 - ALSO set locally
  789. * local: 2 - ONLY set locally
  790. */
  791. void do_chanset(struct chanset_t *chan, char *options, int local)
  792. {
  793. char *buf;
  794. module_entry *me;
  795. Context;
  796. /* send out over botnet. */
  797. if (local != 2) {
  798. /* nmalloc(options,chan,'cset ',' ',+ 1) */
  799. if (chan)
  800. buf = nmalloc(strlen(options) + strlen(chan->dname) + 5 + 1 + 1);
  801. else
  802. buf = nmalloc(strlen(options) + 1 + 5 + 1 + 1);
  803. buf[0] = 0;
  804. strcat(buf, "cset ");
  805. if (chan)
  806. strcat(buf, chan->dname);
  807. else
  808. strcat(buf, "*");
  809. strcat(buf, " ");
  810. strcat(buf, options);
  811. buf[strlen(buf)] = 0;
  812. putlog(LOG_DEBUG, "*", "sending out cset: %s", buf);
  813. putallbots(buf);
  814. nfree(buf);
  815. }
  816. /* now set locally, hopefully it works */
  817. if (local && (me = module_find("channels", 0, 0))) {
  818. /* tcl_channel_modify(0, chan, 1, options) */
  819. Function *func = me->funcs;
  820. char *buf2, *bak;
  821. struct chanset_t *ch;
  822. int all = 0;
  823. if (!chan) {
  824. ch = chanset;
  825. all++;
  826. } else
  827. ch = chan;
  828. bak = options;
  829. buf2 = nmalloc(strlen(options) + 1);
  830. while (ch) {
  831. char *list[2];
  832. strcpy(buf2, bak);
  833. options = buf2;
  834. list[0] = newsplit(&options);
  835. while (list[0][0]) {
  836. if (list[0][0] == '+' || list[0][0] == '-' || (!strcmp(list[0], "dont-idle-kick"))) {
  837. (func[38]) (0, ch, 1, list); /* tcl_channel_modify() */
  838. list[0] = newsplit(&options);
  839. continue;
  840. }
  841. /* chanints */
  842. list[1] = options;
  843. (func[38]) (0, ch, 2, list); /* tcl_channel_modify() */
  844. break;
  845. }
  846. if (all)
  847. ch = ch->next;
  848. else
  849. ch = NULL;
  850. }
  851. nfree(buf2);
  852. }
  853. }