chanprog.c 22 KB

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