/* I/O part of eggdrop: main server communication, startup, etc */ #include #include #include #include #include #include #include #ifdef STOP_UAC #include #include #endif #include #include "eggdrop.h" #ifndef FORGET_UNISTD #include #endif #define msgrate 2 char version[81]="Eggdrop v0.9n (c)1995 Robey Pointer"; char ver[81]="eggdrop v0.9n"; #ifdef BSD char os[]="BSD"; #endif #ifdef LINUX char os[]="Linux"; #endif #ifdef IRIX char os[]="Irix"; #endif #ifdef BSD386 char os[]="BSD/386"; #endif #ifdef HPUX char os[]="HP-UX"; #endif #ifdef AIX char os[]="AIX"; #endif #ifdef SVR4 char os[]="SVR4"; #endif /* 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? */ 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]=""; extern char curchan[]; extern char botchan[]; extern char botname[]; extern char origbotname[]; extern int dcc_total; extern struct dcc_t dcc[]; extern int use_console; extern char dccdir[]; extern char dccin[]; extern int telnet_port; extern char admin[]; extern char gainops[]; extern char notefile[]; extern char newserver[]; 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; int use_stderr=1; int dead_child=0; 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); shutdown(serv,2); } if (helpsock!=-1) { close(helpsock); shutdown(serv,2); } 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_TANDEM) 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); add_mode('+','b',h); flush_mode(); prog_ban(h,time(NULL),sx); if (!enforce_bans) kick_match_since(h,lastmsgtime[which]); lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; 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); } void got_segv() { log(LOG_MISC,"* Last context: %s/%d",cx_file,cx_line); 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() { context; } /* 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); shutdown(serv,2); serv=(-1); } if (helpbot[0]) if (fcntl(helpsock,F_GETFD,0)==-1) { log(LOG_MISC,"Helpbot server expired -- pfft"); close(helpsock); shutdown(helpsock,2); 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); shutdown(dcc[i].sock,2); 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() { context; 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); shutdown(serv,2); serv=(-1); } if (helpbot[0]) if (fcntl(helpsock,F_GETFD,0)<0) { log(LOG_MISC,"* Helpbot socket expired -- pfft"); close(helpsock); shutdown(helpsock,2); helpsock=(-1); } for (i=0; i= 251) && (*p <= 254)) mark=3; if ((*p == 251) || (*p == 253)) { /* "will" X -or- "do" X */ /* response is: won't X */ 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(p,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]=='s') use_console=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(" -s squelch console/log output\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 s1[141],s[121]; int oldserv; context; oldserv=curserv; if (newserverport) { /* jump to specified server */ curserv=(-1); /* reset server list */ strcpy(botserver,newserver); botserverport=newserverport; newserver[0]=0; newserverport=0; oldserv=1; } next_server(&curserv,botserver,&botserverport); serv=(-1); sleep(2); /* let irc-net recover from us */ while ((serv<0) && ((curserv!=oldserv) || (never_give_up))) { log(LOG_CHAN|LOG_MISC,"Attempting connection to %s:%d",botserver, botserverport); alarm(15); /* don't try this for more than 15 seconds */ serv=open_telnet(botserver,botserverport); alarm(0); if (serv<0) { neterror(s); log(LOG_CHAN|LOG_MISC,"Failed connect to %s (%s)", botserver,s); next_server(&curserv,botserver,&botserverport); } else log(LOG_CHAN|LOG_MISC,"Successful connection to %s",botserver); } if ((oldserv==curserv) && (!(never_give_up))) fatal("NO SERVERS WILL ACCEPT MY CONNECTION.",1); tprintf(serv,"USER %s 1 1 :%s\n",botuser,botrealname); tprintf(serv,"NICK %s\n",botname); if (initserver[0]) tprintf(serv,"%s\n",initserver); tprintf(serv,"JOIN %s %s\n",botchan,chankey); } /* connect the helpbot to a server */ void connect_helpbot_server() { char s1[141]; int oldserv; context; oldserv=helpserv; next_server(&helpserv,helpserver,&helpserverport); helpsock=(-1); while (helpsock<0) { alarm(15); helpsock=open_telnet(helpserver,helpserverport); alarm(0); if (helpsock<0) { next_server(&helpserv,helpserver,&helpserverport); } else log(LOG_MISC,"Helpbot -> %s:%d",helpserver,helpserverport); } if (helpbot[0]) { tprintf(helpsock,"USER %s 1 1 :%s\n",botuser,botrealname); tprintf(helpsock,"NICK %s\n",helpbot); tprintf(helpsock,"MODE %s +i-ws\n",helpbot); } } 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],s1[141],from[121],code[520],msg[520],oldserv[121],oldserv1[121]; int timecnt=0,midnite=0,fivemin=0,hourly=0,lastmin=99; int sockl[50]; struct sigaction sv; 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(); cache_miss=0; cache_hit=0; srandom((unsigned short int)time(NULL)); get_first_server(); mtgets(0,NULL,NULL,NULL); getmyhostname(bothost); sprintf(oldserv,"%s:%d",botserver,botserverport); /* move into background? */ if (backgrd) { xx=fork(); if (xx==-1) fatal("CANNOT FORK PROCESS.",0); if (xx!=0) { printf("%s: channel %s, %d users.\n",botname,botchan, count_users(userlist)); printf("Successfully loaded into the background. (pid: %d)\n\n",xx); exit(0); } } use_stderr=0; /* stop writing to stderr now */ log(LOG_ALL,""); log(LOG_ALL,"--- Loading %s (%s)",ver,s); log(LOG_ALL,"=== %s: channel %s, %d users.",botname,botchan, count_users(userlist)); /* redirect output */ if ((backgrd)&&(use_console)) f=freopen("/dev/null","w",stdout); if ((backgrd)&&(use_console)) f=freopen("/dev/null","w",stderr); /* 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,"Failed to find an open telnet port near %d.",telnet_port); telnet_port=0; } } /* 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"); dcc_total++; tprintf(STDOUT,"\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_chatter(STDOUT); } #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(STDOUT,0); tell_mem_status_dcc(STDOUT); tprintf(STDOUT,"\n"); tell_verbose_chan_info(STDOUT); } #ifdef HUNT_ZOMBIES /* check for pending dead children */ if (!dead_child) { pid_t pid; WAIT_T stat; context; pid=waitpid(0,&stat,WNOHANG); 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; 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); } else if (newbotname[0]) { newbotname[0]=0; log(LOG_CHAN|LOG_MISC,"Regained nickname '%s'.",botname); } check_lonely_channel(); 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; } #ifndef NO_IRC check_expired_splits(); check_expired_ignores(); check_expired_bans(); check_for_split(); /* are WE split? */ if (!perm_bans) check_expired_chanbans(); #endif check_expired_dcc(); check_expired_tbufs(); check_for_loops(); /* in the tandem chain */ auto_link_tandem(NULL); /* attempt autolinks */ context; check_expired_forks(); context; #ifdef TCL check_timers(); context; /* 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(); /* send out ctcp awake to itself so server doesn't think it's idle */ mprintf(serv,"PRIVMSG %s :\001AWAKE\001\n",botname); #endif } } else fivemin=0; context; if ((nowtm->tm_hour==0) && (nowtm->tm_min==0)) { /* at midnight */ if (!midnite) { midnite=1; 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==-1) { clear_channel(); curchan[0]=0; connect_server(); } if ((helpbot[0]) && (helpsock==-1)) connect_helpbot_server(); #endif while (dead_child) { got_dead_child(); dead_child--; } /* check for server or dcc activity */ j=0; context; 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,"JOIN")==0) gotjoin(from,msg); else if (strcmp(code,"PART")==0) gotpart(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,"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,"MODE")==0) gotmode(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); shutdown(serv,2); connect_server(); } else if ((helpbot[0]) && (i==helpsock)) { /* helpbot vanished */ close(helpsock); shutdown(helpsock,2); 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); shutdown(serv,2); serv=(-1); } if (helpbot[0]) if (fcntl(helpsock,F_GETFD,0)==-1) { log(LOG_MISC,"Helpbot server socket expired -- pfft"); close(helpsock); shutdown(helpsock,2); helpsock=(-1); } for (i=0; i