/* main.c -- handles: changing nicknames when the desired nick is in use flood detection signal handling telnet code translation command line arguments connecting to a server (bot and helpbot) interpreting server responses (main loop) dprintf'ized, 15nov95 */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #ifdef STOP_UAC /* osf/1 complains a lot */ # include # define UAC_NOPRINT 0x00000001 /* Don't report unaligned fixups */ #else # include /* osf/1 ALSO doesn't like sys/wait.h */ #endif /* some systems have a working sys/wait.h even though configure will */ /* decide it's not bsd compatable. oh well. */ #include "eggdrop.h" #include "proto.h" #ifndef WNOHANG /* probably osf/1 again */ #define WNOHANG 1 #endif /* number of seconds to wait between transmitting queued lines to the server */ #define msgrate 2 /* If you're going to modify the following lines, please don't make up weird shit. Keep the "eggdrop" part and the version number, and add your own customized version info afterwards. That way we can still tell what your modifications were based on, and you don't look like an idiot (ie, "eggdrop eswk!" etc) */ char version[81]="Eggdrop v0.9s (c)1996 Robey Pointer"; char ver[21]="eggdrop v0.9s"; /* socket that the server is on */ int serv=(-1); /* run in the background? */ int backgrd=1; /* successful connect yet? */ int online=0; /* hide parameters in ps list? (doesn't work) */ int hide_param=0; /* foreground: constantly display channel stats? */ int con_chan=0; /* foreground: use the terminal as a party line? */ int term_z=0; /* bot's username */ char botuser[21]; /* bot's real name field */ char botrealname[121]; /* our current host */ char bothost[121]; /* our server */ char botserver[121]; /* port # to connect to */ int botserverport=6667; /* name of the config file */ char configfile[121]="egg.config"; /* temporary thing for nick changes */ char newbotname[10]; /* nickname of the helpbot */ char helpbot[21]; /* socket of the helpbot, if used: */ int helpsock=(-1); /* current position in server list: */ int curserv=0; /* current position in server list of helpbot: */ int helpserv=0; /* current helpbot server: */ char helpserver[121]; /* current helpbot server port: */ int helpserverport=6667; /* directory of help files (if used) */ char helpdir[121]; /* directory for text files that get dumped */ char textdir[121]=""; /* # of msgs per min that's a flood */ int flood_thr=5; /* # of publics per min that's a flood */ int flood_pub_thr=10; /* # of joins per min that's a flood */ int flood_join_thr=5; /* what, if anything, to send to the server on connection */ char initserver[121]; /* never erase logfiles, no matter how old they are? */ int keep_all_logs=0; /* context storage for fatal crashes */ char cx_file[30]; int cx_line; /* show channel update line every 5 mins */ int chan_updates=1; /* unix-time that the bot loaded up */ time_t online_since; /* bot's user@host (refreshed whenever the bot joins a channel) */ /* may not be correct user@host BUT it's how the server sees it */ char botuserhost[121]; /* helpbot has returned a ping recently */ int gothelpping=1; /* using bot in make-userfile mode? (first user to 'hello' becomes master) */ int make_userfile=0; /* never give up when connecting to servers? */ int never_give_up=0; /* permanent owner(s) of the bot */ char owner[121]=""; /* keep trying to regain my intended nickname? */ int keepnick=1; /* set when i send a CTCP AWAKE to myself, cleared when i get it */ int waiting_for_awake=0; /* name of the file for the pid to be stored in */ char pid_file[40]; /* static buffer used by various functions */ char SBUF[1024]; extern char curchan[]; extern char botchan[]; extern char botname[]; extern char origbotname[]; extern int dcc_total; extern struct dcc_t dcc[]; extern char dccdir[]; extern char dccin[]; extern int telnet_port; extern char admin[]; extern char notefile[]; extern char newserver[]; extern char newserverpass[]; extern int newserverport; extern int lastsock; extern int enforce_bans; extern int chankey[]; extern char *logfile[]; extern int conmask; extern int perm_bans; extern struct userrec *userlist; extern int cache_hit,cache_miss; extern char userfile[]; /* send stuff to stderr instead of logfiles? */ int use_stderr=1; int dead_child=0; /* used for mtgets */ #define SOCK_BINARY 1 #define SOCK_LISTEN 2 void fatal(s,recoverable) char *s; int recoverable; { int i; log(LOG_MISC,"* %s",s); if (use_stderr) tprintf(STDERR,"* %s\n",s); if (serv!=-1) close(serv); if (helpsock!=-1) close(helpsock); for (i=0; i (raw stuff from server), pull off who it's from & the code */ void parsemsg(in,from,code,params) char *in,*from,*code,*params; { char *p; from[0]=0; if (in[0]==':') { strcpy(in,&in[1]); p=strchr(in,' '); if (p==NULL) { from[0]=params[0]=0; strcpy(code,in); return; } strcpy(params,p+1); *p=0; strcpy(from,in); *p=' '; p++; strcpy(in,p); } p=strchr(in,' '); if (p==NULL) { strcpy(code,in); params[0]=0; return; } *p=0; strcpy(code,in); *p=' '; strcpy(params,p+1); } /* 433 : nickname in use */ /* change nicks till we're acceptable or we give up */ void got433(from,msg) char *from,*msg; { char c,*oknicks="^-_\\[]`",*p; context; /* could be futile attempt to regain nick: */ if (newbotname[0]) { tprintf(serv,"NICK %s\n",newbotname); strcpy(botname,newbotname); newbotname[0]=0; return; } c=botname[strlen(botname)-1]; p=strchr(oknicks,c); if (((c>='0') && (c<='9')) || (p!=NULL)) { if (p==NULL) { if (c=='9') botname[strlen(botname)-1]=oknicks[0]; else botname[strlen(botname)-1]=c+1; } else { p++; if (p==NULL) fatal("COULDN'T FIND A SUITABLE NICKNAME.",1); botname[strlen(botname)-1]=(*p); } log(LOG_MISC,"NICK IN USE: Trying '%s'",botname); } else { if (strlen(botname)==9) botname[strlen(botname)-1]='0'; else { botname[strlen(botname)+1]=0; botname[strlen(botname)]='0'; } log(LOG_MISC,"NICK IN USE: Trying '%s'",botname); } tprintf(serv,"NICK %s\n",botname); } int lastmsgs[5]={ 0,0,0,0,0 }; char lastmsghost[5][81]={ "","","","","" }; time_t lastmsgtime[5]={ 0L,0L,0L,0L,0L }; /* do on NICK, PRIVMSG, and NOTICE -- and JOIN */ int detect_flood(from,which,tochan) char *from; int which,tochan; { char *p; time_t t; char h[121]; int thr=flood_thr; char me[121]; if (get_attr_host(from)&(USER_BOT|USER_MASTER)) return 0; strcpy(me,botuserhost); splitc(NULL,me,'@'); /* determine how many are necessary to make a flood */ if (((which==_PRIVMSG) || (which==_NOTICE)) && (tochan)) thr=flood_pub_thr; if (which==_JOIN) thr=flood_join_thr; p=strchr(from,'!'); if (p!=NULL) { p++; p=strchr(p,'@'); } if (p!=NULL) { p++; t=time(NULL); if (strcasecmp(p,me)==0) return 0; /* don't flood check self */ if (strcasecmp(lastmsghost[which],p)!=0) { /* new */ strcpy(lastmsghost[which],p); lastmsgtime[which]=t; lastmsgs[which]=0; } else { /* old */ if (lastmsgtime[which] < t-60) { lastmsgtime[which]=t; lastmsgs[which]=0; } else { lastmsgs[which]++; if (lastmsgs[which]>=thr) { /* FLOOD */ if (((which==_PRIVMSG) || (which==_NOTICE)) && (!tochan)) { /* private msg */ sprintf(h,"*!*@%s",p); lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; log(LOG_MISC,"Flood from @%s! Placing on ignore!",p); prog_ignore(h,time(NULL)); return 1; } else if (which==_CTCP) { /* ctcp flood! */ sprintf(h,"*!*@%s",p); lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; log(LOG_MISC, "CTCP flood from @%s! Placing on ignore and kicking!",p); prog_ignore(h,time(NULL)); p=strchr(from,'!'); if (p!=NULL) { *p=0; tprintf(serv,"KICK %s %s :CTCP flood\n",curchan,from); *p='!'; } return 1; } else if (which==_JOIN) { /* join flood */ char sx[21]; sprintf(h,"*!*@%s",p); strcpy(sx,"join flood"); log(LOG_MISC|LOG_CHAN,"Join flood from @%s! Banning...",p); if (!isbanned(h)) { add_mode('+','b',h); flush_mode(); } lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; if (match_ban(from)) return 1; /* already banned */ prog_ban(h,time(NULL),sx); if (!enforce_bans) kick_match_since(h,lastmsgtime[which]); return 1; } else { /* flooding chan! either by public, notice, or nick */ lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; p=strchr(from,'!'); if (p!=NULL) { log(LOG_CHAN,"Channel flood from %s -- kicking",from); *p=0; tprintf(serv,"KICK %s %s :flood\n",curchan,from); *p='!'; return 1; } } } } } } return 0; } void got_bus() { log(LOG_MISC,"* Last context: %s/%d",cx_file,cx_line); fatal("BUS ERROR -- CRASHING!",1); } extern int _lastret,_lastsock,_lastflag; void got_segv() { int x; log(LOG_MISC,"* Last context: %s/%d",cx_file,cx_line); x=creat("DEBUG",0644); if (x<0) { log(LOG_MISC,"* Failed to write DEBUG"); } else { tell_dcc(-x); close(x); log(LOG_MISC,"* Wrote DEBUG"); } fatal("SEGMENT VIOLATION -- CRASHING!",1); } void got_term() { #ifdef DIE_ON_TERMHUP write_userfile(); tprintf(serv,"QUIT :terminate signal\n"); fatal("TERMINATE SIGNAL -- SIGNING OFF"); #else log(LOG_MISC,"RECEIVED TERMINATE SIGNAL (IGNORING)"); write_userfile(); return; #endif } void got_quit() { log(LOG_MISC,"RECEIVED QUIT SIGNAL (IGNORING)"); return; } void got_hup() { #ifdef DIE_ON_TERMHUP write_userfile(); tprintf(serv,"QUIT :hangup signal\n"); fatal("HANGUP SIGNAL -- SIGNING OFF"); #else log(LOG_MISC,"Received HUP signal: rehashing..."); rehash(); return; #endif } void got_alarm() { /* connection to a server was ended prematurely */ return; } /* void got_pipe() { int i,ok=0; static time_t last=0L; static int recur=0,cnt=0; if (recur) fatal("* Recursive pipe fault!",0); recur=1; if (time(NULL)==last) { cnt++; if (cnt>5) fatal("* >5 pipe faults per second!",0); } else { last=time(NULL); cnt=0; } log(LOG_MISC,"* Pipe fault; recovering."); log(LOG_MISC,"Last context: %s/%d",cx_file,cx_line); if (fcntl(serv,F_GETFD,0)==-1) { log(LOG_MISC,"Server socket expired -- pfft"); close(serv); serv=(-1); } if (helpbot[0]) if (fcntl(helpsock,F_GETFD,0)==-1) { log(LOG_MISC,"Helpbot server expired -- pfft"); close(helpsock); helpsock=(-1); } for (i=0; i=0) && (dcc[i].type!=DCC_LOST)) if (fcntl(dcc[i].sock,F_GETFD,0)==-1) { log(LOG_MISC,"DCC socket %d expired -- pfft",dcc[i].sock); close(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; } recur=0; } */ void got_tterr() { log(LOG_MISC,"ATTEMPTED READ/WRITE TTY CONSOLE FROM BACKGROUND"); log(LOG_MISC,"Notify Robey of this error! It's a major goof!"); return; } void got_child() { dead_child++; } void got_usr1() { int x,i; log(LOG_MISC,"* USER1 SIGNAL: Debugging sockets"); x=creat("DEBUG",0644); if (x<0) { log(LOG_MISC,"* Failed to write DEBUG"); return; } tell_dcc(-x); tprintf(x,"\n"); tprintf(x,"SERVER %s:%d, SOCK %d\n",botserver,botserverport,serv); if (helpbot[0]) tprintf(x,"HELPSERVER %s:%d, SOCK %d\n",helpserver,helpserverport, helpsock); if (fcntl(serv,F_GETFD,0)<0) { log(LOG_MISC,"* Server socket expired -- pfft"); close(serv); serv=(-1); } if (helpbot[0]) if (fcntl(helpsock,F_GETFD,0)<0) { log(LOG_MISC,"* Helpbot socket expired -- pfft"); close(helpsock); helpsock=(-1); } for (i=0; i= 251) && (*(p+1) <= 254)) mark=3; strcpy(p,p+mark); } } } void strip_telnet(sock,buf,len) int sock,*len; char *buf; { unsigned char *p=(unsigned char *)buf; int mark; while (*p != 0) { while ((*p != 255) && (*p != 0)) p++; /* search for IAC */ if (*p == 255) { p++; mark=2; if ((*p >= 251) && (*p <= 254)) mark=3; if ((*p == 251) || (*p == 253)) { /* "will" X -or- "do" X */ /* response is: won't X */ if (!((*p == 253) && (*(p+1) == 1))) /* don't react to DO ECHO */ write(sock,"\0377\0374",2); write(sock,p+1,1); } if (*p == 246) { /* "are you there?" */ /* response is: "hell yes!" */ write(sock,"\r\nHell, yes!\r\n",14); } /* anything else can probably be ignored */ p--; strcpy((char *)p,(char *)(p+mark)); /* wipe code from buffer */ *len = *len - mark; } } } void do_arg(s) char *s; { int i; if (s[0]=='-') for (i=1; i < strlen(s); i++) { if (s[i]=='n') backgrd=0; if (s[i]=='c') { con_chan=1; term_z=0; } if (s[i]=='t') { con_chan=0; term_z=1; } if (s[i]=='m') make_userfile=1; if (s[i]=='h') { #ifdef TCL printf("\n%s\n\n",version); #else printf("\n%s (non-Tcl)\n\n",version); #endif printf("Command line arguments:\n"); printf(" -h help\n"); printf(" -n don't go into the background\n"); printf(" -c (with -n) display channel stats every 10 seconds\n"); printf(" -t (with -n) use terminal to simulate dcc-chat\n"); printf(" -m userfile creation mode\n"); printf(" optional config filename (default 'egg.config')\n"); printf("\n"); exit(0); } } else strcpy(configfile,s); } /* hook up to a server */ void connect_server() { char s[121],pass[121]; static int oldserv=(-1); context; waiting_for_awake=0; if ((oldserv<0) || (never_give_up)) oldserv=curserv; /* start up the counter (always reset it if "never-give-up" is on) */ 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; oldserv=(-1); } next_server(&curserv,botserver,&botserverport,pass); serv=(-1); /* sleep(2); */ log(LOG_CHAN|LOG_MISC,"Attempting connection to %s:%d",botserver, botserverport); alarm(WAIT_CONNECT_SERVER); /* don't try this for more than 15 seconds */ serv=open_telnet(botserver,botserverport); alarm(0); if (serv<0) { if (serv==(-2)) strcpy(s,"DNS lookup failed"); else neterror(s); log(LOG_CHAN|LOG_MISC,"Failed connect to %s (%s)",botserver,s); if ((oldserv==curserv) && !(never_give_up)) fatal("NO SERVERS WILL ACCEPT MY CONNECTION.",1); } else { log(LOG_CHAN|LOG_MISC,"Successful connection to %s",botserver); tprintf(serv,"NICK %s\n",botname); oldserv=(-1); if (pass[0]) tprintf(serv,"PASS %s\n",pass); tprintf(serv,"USER %s %s %s :%s\n",botuser,bothost,botserver,botrealname); #ifdef TCL if (initserver[0]) do_tcl("init-server",initserver); #else if (initserver[0]) tprintf(serv,"%s\n",initserver); #endif tprintf(serv,"JOIN %s %s\n",botchan,chankey); } } /* connect the helpbot to a server */ void connect_helpbot_server() { char pass[121]; int oldserv; context; oldserv=helpserv; next_server(&helpserv,helpserver,&helpserverport,pass); helpsock=(-1); while (helpsock<0) { alarm(15); helpsock=open_telnet(helpserver,helpserverport); alarm(0); if (helpsock<0) { next_server(&helpserv,helpserver,&helpserverport,pass); } else log(LOG_MISC,"Helpbot -> %s:%d",helpserver,helpserverport); } if (helpbot[0]) { tprintf(helpsock,"NICK %s\n",helpbot); if (pass[0]) tprintf(helpsock,"PASS %s\n",pass); tprintf(helpsock,"USER %s %s %s :%s\n",botuser,bothost,botserver, botrealname); tprintf(helpsock,"MODE %s +i-ws\n",helpbot); } } int main(argc,argv) int argc; char **argv; { int xx,i,j; char buf[520]; time_t now,then; struct tm *nowtm; FILE *f; char s[520],from[121],code[520],msg[520]; struct sigaction sv; int timecnt=0,midnite=0,fivemin=0,hourly=0,lastmin=99; int sockl[50],flagl[50]; context; #ifdef STOP_UAC { int nvpair[2]; nvpair[0]=SSIN_UACPROC; nvpair[1]=UAC_NOPRINT; setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0); } #endif if (argc>1) for (i=1; itm_min; init_mem(); init_misc(); #ifdef TCL init_tcl(); #endif init_channel(); chanprog(); context; cache_miss=0; cache_hit=0; srandom((unsigned short int)time(NULL)); getmyhostname(bothost); sprintf(botuserhost,"%s@%s",botuser,bothost); /* wishful thinking */ get_first_server(); mtgets(0,NULL,NULL,NULL,NULL); sprintf(pid_file,"pid.%s",origbotname); /* check for pre-existing eggdrop! */ f=fopen(pid_file,"r"); if (f!=NULL) { fgets(s,10,f); xx=atoi(s); kill(xx,SIGWINCH); /* meaningless kill to determine if pid is used */ if (errno!=ESRCH) { printf("I detect %s already running from this directory.\n",origbotname); printf("If this is incorrect, erase the '%s' file.\n\n",pid_file); exit(1); } } i=count_users(userlist); use_stderr=0; log(LOG_ALL,""); log(LOG_ALL,"--- Loading %s (%s)",ver,s); log(LOG_ALL,"=== %s: channel %s, %d users.",botname,botchan,i); use_stderr=1; printf("%s: channel %s, %d users.\n",botname,botchan,i); /* set up telnet listen if necessary */ i=0; if (telnet_port) { j=telnet_port+20; while ((telnet_port0) { int n=dcc_total; dcc[n].addr=getmyip(); dcc[n].port=telnet_port; dcc[n].sock=i; dcc[n].type=DCC_TELNET; dcc[n].u.other=NULL; strcpy(dcc[n].nick,"TELNET"); getmyhostname(dcc[n].host); dcc_total++; } else telnet_port++; } if (i>0) log(LOG_MISC,"Listening at telnet port %d",telnet_port); else { log(LOG_MISC,"Couldn't find telnet port near %d.",telnet_port); telnet_port=0; } } /* move into background? */ if (backgrd) { xx=fork(); if (xx==-1) fatal("CANNOT FORK PROCESS.",0); if (xx!=0) { FILE *fp; printf("Moved into the background (pid: %d)\n\n",xx); /* write pid to file */ unlink(pid_file); fp=fopen(pid_file,"w"); if (fp!=NULL) { fprintf(fp,"%u\n",xx); fclose(fp); } exit(0); } } use_stderr=0; /* stop writing to stderr now */ /* redirect output */ if (backgrd) { f=freopen("/dev/null","w",stdout); f=freopen("/dev/null","w",stderr); } /* terminal emulating dcc chat */ if ((!backgrd) && (term_z)) { int n=dcc_total; dcc[n].addr=getmyip(); dcc[n].port=0; dcc[n].sock=STDOUT; dcc[n].type=DCC_CHAT; set_chat(n); dcc[n].u.chat->away=NULL; dcc[n].u.chat->status=STAT_MASTER; dcc[n].u.chat->timer=time(NULL); dcc[n].u.chat->msgs_per_sec=0; dcc[n].u.chat->con_flags=conmask; dcc[n].u.chat->channel=0; strcpy(dcc[n].nick,"HQ"); strcpy(dcc[n].host,"local console"); dprintf(n,"\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_chatter(n); dcc_total++; } #ifndef NO_IRC /* now connect to a server: */ newserver[0]=0; newserverport=0; connect_server(); /* connect helpbot if applicable */ if (helpbot[0]) connect_helpbot_server(); if (helpbot[0]) log(LOG_MISC,"Helpbot '%s' online to %s:%d",helpbot,helpserver, helpserverport); #else /* initialize irc things so they won't bother us */ serv=(-1); helpbot[0]=0; dccdir[0]=0; strcpy(curchan,botchan); strcpy(botname,origbotname); #endif then=time(NULL); online_since=time(NULL); auto_link_tandem(NULL); /* hurry and connect to tandem bots */ while(1) { context; now=time(NULL); if (now!=then) { /* once a second */ static int cnt=0; context; timecnt++; /* time to dequeue a msg? */ if (timecnt==msgrate) { deq_msg(); deq_helpmsg(); timecnt=0; } cnt++; if (cnt>=10) { /* every 10 seconds */ cnt=0; if ((con_chan) && (!backgrd)) { tprintf(STDOUT,"%c[2J%c[1;1H",27,27); tell_verbose_status(-1,0); /* stdout */ tell_mem_status_dcc(-1); /* stdout */ tprintf(STDOUT,"\n"); tell_verbose_chan_info(-1); /* stdout */ } #ifdef HUNT_ZOMBIES /* check for pending dead children */ if (!dead_child) { pid_t pid; wait_t stat; context; #if HAVE_WAITPID pid=waitpid(0,&stat,WNOHANG); #else pid=wait3(&stat,WNOHANG,NULL); #endif if (pid>0) got_dead_child2(pid,stat); } context; #endif } if ((!online) && (now-online_since >= 60)) online=1; } nowtm=localtime(&now); then=now; if ((online) && (nowtm->tm_min != lastmin)) { /* once a minute */ context; lastmin=(lastmin+1)%60; #ifndef NO_IRC check_lonely_channel(); if (keepnick) { if (strcmp(botname,origbotname)!=0) { /* if i'm not using my intended nickname, try to recapture it */ strcpy(newbotname,botname); strcpy(botname,origbotname); tprintf(serv,"NICK %s\n",botname); waiting_for_awake=0; } else if (newbotname[0]) { newbotname[0]=0; waiting_for_awake=0; log(LOG_CHAN|LOG_MISC,"Regained nickname '%s'.",botname); } } check_idle_kick(); if (strcasecmp(botchan,curchan)!=0) { /* not on our channel... so re-join */ if (curchan[0]) tprintf(serv,"PART %s\n",curchan); tprintf(serv,"JOIN %s %s\n",botchan,chankey); } if (!gothelpping) { /* lost track of help bot : make it change servers */ tprintf(helpsock,"QUIT :zarrf!\n"); close(helpsock); helpsock=(-1); gothelpping=1; log(LOG_MISC,"Helpbot AWOL; moving it"); } else if (helpbot[0]) { /* ping it again */ tprintf(serv,"PRIVMSG %s :\001PING 69\001\n",helpbot); gothelpping=0; } check_expired_splits(); check_expired_ignores(); check_expired_bans(); check_for_split(); /* am *I* split? */ if (!perm_bans) check_expired_chanbans(); #endif /* ifndef NO_IRC */ check_expired_dcc(); check_expired_tbufs(); #ifndef SLOW_PING check_botnet_pings(); #endif auto_link_tandem(NULL); /* attempt autolinks */ check_expired_forks(); #ifdef TCL check_timers(); /* in case for some reason more than 1 min has passed: */ i=0; while (nowtm->tm_min!=lastmin) { /* timer drift, dammit */ check_timers(); i++; lastmin=(lastmin+1)%60; } if (i>1) log(LOG_MISC,"(!) timer drift -- spun %d minutes",i); #endif } context; if (((int)(nowtm->tm_min/5)*5) == (nowtm->tm_min)) { /* 5 min */ if (!fivemin) { fivemin=1; #ifndef NO_IRC if (chan_updates) log_chan(); #ifdef CHECK_STONED if (waiting_for_awake) { /* uh oh! never got ctcp awake from last time, five minutes ago! */ /* server is probably stoned */ close(serv); serv=(-1); /* will reconnect about 50 lines down */ log(LOG_MISC,"Server got stoned; jumping..."); } else { /* send out ctcp awake to itself so server doesn't think it's idle */ mprintf(serv,"PRIVMSG %s :\001AWAKE\001\n",botname); mprintf(serv,"PRIVMSG h%c4x0r%c :hello?\n",(random()/16)%26+'a', (random()/16)%26+'a'); if (newbotname[0]) { mprintf(serv,"PRIVMSG %s :\001AWAKE\001\n",newbotname); mprintf(serv,"PRIVMSG h%c4x0r%c :hello?\n",(random()/16)%26+'a', (random()/16)%26+'a'); /* just in case we tried to change nicks and it's gonna fail */ } waiting_for_awake=1; /* just in case server is zoning out */ } #else mprintf(serv,"PRIVMSG %s :\001AWAKE\001\n",botname); #endif /* CHECK_STONED */ #endif /* !NO_IRC */ #ifdef SLOW_PING check_botnet_pings(); #endif } } else fivemin=0; context; if ((nowtm->tm_hour==0) && (nowtm->tm_min==0)) { /* at midnight */ if (!midnite) { midnite=1; log(LOG_MISC,"Backing up user file..."); strcpy(s,userfile); strcat(s,"~bak"); copyfile(userfile,s); log(LOG_MISC,"Switching logfiles..."); for (i=0; itm_min==0) { /* hourly! */ if (!hourly) { hourly=1; write_userfile(); } } else hourly=0; context; #ifndef NO_IRC if (serv<0) { clear_channel(); curchan[0]=0; connect_server(); } if ((helpbot[0]) && (helpsock==-1)) connect_helpbot_server(); context; #endif while (dead_child) { got_dead_child(); dead_child--; } /* clean up sockets that were just left for dead */ for (i=0; i0) { /* non-error */ context; #ifdef NO_IRC dcc_activity(xx,buf,i); #else if (xx==helpsock) helpbot_activity(buf); else if (xx!=serv) dcc_activity(xx,buf,i); else { /* SERVER ACTIVITY */ context; strcpy(s,buf); context; parsemsg(buf,from,code,msg); fixfrom(from); #ifdef USE_CONSOLE_R if ((strcmp(code,"PRIVMSG")==0) || (strcmp(code,"NOTICE")==0)) { if (!match_ignore(from)) { log(LOG_RAW,"[@] %s",s); #ifdef TCL check_tcl_raw(s); #endif } } else { log(LOG_RAW,"[@] %s",s); #ifdef TCL check_tcl_raw(s); #endif } #endif if (strcmp(code,"PRIVMSG")==0) { if (!match_ignore(from)) gotmsg(from,msg); } else if (strcmp(code,"NOTICE")==0) { if (!match_ignore(from)) gotnotice(from,msg); } else if (strcmp(code,"MODE")==0) gotmode(from,msg); else if (strcmp(code,"JOIN")==0) gotjoin(from,msg); else if (strcmp(code,"PART")==0) gotpart(from,msg); else if (strcmp(code,"ERROR")==0) goterror(from,msg); else if (strcmp(code,"251")==0) got251(from,msg); else if (strcmp(code,"315")==0) got315(from,msg); else if (strcmp(code,"324")==0) got324(from,msg); else if (strcmp(code,"331")==0) got331(from,msg); else if (strcmp(code,"332")==0) got332(from,msg); else if (strcmp(code,"352")==0) got352(from,msg); else if (strcmp(code,"367")==0) got367(from,msg); else if (strcmp(code,"368")==0) got368(from,msg); else if (strcmp(code,"433")==0) got433(from,msg); else if (strcmp(code,"471")==0) got471(from,msg); else if (strcmp(code,"473")==0) got473(from,msg); else if (strcmp(code,"474")==0) got474(from,msg); else if (strcmp(code,"475")==0) got475(from,msg); else if (strcmp(code,"QUIT")==0) gotquit(from,msg); else if (strcmp(code,"NICK")==0) { gotnick(from,msg); detect_flood(from,_NICK,1); } else if (strcmp(code,"KICK")==0) gotkick(from,msg); else if (strcmp(code,"INVITE")==0) gotinvite(from,msg); else if ((strcmp(code,"375")==0) || (strcmp(code,"376")==0) || (strcmp(code,"372")==0)) ; /* ignore motd */ else if (strcmp(code,"TOPIC")==0) gottopic(from,msg); else if (strcmp(code,"PING")==0) { fixcolon(msg); tprintf(serv,"PONG :%s\n",msg); } } flush_mode(); /* dump all mode changes */ #endif /* NO_IRC */ } else if (xx==-1) { /* EOF from someone */ context; #ifdef NO_IRC if (i!=STDOUT) eof_dcc(i); else fatal("END OF FILE ON TERMINAL",1); #else if (i==serv) { /* we lost this server, dammit */ log(LOG_MISC|LOG_CHAN,"Disconnected from %s",botserver); clear_channel(); curchan[0]=0; /* we're not on a channel any more */ close(serv); connect_server(); } else if ((helpbot[0]) && (i==helpsock)) { /* helpbot vanished */ close(helpsock); connect_helpbot_server(); } else if (i!=STDOUT) eof_dcc(i); else fatal("END OF FILE ON TERMINAL",1); #endif } else if ((xx==-2) && (errno!=EINTR)) { /* select() error */ context; log(LOG_MISC,"* Socket error #%d; recovering.",errno); if (fcntl(serv,F_GETFD,0)==(-1)) { log(LOG_MISC,"Server socket expired -- pfft"); close(serv); serv=(-1); } if (helpbot[0]) if (fcntl(helpsock,F_GETFD,0)==(-1)) { log(LOG_MISC,"Helpbot server socket expired -- pfft"); close(helpsock); helpsock=(-1); } for (i=0; i