static void timeout_server(int idx) { putlog(LOG_SERV, "*", "Timeout: connect to %s", dcc[idx].host); disconnect_server(idx); check_tcl_event("fail-server"); lostdcc(idx); }
/* Got ILL signal -- log context and continue */ static void got_ill(int z) { check_tcl_event("sigill"); #ifdef DEBUG_CONTEXT putlog(LOG_MISC, "*", "* Context: %s/%d [%s]", cx_file[cx_ptr], cx_line[cx_ptr], (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : ""); #endif }
static void server_resolve_failure(int servidx) { serv = -1; resolvserv = 0; putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host, IRC_DNSFAILED); check_tcl_event("fail-server"); lostdcc(servidx); }
/* 001: welcome to IRC (use it to fix the server name) */ static int got001(char *from, char *msg) { int i; char *key; struct chanset_t *chan; struct server_list *x = serverlist; /* FIXME - x should never be NULL anywhere in this function, but * apparently it sometimes is. */ if (x) { for (i = curserv; i > 0 && x; i--) x = x->next; if (!x) { putlog(LOG_MISC, "*", "Invalid server list!"); } else { if (x->realname) nfree(x->realname); x->realname = nmalloc(strlen(from) + 1); strcpy(x->realname, from); } if (realservername) nfree(realservername); realservername = nmalloc(strlen(from) + 1); strcpy(realservername, from); } else putlog(LOG_MISC, "*", "No server list!"); server_online = now; fixcolon(msg); strncpyz(botname, msg, NICKLEN); altnick_char = 0; dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */ if (initserver[0]) do_tcl("init-server", initserver); /* Call Tcl init-server */ check_tcl_event("init-server"); if (!x) return 0; if (module_find("irc", 0, 0)) { /* Only join if the IRC module is loaded. */ for (chan = chanset; chan; chan = chan->next) { chan->status &= ~(CHAN_ACTIVE | CHAN_PEND); if (!channel_inactive(chan)) { key = chan->channel.key[0] ? chan->channel.key : chan->key_prot; if (key[0]) dprintf(DP_SERVER, "JOIN %s %s\n", chan->name[0] ? chan->name : chan->dname, key); else dprintf(DP_SERVER, "JOIN %s\n", chan->name[0] ? chan->name : chan->dname); } } } return 0; }
static void got_term(int z) { write_userfile(-1); check_tcl_event("sigterm"); if (die_on_sigterm) { botnet_send_chat(-1, botnetnick, "ACK, I've been terminated!"); fatal("TERMINATE SIGNAL -- SIGNING OFF", 0); } else putlog(LOG_MISC, "*", "RECEIVED TERMINATE SIGNAL (IGNORING)"); }
static void got_hup(int z) { write_userfile(-1); check_tcl_event("sighup"); if (die_on_sighup) { fatal("HANGUP SIGNAL -- SIGNING OFF", 0); } else putlog(LOG_MISC, "*", "Received HUP signal: rehashing..."); do_restart = -2; return; }
static void disconnect_server(int idx) { if (server_online > 0) check_tcl_event("disconnect-server"); server_online = 0; if (realservername) nfree(realservername); realservername = 0; if (dcc[idx].sock >= 0) killsock(dcc[idx].sock); dcc[idx].sock = -1; serv = -1; botuserhost[0] = 0; }
static void server_resolve_success(int servidx) { char s[121], pass[121]; resolvserv = 0; dcc[servidx].addr = dcc[servidx].u.dns->ip; strcpy(pass, dcc[servidx].u.dns->cbuf); changeover_dcc(servidx, &SERVER_SOCKET, 0); serv = open_telnet(iptostr(htonl(dcc[servidx].addr)), dcc[servidx].port); if (serv < 0) { neterror(s); putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host, s); check_tcl_event("fail-server"); lostdcc(servidx); } else { dcc[servidx].sock = serv; /* Queue standard login */ dcc[servidx].timeval = now; SERVER_SOCKET.timeout_val = &server_timeout; /* Another server may have truncated it, so use the original */ strcpy(botname, origbotname); /* Start alternate nicks from the beginning */ altnick_char = 0; check_tcl_event("preinit-server"); if (pass[0]) dprintf(DP_MODE, "PASS %s\n", pass); dprintf(DP_MODE, "NICK %s\n", botname); rmspace(botrealname); if (botrealname[0] == 0) strcpy(botrealname, "/msg LamestBot hello"); dprintf(DP_MODE, "USER %s . . :%s\n", botuser, botrealname); /* Wait for async result now. */ } }
/* Reload the user file from disk */ void reload() { if (!file_readable(userfile)) { putlog(LOG_MISC, "*", MISC_CANTRELOADUSER); return; } noshare = 1; clear_userlist(userlist); noshare = 0; userlist = NULL; if (!readuserfile(userfile, &userlist)) fatal(MISC_MISSINGUSERF, 0); reaffirm_owners(); check_tcl_event("userfile-loaded"); call_hook(HOOK_READ_USERFILE); }
void chanprog() { int i; FILE *f; char s[161], rands[8]; admin[0] = 0; helpdir[0] = 0; tempdir[0] = 0; conmask = 0; for (i = 0; i < max_logs; i++) logs[i].flags |= LF_EXPIRING; /* Turn off read-only variables (make them write-able) for rehash */ protect_readonly = 0; /* Now read it */ if (!readtclprog(configfile)) fatal(MISC_NOCONFIGFILE, 0); for (i = 0; i < max_logs; i++) { if (logs[i].flags & LF_EXPIRING) { if (logs[i].filename != NULL) { nfree(logs[i].filename); logs[i].filename = NULL; } if (logs[i].chname != NULL) { nfree(logs[i].chname); logs[i].chname = NULL; } if (logs[i].f != NULL) { fclose(logs[i].f); logs[i].f = NULL; } logs[i].mask = 0; logs[i].flags = 0; } } /* We should be safe now */ call_hook(HOOK_REHASH); protect_readonly = 1; if (!botnetnick[0]) strncpyz(botnetnick, origbotname, HANDLEN + 1); if (!botnetnick[0]) fatal("I don't have a botnet nick!!\n", 0); if (!userfile[0]) fatal(MISC_NOUSERFILE2, 0); if (!readuserfile(userfile, &userlist)) { if (!make_userfile) { char tmp[178]; egg_snprintf(tmp, sizeof tmp, MISC_NOUSERFILE, configfile); fatal(tmp, 0); } printf("\n\n%s\n", MISC_NOUSERFILE2); if (module_find("server", 0, 0)) printf(MISC_USERFCREATE1, origbotname); printf("%s\n\n", MISC_USERFCREATE2); } else if (make_userfile) { make_userfile = 0; printf("%s\n", MISC_USERFEXISTS); } if (helpdir[0]) if (helpdir[strlen(helpdir) - 1] != '/') strcat(helpdir, "/"); if (tempdir[0]) if (tempdir[strlen(tempdir) - 1] != '/') strcat(tempdir, "/"); /* Test tempdir: it's vital. */ /* Possible file race condition solved by using a random string * and the process id in the filename. * FIXME: This race is only partitially fixed. We could still be * overwriting an existing file / following a malicious * link. */ make_rand_str(rands, 7); /* create random string */ sprintf(s, "%s.test-%u-%s", tempdir, getpid(), rands); f = fopen(s, "w"); if (f == NULL) fatal(MISC_CANTWRITETEMP, 0); fclose(f); unlink(s); reaffirm_owners(); check_tcl_event("userfile-loaded"); }
int mainloop(int toplevel) { static int socket_cleanup = 0; int xx, i, eggbusy = 1, tclbusy = 0; char buf[520]; /* Lets move some of this here, reducing the numer of actual * calls to periodic_timers */ now = time(NULL); /* * FIXME: Get rid of this, it's ugly and wastes lots of cpu. * * pre-1.3.0 Eggdrop had random() in the once a second block below. * * This attempts to keep random() more random by constantly * calling random() and updating the state information. */ random(); /* Woop, lets really jumble things */ /* If we want to restart, we have to unwind to the toplevel. * Tcl will Panic if we kill the interp with Tcl_Eval in progress. * This is done by returning -1 in tickle_WaitForEvent. */ if (do_restart && do_restart != -2 && !toplevel) return -1; /* Once a second */ if (now != then) { call_hook(HOOK_SECONDLY); then = now; } /* Only do this every so often. */ if (!socket_cleanup) { socket_cleanup = 5; /* Remove dead dcc entries. */ dcc_remove_lost(); /* Check for server or dcc activity. */ dequeue_sockets(); } else socket_cleanup--; /* Free unused structures. */ garbage_collect(); xx = sockgets(buf, &i); if (xx >= 0) { /* Non-error */ int idx; for (idx = 0; idx < dcc_total; idx++) if (dcc[idx].sock == xx) { if (dcc[idx].type && dcc[idx].type->activity) { /* Traffic stats */ if (dcc[idx].type->name) { if (!strncmp(dcc[idx].type->name, "BOT", 3)) itraffic_bn_today += strlen(buf) + 1; else if (!strcmp(dcc[idx].type->name, "SERVER")) itraffic_irc_today += strlen(buf) + 1; else if (!strncmp(dcc[idx].type->name, "CHAT", 4)) itraffic_dcc_today += strlen(buf) + 1; else if (!strncmp(dcc[idx].type->name, "FILES", 5)) itraffic_dcc_today += strlen(buf) + 1; else if (!strcmp(dcc[idx].type->name, "SEND")) itraffic_trans_today += strlen(buf) + 1; else if (!strncmp(dcc[idx].type->name, "GET", 3)) itraffic_trans_today += strlen(buf) + 1; else itraffic_unknown_today += strlen(buf) + 1; } dcc[idx].type->activity(idx, buf, i); } else putlog(LOG_MISC, "*", "!!! untrapped dcc activity: type %s, sock %d", dcc[idx].type->name, dcc[idx].sock); break; } } else if (xx == -1) { /* EOF from someone */ int idx; if (i == STDOUT && !backgrd) fatal("END OF FILE ON TERMINAL", 0); for (idx = 0; idx < dcc_total; idx++) if (dcc[idx].sock == i) { if (dcc[idx].type && dcc[idx].type->eof) dcc[idx].type->eof(idx); else { putlog(LOG_MISC, "*", "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED", i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*"); killsock(i); lostdcc(idx); } idx = dcc_total + 1; } if (idx == dcc_total) { putlog(LOG_MISC, "*", "(@) EOF socket %d, not a dcc socket, not anything.", i); close(i); killsock(i); } } else if (xx == -2 && errno != EINTR) { /* select() error */ putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno); for (i = 0; i < dcc_total; i++) { if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno == EBADF)) { putlog(LOG_MISC, "*", "DCC socket %d (type %d, name '%s') expired -- pfft", dcc[i].sock, dcc[i].type, dcc[i].nick); killsock(dcc[i].sock); lostdcc(i); i--; } } } else if (xx == -3) { call_hook(HOOK_IDLE); socket_cleanup = 0; /* If we've been idle, cleanup & flush */ eggbusy = 0; } else if (xx == -5) { eggbusy = 0; tclbusy = 1; } if (do_restart) { if (do_restart == -2) rehash(); else if (!toplevel) return -1; /* Unwind to toplevel before restarting */ else { /* Unload as many modules as possible */ int f = 1; module_entry *p; Function startfunc; char name[256]; /* oops, I guess we should call this event before tcl is restarted */ check_tcl_event("prerestart"); while (f) { f = 0; for (p = module_list; p != NULL; p = p->next) { dependancy *d = dependancy_list; int ok = 1; while (ok && d) { if (d->needed == p) ok = 0; d = d->next; } if (ok) { strcpy(name, p->name); if (module_unload(name, botnetnick) == NULL) { f = 1; break; } } } } /* Make sure we don't have any modules left hanging around other than * "eggdrop" and the two that are supposed to be. */ for (f = 0, p = module_list; p; p = p->next) { if (strcmp(p->name, "eggdrop") && strcmp(p->name, "encryption") && strcmp(p->name, "uptime")) { f++; } } if (f != 0) { putlog(LOG_MISC, "*", MOD_STAGNANT); } flushlogs(); kill_tcl(); init_tcl(argc, argv); init_language(0); /* this resets our modules which we didn't unload (encryption and uptime) */ for (p = module_list; p; p = p->next) { if (p->funcs) { startfunc = p->funcs[MODCALL_START]; startfunc(NULL); } } rehash(); #ifdef TLS ssl_cleanup(); ssl_init(); #endif restart_chons(); call_hook(HOOK_LOADED); } eggbusy = 1; do_restart = 0; } #ifdef USE_TCL_EVENTS if (!eggbusy) { /* Process all pending tcl events */ # ifdef REPLACE_NOTIFIER if (Tcl_ServiceAll()) tclbusy = 1; # else while (Tcl_DoOneEvent(TCL_DONT_WAIT | TCL_ALL_EVENTS)) tclbusy = 1; # endif /* REPLACE_NOTIFIER */ #endif /* USE_TCL_EVENTS */ } return (eggbusy || tclbusy); }
static void event_loaded() { check_tcl_event("loaded"); }
static void event_logfile() { check_tcl_event("logfile"); }
static void event_save() { check_tcl_event("save"); }
static void event_prerehash() { check_tcl_event("prerehash"); }
static void event_rehash() { check_tcl_event("rehash"); }
/* Hook up to a server */ static void connect_server(void) { char pass[121], botserver[UHOSTLEN]; int servidx; unsigned int botserverport = 0; lastpingcheck = 0; trying_server = now; empty_msgq(); if (newserverport) { /* Jump to specified server */ curserv = -1; /* Reset server list */ strcpy(botserver, newserver); botserverport = newserverport; strcpy(pass, newserverpass); newserver[0] = 0; newserverport = 0; newserverpass[0] = 0; } else { if (curserv == -1) curserv = 999; pass[0] = 0; } if (!cycle_time) { struct chanset_t *chan; struct server_list *x = serverlist; if (!x && !botserverport) { putlog(LOG_SERV, "*", "No servers in server list"); cycle_time = 300; return; } servidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info)); if (servidx < 0) { putlog(LOG_SERV, "*", "NO MORE DCC CONNECTIONS -- Can't create server connection."); return; } if (connectserver[0]) /* drummer */ do_tcl("connect-server", connectserver); check_tcl_event("connect-server"); next_server(&curserv, botserver, &botserverport, pass); #ifdef TLS putlog(LOG_SERV, "*", "%s [%s]:%s%d", IRC_SERVERTRY, botserver, use_ssl ? "+" : "", botserverport); dcc[servidx].ssl = use_ssl; #else putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver, botserverport); #endif dcc[servidx].port = botserverport; strcpy(dcc[servidx].nick, "(server)"); strncpyz(dcc[servidx].host, botserver, UHOSTLEN); botuserhost[0] = 0; nick_juped = 0; for (chan = chanset; chan; chan = chan->next) chan->status &= ~CHAN_JUPED; dcc[servidx].timeval = now; dcc[servidx].sock = -1; dcc[servidx].u.dns->host = get_data_ptr(strlen(dcc[servidx].host) + 1); strcpy(dcc[servidx].u.dns->host, dcc[servidx].host); dcc[servidx].u.dns->cbuf = get_data_ptr(strlen(pass) + 1); strcpy(dcc[servidx].u.dns->cbuf, pass); dcc[servidx].u.dns->dns_success = server_resolve_success; dcc[servidx].u.dns->dns_failure = server_resolve_failure; dcc[servidx].u.dns->dns_type = RES_IPBYHOST; dcc[servidx].u.dns->type = &SERVER_SOCKET; if (server_cycle_wait) /* Back to 1st server & set wait time. * Note: Put it here, just in case the server quits on us quickly */ cycle_time = server_cycle_wait; else cycle_time = 0; /* I'm resolving... don't start another server connect request */ resolvserv = 1; /* Resolve the hostname. */ dcc_dnsipbyhost(dcc[servidx].host); } }
static void got_quit(int z) { check_tcl_event("sigquit"); putlog(LOG_MISC, "*", "RECEIVED QUIT SIGNAL (IGNORING)"); return; }
int main(int argc, char **argv) { int xx, i; #ifdef STOP_UAC int nvpair[2]; #endif char buf[520], s[25]; FILE *f; #ifndef ENABLE_STRIP struct rlimit cdlim; #endif /* Don't allow Eggdrop to run as root. */ if (((int) getuid() == 0) || ((int) geteuid() == 0)) fatal("ERROR: Eggdrop will not run as root!", 0); #ifndef ENABLE_STRIP cdlim.rlim_cur = RLIM_INFINITY; cdlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &cdlim); #endif #include "patch.h" /* Version info! */ egg_snprintf(ver, sizeof ver, "eggdrop v%s", egg_version); egg_snprintf(version, sizeof version, "Eggdrop v%s (C) 1997 Robey Pointer (C) 2005 Eggheads", egg_version); /* Now add on the patchlevel (for Tcl) */ sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver); strcat(egg_version, egg_xtra); #ifdef STOP_UAC nvpair[0] = SSIN_UACPROC; nvpair[1] = UAC_NOPRINT; setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0); #endif /* Set up error / signal traps. */ setup_signal_traps(); /* Initialize a few variables before main loop. */ cache_miss = 0; cache_hit = 0; chanset = NULL; now = time(NULL); egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm)); lastmin = nowtm.tm_min; /* Initialize random number generator. */ srandom((unsigned int) (now % (getpid() + getppid()))); init_mem(); init_language(1); /* Process command line arguments. */ process_args(argc, argv); printf("\n%s\n", version); init_dcc_max(); init_userent(); logfile_init(0); init_bots(); init_net(); init_modules(); if (backgrd) bg_prepare_split(); init_tcl(argc, argv); init_language(0); help_init(); traffic_init(); logfile_init(1); #ifdef STATIC link_statics(); #endif strncpyz(s, ctime(&now), sizeof s); strcpy(&s[11], &s[20]); putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s); /* Read configuration data. */ readconfig(); /* Check for encryption module. */ if (!encrypt_pass) { printf(MOD_NOCRYPT); bg_send_quit(BG_ABORT); exit(1); } putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.", botnetnick, count_channels(), count_users(userlist)); if (!pid_file[0]) egg_snprintf(pid_file, sizeof pid_file, "pid.%s", botnetnick); /* Check for pre-existing eggdrop! */ f = fopen(pid_file, "r"); if (f != NULL) { fgets(s, 10, f); xx = atoi(s); kill(xx, SIGCHLD); /* Meaningless kill to determine if PID is used. */ if (errno != ESRCH) { printf(EGG_RUNNING1, botnetnick); printf(EGG_RUNNING2, pid_file); bg_send_quit(BG_ABORT); exit(1); } } /* Move into background? */ if (backgrd) { #ifndef CYGWIN_HACKS bg_do_split(); } else { #endif xx = getpid(); if (xx != 0) { FILE *fp; /* Write PID to file. */ unlink(pid_file); fp = fopen(pid_file, "w"); if (fp != NULL) { fprintf(fp, "%u\n", xx); if (fflush(fp)) { /* Let the bot live since this doesn't appear to be a botchk. */ printf("Cannot not write to '%s' (PID file).\n", pid_file); fclose(fp); unlink(pid_file); } else fclose(fp); } else printf("Cannot not write to '%s' (PID file).\n", pid_file); #ifdef CYGWIN_HACKS printf("Launched into the background (PID: %d)\n\n", xx); #endif } } use_stderr = 0; /* Stop writing to stderr now */ if (backgrd) { /* Ok, try to disassociate from controlling terminal (finger cross) */ #if defined(HAVE_SETPGID) && !defined(CYGWIN_HACKS) setpgid(0, 0); #endif /* Tcl wants the stdin, stdout and stderr file handles kept open. */ freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); #ifdef CYGWIN_HACKS FreeConsole(); #endif } /* Terminal emulating dcc chat */ if (!backgrd && term_z) { int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info)); dcc[n].addr = iptolong(getmyip()); dcc[n].sock = STDOUT; dcc[n].timeval = now; dcc[n].u.chat->con_flags = conmask; dcc[n].u.chat->strip_flags = STRIP_ALL; dcc[n].status = STAT_ECHO; strcpy(dcc[n].nick, "HQ"); strcpy(dcc[n].host, "llama@console"); /* HACK: Workaround not to pass literal "HQ" as a non-const arg */ dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); /* Make sure there's an innocuous HQ user if needed */ if (!dcc[n].user) { userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_PARTY); dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); } setsock(STDOUT, 0); /* Entry in net table */ dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_chatter(n); } then = now; online_since = now; autolink_cycle(NULL); /* Hurry and connect to tandem bots. */ add_help_reference("cmds1.help"); add_help_reference("cmds2.help"); add_help_reference("core.help"); /* Create hooks. */ add_hook(HOOK_SECONDLY, (Function) core_secondly); add_hook(HOOK_MINUTELY, (Function) core_minutely); add_hook(HOOK_HOURLY, (Function) core_hourly); add_hook(HOOK_REHASH, (Function) event_rehash); add_hook(HOOK_PRE_REHASH, (Function) event_prerehash); add_hook(HOOK_USERFILE, (Function) event_save); add_hook(HOOK_BACKUP, (Function) backupuserfile); add_hook(HOOK_DAILY, (Function) event_logfile); add_hook(HOOK_DAILY, (Function) traffic_reset); add_hook(HOOK_LOADED, (Function) event_loaded); call_hook(HOOK_LOADED); debug0("main: entering loop"); while (1) { int socket_cleanup = 0; #ifdef USE_TCL_EVENTS /* Process a single Tcl event. */ Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT); #endif now = time(NULL); random(); /* Every second... */ if (now != then) { call_hook(HOOK_SECONDLY); then = now; } /* Only do this every so often. */ if (!socket_cleanup) { socket_cleanup = 5; /* Remove dead dcc entries. */ dcc_remove_lost(); /* Check for server or dcc activity. */ dequeue_sockets(); } else { socket_cleanup--; } /* Free unused structures. */ garbage_collect(); xx = sockgets(buf, &i); if (xx >= 0) { /* Non-error */ int idx; for (idx = 0; idx < dcc_total; idx++) { if (dcc[idx].sock != xx) continue; if (dcc[idx].type && dcc[idx].type->activity) { traffic_update_in(dcc[idx].type, (strlen(buf) + 1)); /* Traffic stats. */ dcc[idx].type->activity(idx, buf, i); } else { putlog(LOG_MISC, "*", "!!! untrapped dcc activity: type %s, sock %d", dcc[idx].type->name, dcc[idx].sock); } break; } } else if (xx == -1) { /* EOF */ int idx; if (i == STDOUT && !backgrd) fatal("END OF FILE ON TERMINAL", 0); for (idx = 0; idx < dcc_total; idx++) { if (dcc[idx].sock != i) continue; if (dcc[idx].type && dcc[idx].type->eof) { dcc[idx].type->eof(idx); } else { putlog(LOG_MISC, "*", "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED", i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*"); killsock(i); lostdcc(idx); } idx = dcc_total + 1; } if (idx == dcc_total) { putlog(LOG_MISC, "*", "(@) EOF socket %d, not a dcc socket, not anything.", i); close(i); killsock(i); } } else if (xx == -2 && errno != EINTR) { /* select() error */ putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno); for (i = 0; i < dcc_total; i++) { if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno == EBADF)) { putlog(LOG_MISC, "*", "DCC socket %d (type %d, name '%s') expired -- pfft", dcc[i].sock, dcc[i].type, dcc[i].nick); killsock(dcc[i].sock); lostdcc(i); i--; } } } else if (xx == -3) { call_hook(HOOK_IDLE); socket_cleanup = 0; /* If we've been idle, cleanup & flush */ } if (do_restart) { if (do_restart == -2) { rehash(); } else { int f = 1; module_entry *p; Function startfunc; char name[256]; check_tcl_event("prerestart"); /* Unload as many modules as possible */ while (f) { f = 0; for (p = module_list; p != NULL; p = p->next) { dependancy *d = dependancy_list; int ok = 1; while (ok && d) { if (d->needed == p) ok = 0; d = d->next; } if (ok) { strcpy(name, p->name); if (module_unload(name, botnetnick) == NULL) { f = 1; break; } } } } /* Make sure we don't have any modules left hanging around other than * "eggdrop" and the two that are supposed to be. */ for (f = 0, p = module_list; p; p = p->next) { if (strcmp(p->name, "eggdrop") && strcmp(p->name, "encryption") && strcmp(p->name, "uptime")) { f++; } } if (f != 0) { putlog(LOG_MISC, "*", MOD_STAGNANT); } /* Flush log files to disk. */ flushlogs(); /* Clean up Tcl stuff. */ kill_tcl(); /* Initialize stuff again. */ init_tcl(argc, argv); init_language(0); help_init(); traffic_init(); logfile_init(1); /* This resets our modules which we didn't unload (encryption and uptime). */ for (p = module_list; p; p = p->next) { if (p->funcs) { startfunc = p->funcs[MODCALL_START]; startfunc(NULL); } } rehash(); restart_chons(); call_hook(HOOK_LOADED); } do_restart = 0; } } }
/* Got ILL signal. */ static void got_ill(int z) { check_tcl_event("sigill"); }
static void got_quit(int z) { check_tcl_event("sigquit"); putlog(LOG_MISC, "*", "Received QUIT signal (ignoring)."); return; }