00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "main.h"
00035
00036 #include <fcntl.h>
00037 #include <errno.h>
00038 #include <signal.h>
00039 #include <netdb.h>
00040 #include <setjmp.h>
00041
00042 #ifdef TIME_WITH_SYS_TIME
00043 # include <sys/time.h>
00044 # include <time.h>
00045 #else
00046 # ifdef HAVE_SYS_TIME_H
00047 # include <sys/time.h>
00048 # else
00049 # include <time.h>
00050 # endif
00051 #endif
00052
00053 #ifdef STOP_UAC
00054 # include <sys/sysinfo.h>
00055 # define UAC_NOPRINT 0x00000001
00056 #endif
00057
00058 #include "chan.h"
00059 #include "modules.h"
00060 #include "tandem.h"
00061 #include "bg.h"
00062
00063 #ifdef DEBUG
00064 # include <sys/resource.h>
00065 #endif
00066
00067 #ifdef CYGWIN_HACKS
00068 # include <windows.h>
00069 #endif
00070
00071 #ifndef _POSIX_SOURCE
00072 # define _POSIX_SOURCE 1
00073 #endif
00074
00075 extern char origbotname[], userfile[], botnetnick[];
00076 extern int dcc_total, conmask, cache_hit, cache_miss, max_logs, quick_logs,
00077 quiet_save;
00078 extern struct dcc_t *dcc;
00079 extern struct userrec *userlist;
00080 extern struct chanset_t *chanset;
00081 extern log_t *logs;
00082 extern Tcl_Interp *interp;
00083 extern tcl_timer_t *timer, *utimer;
00084 #ifdef REPLACE_NOTIFIER
00085 extern tclevent_t *tclevents;
00086 #endif
00087 extern sigjmp_buf alarmret;
00088 time_t now;
00089 static int argc;
00090 static char **argv;
00091
00092
00093
00094
00095
00096
00097
00098
00099 char egg_version[1024] = "1.6.21";
00100 int egg_numver = 1062100;
00101
00102 char notify_new[121] = "";
00103 int default_flags = 0;
00104 int default_uflags = 0;
00105
00106 int backgrd = 1;
00107 int con_chan = 0;
00108 int term_z = 0;
00109 int use_stderr = 1;
00110
00111 char configfile[121] = "eggdrop.conf";
00112 char pid_file[120];
00113 char helpdir[121] = "help/";
00114 char textdir[121] = "text/";
00115
00116 int keep_all_logs = 0;
00117 char logfile_suffix[21] = ".%d%b%Y";
00118 int switch_logfiles_at = 300;
00119
00120 time_t online_since;
00121
00122 int make_userfile = 0;
00123 char owner[121] = "";
00124
00125 int save_users_at = 0;
00126 int notify_users_at = 0;
00127
00128 char version[81];
00129 char ver[41];
00130 char egg_xtra[2048];
00131
00132 int do_restart = 0;
00133 int die_on_sighup = 0;
00134 int die_on_sigterm = 1;
00135 int resolve_timeout = 15;
00136 char quit_msg[1024];
00137
00138
00139 unsigned long otraffic_irc = 0;
00140 unsigned long otraffic_irc_today = 0;
00141 unsigned long otraffic_bn = 0;
00142 unsigned long otraffic_bn_today = 0;
00143 unsigned long otraffic_dcc = 0;
00144 unsigned long otraffic_dcc_today = 0;
00145 unsigned long otraffic_filesys = 0;
00146 unsigned long otraffic_filesys_today = 0;
00147 unsigned long otraffic_trans = 0;
00148 unsigned long otraffic_trans_today = 0;
00149 unsigned long otraffic_unknown = 0;
00150 unsigned long otraffic_unknown_today = 0;
00151 unsigned long itraffic_irc = 0;
00152 unsigned long itraffic_irc_today = 0;
00153 unsigned long itraffic_bn = 0;
00154 unsigned long itraffic_bn_today = 0;
00155 unsigned long itraffic_dcc = 0;
00156 unsigned long itraffic_dcc_today = 0;
00157 unsigned long itraffic_trans = 0;
00158 unsigned long itraffic_trans_today = 0;
00159 unsigned long itraffic_unknown = 0;
00160 unsigned long itraffic_unknown_today = 0;
00161
00162 #ifdef DEBUG_CONTEXT
00163
00164 char cx_file[16][30];
00165 char cx_note[16][256];
00166 int cx_line[16];
00167 int cx_ptr = 0;
00168 #endif
00169
00170
00171 void fatal(const char *s, int recoverable)
00172 {
00173 int i;
00174
00175 putlog(LOG_MISC, "*", "* %s", s);
00176 flushlogs();
00177 for (i = 0; i < dcc_total; i++)
00178 if (dcc[i].sock >= 0)
00179 killsock(dcc[i].sock);
00180 unlink(pid_file);
00181 if (!recoverable) {
00182 bg_send_quit(BG_ABORT);
00183 exit(1);
00184 }
00185 }
00186
00187 int expmem_chanprog();
00188 int expmem_users();
00189 int expmem_misc();
00190 int expmem_dccutil();
00191 int expmem_botnet();
00192 int expmem_tcl();
00193 int expmem_tclhash();
00194 int expmem_net();
00195 int expmem_modules(int);
00196 int expmem_language();
00197 int expmem_tcldcc();
00198 int expmem_tclmisc();
00199
00200
00201
00202 int expected_memory(void)
00203 {
00204 int tot;
00205
00206 tot = expmem_chanprog() + expmem_users() + expmem_misc() + expmem_dccutil() +
00207 expmem_botnet() + expmem_tcl() + expmem_tclhash() + expmem_net() +
00208 expmem_modules(0) + expmem_language() + expmem_tcldcc() +
00209 expmem_tclmisc();
00210 return tot;
00211 }
00212
00213 static void check_expired_dcc()
00214 {
00215 int i;
00216
00217 for (i = 0; i < dcc_total; i++)
00218 if (dcc[i].type && dcc[i].type->timeout_val &&
00219 ((now - dcc[i].timeval) > *(dcc[i].type->timeout_val))) {
00220 if (dcc[i].type->timeout)
00221 dcc[i].type->timeout(i);
00222 else if (dcc[i].type->eof)
00223 dcc[i].type->eof(i);
00224 else
00225 continue;
00226
00227 return;
00228 }
00229 }
00230
00231 #ifndef DEBUG_CONTEXT
00232 #define write_debug() do {} while (0)
00233 #else
00234 static int nested_debug = 0;
00235
00236 static void write_debug()
00237 {
00238 int x;
00239 char s[25];
00240 int y;
00241
00242 if (nested_debug) {
00243
00244
00245
00246
00247
00248
00249 x = creat("DEBUG.DEBUG", 0644);
00250 setsock(x, SOCK_NONSOCK);
00251 if (x >= 0) {
00252 strncpyz(s, ctime(&now), sizeof s);
00253 dprintf(-x, "Debug (%s) written %s\n", ver, s);
00254 dprintf(-x, "Please report problem to bugs@eggheads.org\n");
00255 dprintf(-x, "after a visit to http://www.eggheads.org/bugzilla/\n");
00256 dprintf(-x, "Full Patch List: %s\n", egg_xtra);
00257 dprintf(-x, "Context: ");
00258 cx_ptr = cx_ptr & 15;
00259 for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
00260 dprintf(-x, "%s/%d,\n ", cx_file[y], cx_line[y]);
00261 dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
00262 killsock(x);
00263 close(x);
00264 }
00265 bg_send_quit(BG_ABORT);
00266 exit(1);
00267
00268 } else
00269 nested_debug = 1;
00270 putlog(LOG_MISC, "*", "* Last context: %s/%d [%s]", cx_file[cx_ptr],
00271 cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
00272 putlog(LOG_MISC, "*", "* Please REPORT this BUG!");
00273 putlog(LOG_MISC, "*", "* Check doc/BUG-REPORT on how to do so.");
00274 x = creat("DEBUG", 0644);
00275 setsock(x, SOCK_NONSOCK);
00276 if (x < 0) {
00277 putlog(LOG_MISC, "*", "* Failed to write DEBUG");
00278 } else {
00279 strncpyz(s, ctime(&now), sizeof s);
00280 dprintf(-x, "Debug (%s) written %s\n", ver, s);
00281 dprintf(-x, "Full Patch List: %s\n", egg_xtra);
00282 #ifdef STATIC
00283 dprintf(-x, "STATICALLY LINKED\n");
00284 #endif
00285
00286
00287 dprintf(-x, "Tcl library: %s\n",
00288 ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
00289 tcl_resultstring() : "*unknown*");
00290
00291
00292 dprintf(-x, "Tcl version: %s (header version %s)\n",
00293 ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
00294 tcl_resultstring() : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
00295 tcl_resultstring() : "*unknown*", TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL :
00296 "*unknown*");
00297
00298 if (tcl_threaded())
00299 dprintf(-x, "Tcl is threaded\n");
00300
00301 dprintf(-x, "Configure flags: %s\n", EGG_AC_ARGS);
00302
00303 #ifdef CCFLAGS
00304 dprintf(-x, "Compile flags: %s\n", CCFLAGS);
00305 #endif
00306
00307 #ifdef LDFLAGS
00308 dprintf(-x, "Link flags: %s\n", LDFLAGS);
00309 #endif
00310
00311 #ifdef STRIPFLAGS
00312 dprintf(-x, "Strip flags: %s\n", STRIPFLAGS);
00313 #endif
00314
00315 dprintf(-x, "Context: ");
00316 cx_ptr = cx_ptr & 15;
00317 for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
00318 dprintf(-x, "%s/%d, [%s]\n ", cx_file[y], cx_line[y],
00319 (cx_note[y][0]) ? cx_note[y] : "");
00320 dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
00321 (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
00322 tell_dcc(-x);
00323 dprintf(-x, "\n");
00324 debug_mem_to_dcc(-x);
00325 killsock(x);
00326 close(x);
00327 putlog(LOG_MISC, "*", "* Wrote DEBUG");
00328 }
00329 }
00330 #endif
00331
00332 static void got_bus(int z)
00333 {
00334 write_debug();
00335 fatal("BUS ERROR -- CRASHING!", 1);
00336 #ifdef SA_RESETHAND
00337 kill(getpid(), SIGBUS);
00338 #else
00339 bg_send_quit(BG_ABORT);
00340 exit(1);
00341 #endif
00342 }
00343
00344 static void got_segv(int z)
00345 {
00346 write_debug();
00347 fatal("SEGMENT VIOLATION -- CRASHING!", 1);
00348 #ifdef SA_RESETHAND
00349 kill(getpid(), SIGSEGV);
00350 #else
00351 bg_send_quit(BG_ABORT);
00352 exit(1);
00353 #endif
00354 }
00355
00356 static void got_fpe(int z)
00357 {
00358 write_debug();
00359 fatal("FLOATING POINT ERROR -- CRASHING!", 0);
00360 }
00361
00362 static void got_term(int z)
00363 {
00364 write_userfile(-1);
00365 check_tcl_event("sigterm");
00366 if (die_on_sigterm) {
00367 botnet_send_chat(-1, botnetnick, "ACK, I've been terminated!");
00368 fatal("TERMINATE SIGNAL -- SIGNING OFF", 0);
00369 } else
00370 putlog(LOG_MISC, "*", "RECEIVED TERMINATE SIGNAL (IGNORING)");
00371 }
00372
00373 static void got_quit(int z)
00374 {
00375 check_tcl_event("sigquit");
00376 putlog(LOG_MISC, "*", "RECEIVED QUIT SIGNAL (IGNORING)");
00377 return;
00378 }
00379
00380 static void got_hup(int z)
00381 {
00382 write_userfile(-1);
00383 check_tcl_event("sighup");
00384 if (die_on_sighup) {
00385 fatal("HANGUP SIGNAL -- SIGNING OFF", 0);
00386 } else
00387 putlog(LOG_MISC, "*", "Received HUP signal: rehashing...");
00388 do_restart = -2;
00389 return;
00390 }
00391
00392
00393
00394 static void got_alarm(int z)
00395 {
00396 siglongjmp(alarmret, 1);
00397
00398
00399 }
00400
00401
00402
00403 static void got_ill(int z)
00404 {
00405 check_tcl_event("sigill");
00406 #ifdef DEBUG_CONTEXT
00407 putlog(LOG_MISC, "*", "* Context: %s/%d [%s]", cx_file[cx_ptr],
00408 cx_line[cx_ptr], (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
00409 #endif
00410 }
00411
00412 #ifdef DEBUG_CONTEXT
00413
00414
00415 void eggContext(const char *file, int line, const char *module)
00416 {
00417 char x[31], *p;
00418
00419 p = strrchr(file, '/');
00420 if (!module) {
00421 strncpyz(x, p ? p + 1 : file, sizeof x);
00422 } else
00423 egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
00424 cx_ptr = ((cx_ptr + 1) & 15);
00425 strcpy(cx_file[cx_ptr], x);
00426 cx_line[cx_ptr] = line;
00427 cx_note[cx_ptr][0] = 0;
00428 }
00429
00430
00431
00432 void eggContextNote(const char *file, int line, const char *module,
00433 const char *note)
00434 {
00435 char x[31], *p;
00436
00437 p = strrchr(file, '/');
00438 if (!module)
00439 strncpyz(x, p ? p + 1 : file, sizeof x);
00440 else
00441 egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
00442 cx_ptr = ((cx_ptr + 1) & 15);
00443 strcpy(cx_file[cx_ptr], x);
00444 cx_line[cx_ptr] = line;
00445 strncpyz(cx_note[cx_ptr], note, sizeof cx_note[cx_ptr]);
00446 }
00447 #endif
00448
00449 #ifdef DEBUG_ASSERT
00450
00451
00452 void eggAssert(const char *file, int line, const char *module)
00453 {
00454 write_debug();
00455 if (!module)
00456 putlog(LOG_MISC, "*", "* In file %s, line %u", file, line);
00457 else
00458 putlog(LOG_MISC, "*", "* In file %s:%s, line %u", module, file, line);
00459 fatal("ASSERT FAILED -- CRASHING!", 1);
00460 }
00461 #endif
00462
00463 static void do_arg(char *s)
00464 {
00465 char x[512], *z = x;
00466 int i;
00467
00468 if (s[0] == '-')
00469 for (i = 1; i < strlen(s); i++) {
00470 switch (s[i]) {
00471 case 'n':
00472 backgrd = 0;
00473 break;
00474 case 'c':
00475 con_chan = 1;
00476 term_z = 0;
00477 break;
00478 case 't':
00479 con_chan = 0;
00480 term_z = 1;
00481 break;
00482 case 'm':
00483 make_userfile = 1;
00484 break;
00485 case 'v':
00486 strncpyz(x, egg_version, sizeof x);
00487 newsplit(&z);
00488 newsplit(&z);
00489 printf("%s\n", version);
00490 if (z[0])
00491 printf(" (patches: %s)\n", z);
00492 printf("Configured with: " EGG_AC_ARGS "\n");
00493 printf("handlen=%d\n", HANDLEN);
00494 bg_send_quit(BG_ABORT);
00495 exit(0);
00496 break;
00497 case 'h':
00498 printf("\n%s\n\n", version);
00499 printf(EGG_USAGE);
00500 printf("\n");
00501 bg_send_quit(BG_ABORT);
00502 exit(0);
00503 break;
00504 }
00505 } else
00506 strncpyz(configfile, s, sizeof configfile);
00507 }
00508
00509 void backup_userfile(void)
00510 {
00511 char s[125];
00512
00513 if (quiet_save < 2)
00514 putlog(LOG_MISC, "*", USERF_BACKUP);
00515 egg_snprintf(s, sizeof s, "%s~bak", userfile);
00516 copyfile(userfile, s);
00517 }
00518
00519
00520 static int lastmin = 99;
00521 static time_t then;
00522 static struct tm nowtm;
00523
00524
00525
00526
00527
00528 static void core_secondly()
00529 {
00530 static int cnt = 0;
00531 int miltime;
00532
00533 do_check_timers(&utimer);
00534 cnt++;
00535 if (cnt >= 10) {
00536 cnt = 0;
00537 check_expired_dcc();
00538 if (con_chan && !backgrd) {
00539 dprintf(DP_STDOUT, "\033[2J\033[1;1H");
00540 tell_verbose_status(DP_STDOUT);
00541 do_module_report(DP_STDOUT, 0, "server");
00542 do_module_report(DP_STDOUT, 0, "channels");
00543 tell_mem_status_dcc(DP_STDOUT);
00544 }
00545 }
00546 egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
00547 if (nowtm.tm_min != lastmin) {
00548 int i = 0;
00549
00550
00551 lastmin = (lastmin + 1) % 60;
00552 call_hook(HOOK_MINUTELY);
00553 check_expired_ignores();
00554 autolink_cycle(NULL);
00555
00556 while (nowtm.tm_min != lastmin) {
00557
00558 debug2("timer: drift (lastmin=%d, now=%d)", lastmin, nowtm.tm_min);
00559 i++;
00560 lastmin = (lastmin + 1) % 60;
00561 call_hook(HOOK_MINUTELY);
00562 }
00563 if (i > 1)
00564 putlog(LOG_MISC, "*", "(!) timer drift -- spun %d minutes", i);
00565 miltime = (nowtm.tm_hour * 100) + (nowtm.tm_min);
00566 if (((int) (nowtm.tm_min / 5) * 5) == (nowtm.tm_min)) {
00567 call_hook(HOOK_5MINUTELY);
00568 check_botnet_pings();
00569 if (!quick_logs) {
00570 flushlogs();
00571 check_logsize();
00572 }
00573 if (!miltime) {
00574 char s[25];
00575 int j;
00576
00577 strncpyz(s, ctime(&now), sizeof s);
00578 if (quiet_save < 3)
00579 putlog(LOG_ALL, "*", "--- %.11s%s", s, s + 20);
00580 call_hook(HOOK_BACKUP);
00581 for (j = 0; j < max_logs; j++) {
00582 if (logs[j].filename != NULL && logs[j].f != NULL) {
00583 fclose(logs[j].f);
00584 logs[j].f = NULL;
00585 }
00586 }
00587 }
00588 }
00589 if (nowtm.tm_min == notify_users_at)
00590 call_hook(HOOK_HOURLY);
00591
00592
00593
00594 if (miltime == switch_logfiles_at) {
00595 call_hook(HOOK_DAILY);
00596 if (!keep_all_logs) {
00597 if (quiet_save < 3)
00598 putlog(LOG_MISC, "*", MISC_LOGSWITCH);
00599 for (i = 0; i < max_logs; i++)
00600 if (logs[i].filename) {
00601 char s[1024];
00602
00603 if (logs[i].f) {
00604 fclose(logs[i].f);
00605 logs[i].f = NULL;
00606 }
00607 egg_snprintf(s, sizeof s, "%s.yesterday", logs[i].filename);
00608 unlink(s);
00609 movefile(logs[i].filename, s);
00610 }
00611 }
00612 }
00613 }
00614 }
00615
00616 static void core_minutely()
00617 {
00618 check_tcl_time(&nowtm);
00619 check_tcl_cron(&nowtm);
00620 do_check_timers(&timer);
00621 if (quick_logs != 0) {
00622 flushlogs();
00623 check_logsize();
00624 }
00625 }
00626
00627 static void core_hourly()
00628 {
00629 write_userfile(-1);
00630 }
00631
00632 static void event_rehash()
00633 {
00634 check_tcl_event("rehash");
00635 }
00636
00637 static void event_prerehash()
00638 {
00639 check_tcl_event("prerehash");
00640 }
00641
00642 static void event_save()
00643 {
00644 check_tcl_event("save");
00645 }
00646
00647 static void event_logfile()
00648 {
00649 check_tcl_event("logfile");
00650 }
00651
00652 static void event_resettraffic()
00653 {
00654 otraffic_irc += otraffic_irc_today;
00655 itraffic_irc += itraffic_irc_today;
00656 otraffic_bn += otraffic_bn_today;
00657 itraffic_bn += itraffic_bn_today;
00658 otraffic_dcc += otraffic_dcc_today;
00659 itraffic_dcc += itraffic_dcc_today;
00660 otraffic_unknown += otraffic_unknown_today;
00661 itraffic_unknown += itraffic_unknown_today;
00662 otraffic_trans += otraffic_trans_today;
00663 itraffic_trans += itraffic_trans_today;
00664 otraffic_irc_today = otraffic_bn_today = 0;
00665 otraffic_dcc_today = otraffic_unknown_today = 0;
00666 itraffic_irc_today = itraffic_bn_today = 0;
00667 itraffic_dcc_today = itraffic_unknown_today = 0;
00668 itraffic_trans_today = otraffic_trans_today = 0;
00669 }
00670
00671 static void event_loaded()
00672 {
00673 check_tcl_event("loaded");
00674 }
00675
00676 void kill_tcl();
00677 extern module_entry *module_list;
00678 void restart_chons();
00679
00680 #ifdef STATIC
00681 void check_static(char *, char *(*)());
00682
00683 #include "mod/static.h"
00684 #endif
00685 int init_threaddata(int);
00686 int init_mem();
00687 int init_userent();
00688 int init_misc();
00689 int init_bots();
00690 int init_modules();
00691 int init_tcl(int, char **);
00692 int init_language(int);
00693
00694 static void patch(const char *str)
00695 {
00696 char *p = strchr(egg_version, '+');
00697
00698 if (!p)
00699 p = &egg_version[strlen(egg_version)];
00700 sprintf(p, "+%s", str);
00701 egg_numver++;
00702 sprintf(&egg_xtra[strlen(egg_xtra)], " %s", str);
00703 }
00704
00705 static inline void garbage_collect(void)
00706 {
00707 static u_8bit_t run_cnt = 0;
00708
00709 if (run_cnt == 3)
00710 garbage_collect_tclhash();
00711 else
00712 run_cnt++;
00713 }
00714
00715 int mainloop(int toplevel)
00716 {
00717 static int socket_cleanup = 0;
00718 int xx, i, eggbusy = 1, tclbusy = 0, old_do_restart;
00719 char buf[520];
00720
00721
00722
00723
00724 now = time(NULL);
00725
00726
00727
00728
00729
00730
00731
00732
00733 random();
00734
00735
00736
00737
00738
00739 if (do_restart && do_restart != -2 && !toplevel)
00740 return -1;
00741
00742
00743 if (now != then) {
00744 call_hook(HOOK_SECONDLY);
00745 then = now;
00746 }
00747
00748
00749 if (!socket_cleanup) {
00750 socket_cleanup = 5;
00751
00752
00753 dcc_remove_lost();
00754
00755
00756 dequeue_sockets();
00757 } else
00758 socket_cleanup--;
00759
00760
00761 if (toplevel)
00762 garbage_collect();
00763
00764 xx = sockgets(buf, &i);
00765 if (xx >= 0) {
00766 int idx;
00767
00768 for (idx = 0; idx < dcc_total; idx++)
00769 if (dcc[idx].sock == xx) {
00770 if (dcc[idx].type && dcc[idx].type->activity) {
00771
00772 if (dcc[idx].type->name) {
00773 if (!strncmp(dcc[idx].type->name, "BOT", 3))
00774 itraffic_bn_today += strlen(buf) + 1;
00775 else if (!strcmp(dcc[idx].type->name, "SERVER"))
00776 itraffic_irc_today += strlen(buf) + 1;
00777 else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
00778 itraffic_dcc_today += strlen(buf) + 1;
00779 else if (!strncmp(dcc[idx].type->name, "FILES", 5))
00780 itraffic_dcc_today += strlen(buf) + 1;
00781 else if (!strcmp(dcc[idx].type->name, "SEND"))
00782 itraffic_trans_today += strlen(buf) + 1;
00783 else if (!strncmp(dcc[idx].type->name, "GET", 3))
00784 itraffic_trans_today += strlen(buf) + 1;
00785 else
00786 itraffic_unknown_today += strlen(buf) + 1;
00787 }
00788 dcc[idx].type->activity(idx, buf, i);
00789 } else
00790 putlog(LOG_MISC, "*",
00791 "!!! untrapped dcc activity: type %s, sock %d",
00792 dcc[idx].type->name, dcc[idx].sock);
00793 break;
00794 }
00795 } else if (xx == -1) {
00796 int idx;
00797
00798 if (i == STDOUT && !backgrd)
00799 fatal("END OF FILE ON TERMINAL", 0);
00800 for (idx = 0; idx < dcc_total; idx++)
00801 if (dcc[idx].sock == i) {
00802 if (dcc[idx].type && dcc[idx].type->eof)
00803 dcc[idx].type->eof(idx);
00804 else {
00805 putlog(LOG_MISC, "*",
00806 "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
00807 i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
00808 killsock(i);
00809 lostdcc(idx);
00810 }
00811 idx = dcc_total + 1;
00812 }
00813 if (idx == dcc_total) {
00814 putlog(LOG_MISC, "*",
00815 "(@) EOF socket %d, not a dcc socket, not anything.", i);
00816 close(i);
00817 killsock(i);
00818 }
00819 } else if (xx == -2 && errno != EINTR) {
00820 putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno);
00821 for (i = 0; i < dcc_total; i++) {
00822 if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno == EBADF)) {
00823 putlog(LOG_MISC, "*",
00824 "DCC socket %d (type %d, name '%s') expired -- pfft",
00825 dcc[i].sock, dcc[i].type, dcc[i].nick);
00826 killsock(dcc[i].sock);
00827 lostdcc(i);
00828 i--;
00829 }
00830 }
00831 } else if (xx == -3) {
00832 call_hook(HOOK_IDLE);
00833 socket_cleanup = 0;
00834 eggbusy = 0;
00835 } else if (xx == -5) {
00836 eggbusy = 0;
00837 tclbusy = 1;
00838 }
00839
00840
00841
00842 if (do_restart) {
00843 old_do_restart = do_restart;
00844 do_restart = 0;
00845 if (old_do_restart == -2)
00846 rehash();
00847 else if (!toplevel)
00848 return -1;
00849 else {
00850
00851 int f = 1;
00852 module_entry *p;
00853 Function startfunc;
00854 char name[256];
00855
00856
00857 check_tcl_event("prerestart");
00858
00859 while (f) {
00860 f = 0;
00861 for (p = module_list; p != NULL; p = p->next) {
00862 dependancy *d = dependancy_list;
00863 int ok = 1;
00864
00865 while (ok && d) {
00866 if (d->needed == p)
00867 ok = 0;
00868 d = d->next;
00869 }
00870 if (ok) {
00871 strcpy(name, p->name);
00872 if (module_unload(name, botnetnick) == NULL) {
00873 f = 1;
00874 break;
00875 }
00876 }
00877 }
00878 }
00879
00880
00881
00882
00883 for (f = 0, p = module_list; p; p = p->next) {
00884 if (strcmp(p->name, "eggdrop") && strcmp(p->name, "encryption") &&
00885 strcmp(p->name, "uptime")) {
00886 f++;
00887 }
00888 }
00889 if (f != 0) {
00890 putlog(LOG_MISC, "*", MOD_STAGNANT);
00891 }
00892
00893 flushlogs();
00894 kill_tcl();
00895 init_tcl(argc, argv);
00896 init_language(0);
00897
00898
00899 for (p = module_list; p; p = p->next) {
00900 if (p->funcs) {
00901 startfunc = p->funcs[MODCALL_START];
00902 startfunc(NULL);
00903 }
00904 }
00905
00906 rehash();
00907 restart_chons();
00908 call_hook(HOOK_LOADED);
00909 }
00910 eggbusy = 1;
00911 }
00912
00913 #ifdef USE_TCL_EVENTS
00914 if (!eggbusy) {
00915
00916
00917 # ifdef REPLACE_NOTIFIER
00918 tclevent_t *e;
00919 if (Tcl_ServiceAll())
00920 tclbusy = 1;
00921 while (tclevents) {
00922 e = tclevents;
00923 tclevents = tclevents->next;
00924 tclbusy = 1;
00925 do_tcl_sync(e->context, e->script, e->callback, 1);
00926 nfree(e);
00927 }
00928 # else
00929 while (Tcl_DoOneEvent(TCL_DONT_WAIT | TCL_ALL_EVENTS))
00930 tclbusy = 1;
00931 # endif
00932
00933 #endif
00934 }
00935
00936 return (eggbusy || tclbusy);
00937 }
00938
00939 int main(int arg_c, char **arg_v)
00940 {
00941 int i, xx;
00942 char s[25];
00943 FILE *f;
00944 struct sigaction sv;
00945 struct chanset_t *chan;
00946 #ifdef DEBUG
00947 struct rlimit cdlim;
00948 #endif
00949 #ifdef STOP_UAC
00950 int nvpair[2];
00951 #endif
00952
00953
00954
00955
00956
00957
00958
00959
00960 #ifdef DEBUG
00961 cdlim.rlim_cur = RLIM_INFINITY;
00962 cdlim.rlim_max = RLIM_INFINITY;
00963 setrlimit(RLIMIT_CORE, &cdlim);
00964 #endif
00965
00966 #ifdef DEBUG_CONTEXT
00967
00968 for (i = 0; i < 16; i++)
00969 Context;
00970 #endif
00971
00972
00973 #include "patch.h"
00974
00975 argc = arg_c;
00976 argv = arg_v;
00977
00978
00979 egg_snprintf(ver, sizeof ver, "eggdrop v%s", egg_version);
00980 egg_snprintf(version, sizeof version,
00981 "Eggdrop v%s (C) 1997 Robey Pointer (C) 2011 Eggheads",
00982 egg_version);
00983
00984 sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver);
00985 strcat(egg_version, egg_xtra);
00986
00987
00988 #ifdef STOP_UAC
00989
00990 nvpair[0] = SSIN_UACPROC;
00991 nvpair[1] = UAC_NOPRINT;
00992 setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
00993 #endif
00994
00995
00996 sv.sa_handler = got_bus;
00997 sigemptyset(&sv.sa_mask);
00998 #ifdef SA_RESETHAND
00999 sv.sa_flags = SA_RESETHAND;
01000 #else
01001 sv.sa_flags = 0;
01002 #endif
01003 sigaction(SIGBUS, &sv, NULL);
01004 sv.sa_handler = got_segv;
01005 sigaction(SIGSEGV, &sv, NULL);
01006 #ifdef SA_RESETHAND
01007 sv.sa_flags = 0;
01008 #endif
01009 sv.sa_handler = got_fpe;
01010 sigaction(SIGFPE, &sv, NULL);
01011 sv.sa_handler = got_term;
01012 sigaction(SIGTERM, &sv, NULL);
01013 sv.sa_handler = got_hup;
01014 sigaction(SIGHUP, &sv, NULL);
01015 sv.sa_handler = got_quit;
01016 sigaction(SIGQUIT, &sv, NULL);
01017 sv.sa_handler = SIG_IGN;
01018 sigaction(SIGPIPE, &sv, NULL);
01019 sv.sa_handler = got_ill;
01020 sigaction(SIGILL, &sv, NULL);
01021 sv.sa_handler = got_alarm;
01022 sigaction(SIGALRM, &sv, NULL);
01023
01024
01025 now = time(NULL);
01026 chanset = NULL;
01027 egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
01028 lastmin = nowtm.tm_min;
01029 srandom((unsigned int) (now % (getpid() + getppid())));
01030 init_mem();
01031 init_language(1);
01032 if (argc > 1)
01033 for (i = 1; i < argc; i++)
01034 do_arg(argv[i]);
01035
01036 printf("\n%s\n", version);
01037
01038 #ifndef CYGWIN_HACKS
01039
01040
01041
01042
01043 if (((int) getuid() == 0) || ((int) geteuid() == 0))
01044 fatal("ERROR: Eggdrop will not run as root!", 0);
01045 #endif
01046
01047 #ifndef REPLACE_NOTIFIER
01048 init_threaddata(1);
01049 #endif
01050 init_userent();
01051 init_misc();
01052 init_bots();
01053 init_modules();
01054 if (backgrd)
01055 bg_prepare_split();
01056 init_tcl(argc, argv);
01057 init_language(0);
01058 #ifdef STATIC
01059 link_statics();
01060 #endif
01061 strncpyz(s, ctime(&now), sizeof s);
01062 strcpy(&s[11], &s[20]);
01063 putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s);
01064 chanprog();
01065 if (!encrypt_pass) {
01066 printf(MOD_NOCRYPT);
01067 bg_send_quit(BG_ABORT);
01068 exit(1);
01069 }
01070 i = 0;
01071 for (chan = chanset; chan; chan = chan->next)
01072 i++;
01073 putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.",
01074 botnetnick, i, count_users(userlist));
01075 cache_miss = 0;
01076 cache_hit = 0;
01077 if (!pid_file[0])
01078 egg_snprintf(pid_file, sizeof pid_file, "pid.%s", botnetnick);
01079
01080
01081 f = fopen(pid_file, "r");
01082 if (f != NULL) {
01083 fgets(s, 10, f);
01084 xx = atoi(s);
01085 i = kill(xx, SIGCHLD);
01086
01087 if (i == 0 || errno != ESRCH) {
01088 printf(EGG_RUNNING1, botnetnick);
01089 printf(EGG_RUNNING2, pid_file);
01090 bg_send_quit(BG_ABORT);
01091 exit(1);
01092 }
01093 }
01094
01095
01096 if (backgrd) {
01097 bg_do_split();
01098 } else {
01099 xx = getpid();
01100 if (xx != 0) {
01101 FILE *fp;
01102
01103
01104 unlink(pid_file);
01105 fp = fopen(pid_file, "w");
01106 if (fp != NULL) {
01107 fprintf(fp, "%u\n", xx);
01108 if (fflush(fp)) {
01109
01110 printf(EGG_NOWRITE, pid_file);
01111 fclose(fp);
01112 unlink(pid_file);
01113 } else
01114 fclose(fp);
01115 } else
01116 printf(EGG_NOWRITE, pid_file);
01117 }
01118 }
01119
01120 use_stderr = 0;
01121 if (backgrd) {
01122
01123 #ifdef HAVE_SETPGID
01124 setpgid(0, 0);
01125 #endif
01126
01127 freopen("/dev/null", "r", stdin);
01128 freopen("/dev/null", "w", stdout);
01129 freopen("/dev/null", "w", stderr);
01130 #ifdef CYGWIN_HACKS
01131 FreeConsole();
01132 #endif
01133 }
01134
01135
01136 if (!backgrd && term_z) {
01137 int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
01138
01139 dcc[n].addr = iptolong(getmyip());
01140 dcc[n].sock = STDOUT;
01141 dcc[n].timeval = now;
01142 dcc[n].u.chat->con_flags = conmask;
01143 dcc[n].u.chat->strip_flags = STRIP_ALL;
01144 dcc[n].status = STAT_ECHO;
01145 strcpy(dcc[n].nick, "HQ");
01146 strcpy(dcc[n].host, "llama@console");
01147
01148 dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
01149
01150 if (!dcc[n].user) {
01151 userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_PARTY);
01152 dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
01153 }
01154 setsock(STDOUT, 0);
01155 dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
01156 dcc_chatter(n);
01157 }
01158
01159 then = now;
01160 online_since = now;
01161 autolink_cycle(NULL);
01162 add_help_reference("cmds1.help");
01163 add_help_reference("cmds2.help");
01164 add_help_reference("core.help");
01165 add_hook(HOOK_SECONDLY, (Function) core_secondly);
01166 add_hook(HOOK_MINUTELY, (Function) core_minutely);
01167 add_hook(HOOK_HOURLY, (Function) core_hourly);
01168 add_hook(HOOK_REHASH, (Function) event_rehash);
01169 add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
01170 add_hook(HOOK_USERFILE, (Function) event_save);
01171 add_hook(HOOK_BACKUP, (Function) backup_userfile);
01172 add_hook(HOOK_DAILY, (Function) event_logfile);
01173 add_hook(HOOK_DAILY, (Function) event_resettraffic);
01174 add_hook(HOOK_LOADED, (Function) event_loaded);
01175
01176 call_hook(HOOK_LOADED);
01177
01178 debug0("main: entering loop");
01179 while (1) {
01180 mainloop(1);
01181 }
01182 }