/* 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 */ #endif /* some systems have a working sys/wait.h even though configure will */ /* decide it's not bsd compatable. oh well. */ #include "../lush.h" #include "eggdrop.h" #include "chan.h" #include "proto.h" /* 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). Also please read the README file regarding your rights to distribute modified versions of this bot. */ char version[81]="Eggdrop v1.0c (c)1996 Robey Pointer"; char ver[41]="eggdrop v1.0c"; char egg_version[81]="1.0c 1030"; /* 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; /* trying to connect to a server right now? */ time_t trying_server=0L; /* 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]; /* current position in server list: */ int curserv=0; /* 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; /* 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]; /* 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]; /* how many minutes past the hour to save the userfile? */ int save_users_at=0; /* when (military time) to switch logfiles */ int switch_logfiles_at=300; /* static buffer used by various functions */ char SBUF[1024]; 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 char *logfile[]; extern char *logchan[]; extern int conmask; extern struct userrec *userlist; extern int cache_hit,cache_miss; extern char userfile[]; extern struct chanset_t *chanset; /* send stuff to stderr instead of logfiles? */ int use_stderr=1; void fatal(s,recoverable) char *s; int recoverable; { int i; putlog(LOG_MISC,"*","* %s",s); if (use_stderr) tprintf(STDERR,"* %s\n",s); if (serv!=-1) killsock(serv); 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); } /* 303 : ison */ void got303(from,msg) char *from,*msg; { context; split(NULL,msg); fixcolon(msg); waiting_for_awake=0; if (newbotname[0]) { /* check if nick change worked */ if (strcasecmp(botname,msg)==0) { putlog(LOG_MISC,"*","Regained nickname '%s'.",botname); newbotname[0]=0; } } } /* 432 : bad nickname */ void got432(from,msg) char *from,*msg; { context; putlog(LOG_MISC,"*","Server says my nickname is invalid."); putlog(LOG_MISC,"*","SWITCHING TO TEMPORARY NICK 'fucked' -- PLEASE FIX!"); strcpy(botname,"fucked"); newbotname[0]=0; tprintf(serv,"NICK fucked\n"); } /* 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); } putlog(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'; } putlog(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,chan,which,tochan) char *from; int which,tochan; struct chanset_t *chan; { char *p; time_t t; char h[UHOSTLEN],floodnick[NICKLEN]; int thr=flood_thr; if (get_attr_host(from)&(USER_BOT|USER_MASTER)) return 0; /* determine how many are necessary to make a flood */ if (((which==FLOOD_PRIVMSG) || (which==FLOOD_NOTICE)) && (tochan)) thr=flood_pub_thr; if ((which==FLOOD_JOIN) || (which==FLOOD_NICK)) thr=flood_join_thr; if (thr==0) return 0; /* no flood protection */ /* okay, make sure i'm not flood-checking myself */ strcpy(h,from); splitnick(floodnick,h); if (newbotname[0]) { if (strcasecmp(floodnick,newbotname)==0) return 0; } else if (strcasecmp(floodnick,botname)==0) return 0; if (strcasecmp(h,botuserhost)==0) return 0; /* my user@host (?) */ p=strchr(from,'!'); if (p!=NULL) { p++; p=strchr(p,'@'); } if (p!=NULL) { p++; t=time(NULL); 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==FLOOD_PRIVMSG) || (which==FLOOD_NOTICE)) && (!tochan)) { /* private msg */ sprintf(h,"*!*@%s",p); lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; putlog(LOG_MISC,"*","Flood from @%s! Placing on ignore!",p); prog_ignore(h,time(NULL),origbotname); return 1; } else if (which==FLOOD_CTCP) { /* ctcp flood! */ sprintf(h,"*!*@%s",p); lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; putlog(LOG_MISC,"*","CTCP flood from @%s! Placing on ignore!",p); prog_ignore(h,time(NULL),origbotname); return 1; } else if (which==FLOOD_JOIN) { /* join flood */ char sx[21]; sprintf(h,"*!*@%s",p); strcpy(sx,"join flood"); if (!isbanned(chan,h)) { add_mode(chan,'+','b',h); flush_mode(chan); } lastmsgs[which]=0; lastmsgtime[which]=0; lastmsghost[which][0]=0; if ((match_ban(from)) || (u_match_ban(chan->bans,from))) return 1; /* already banned */ putlog(LOG_MISC|LOG_JOIN,chan->name, "Join flood from @%s! Banning...",p); u_prog_ban(chan->bans,h,time(NULL),sx); if (!(chan->stat&CHAN_ENFORCEBANS)) kick_match_since(chan,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) { putlog(LOG_MODES,chan->name,"Channel flood from %s -- kicking", from); *p=0; mprintf(serv,"KICK %s %s :flood\n",chan->name,from); *p='!'; return 1; } } } } } } return 0; } void got_bus() { putlog(LOG_MISC,"*","* Last context: %s/%d",cx_file,cx_line); fatal("BUS ERROR -- CRASHING!",1); } void got_segv() { int x; putlog(LOG_MISC,"*","* Last context: %s/%d",cx_file,cx_line); x=creat("DEBUG",0644); setsock(x,SOCK_NONSOCK); if (x<0) { putlog(LOG_MISC,"*","* Failed to write DEBUG"); } else { tell_dcc(-x); close(x); putlog(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 putlog(LOG_MISC,"*","RECEIVED TERMINATE SIGNAL (IGNORING)"); write_userfile(); return; #endif } void got_quit() { putlog(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 putlog(LOG_MISC,"*","Received HUP signal: rehashing..."); rehash(); return; #endif } void got_alarm() { /* connection to a server was ended prematurely */ return; } void got_usr1() { int x,i; putlog(LOG_MISC,"*","* USER1 SIGNAL: Debugging sockets"); x=creat("DEBUG",0644); setsock(x,SOCK_NONSOCK); if (x<0) { putlog(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 (fcntl(serv,F_GETFD,0)<0) { putlog(LOG_MISC,"*","* Server socket expired -- pfft"); killsock(serv); serv=(-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 change_telnet_port() { int i,j,idx=(-1); /* find old entry if it exists */ for (i=0; i= MAXDCC) { putlog(LOG_MISC,"*","No more DCC slots available: can't open telnet port"); return; } idx=dcc_total; dcc[idx].addr=getmyip(); dcc[idx].type=DCC_TELNET; dcc[idx].u.other=NULL; strcpy(dcc[idx].nick,"(telnet)"); getmyhostname(dcc[idx].host); dcc_total++; } else { /* already an entry */ if (!telnet_port) { killsock(dcc[idx].sock); lostdcc(idx); putlog(LOG_MISC,"*","No longer listening at a telnet port."); return; } } j=telnet_port+20; i=0; while ((telnet_port0) { dcc[idx].port=telnet_port; dcc[idx].sock=i; putlog(LOG_MISC,"*","Listening at telnet port %d",telnet_port); return; } putlog(LOG_MISC,"*","Couldn't find telnet port near %d.",telnet_port); telnet_port=0; lostdcc(idx); } 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]=='v') { printf("%s\n",version); exit(0); } if (s[i]=='h') { printf("\n%s\n\n",version); printf("Command line arguments:\n"); printf(" -h help\n"); printf(" -v print version and exit\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 */ /* works a little differently now... async i/o is your friend */ void connect_server() { char s[121],pass[121]; static int oldserv=(-1); struct chanset_t *chan; context; waiting_for_awake=0; trying_server=time(NULL); 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); putlog(LOG_SERV,"*","Trying server %s:%d",botserver, botserverport); serv=open_telnet(botserver,botserverport); if (serv<0) { if (serv==(-2)) strcpy(s,"DNS lookup failed"); else neterror(s); putlog(LOG_SERV,"*","Failed connect to %s (%s)",botserver,s); if ((oldserv==curserv) && !(never_give_up)) fatal("NO SERVERS WILL ACCEPT MY CONNECTION.",1); } else { /* queue standard login */ tprintf(serv,"NICK %s\n",botname); if (pass[0]) tprintf(serv,"PASS %s\n",pass); tprintf(serv,"USER %s %s %s :%s\n",botuser,bothost,botserver,botrealname); chan=chanset; while (chan!=NULL) { tprintf(serv,"JOIN %s %s\n",chan->name,chan->key_prot); chan->stat&=~(CHANACTIVE|CHANPEND); chan=chan->next; } /* wait for async result now */ } } 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,miltime,switched=0,lastmin=99; struct chanset_t *chan; 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(); init_tand(); init_net(); init_tcl(); 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(); 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,SIGCHLD); /* 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; j=0; chan=chanset; while (chan!=NULL) { j++; chan=chan->next; } putlog(LOG_ALL,"*",""); putlog(LOG_ALL,"*","--- Loading %s (%s)",ver,s); putlog(LOG_ALL,"*","=== %s: %d channel%s, %d users.",botname,j,j==1?"":"s", i); use_stderr=1; printf("%s: %d channel%s, %d users.\n",botname,j,j==1?"":"s",i); /* move into background? */ if (backgrd) { xx=fork(); if (xx==-1) fatal("CANNOT FORK PROCESS.",0); if (xx!=0) { FILE *fp; printf("Launched 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); } else printf("* Warning! Could not write %s file!\n",pid_file); 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"); setsock(STDOUT,0); /* entry in net table */ dprintf(n,"\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_total++; dcc_chatter(n); } #ifndef NO_IRC /* now connect to a server: */ newserver[0]=0; newserverport=0; connect_server(); #else /* initialize irc things so they won't bother us */ serv=(-1); dccdir[0]=0; 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(); timecnt=0; } check_utimers(); /* secondly timers */ 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 */ } } 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_channels(); 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; putlog(LOG_MISC,"*","Regained nickname '%s'.",botname); } } check_idle_kick(); /* join any channels that aren't active or pending */ chan=chanset; while (chan!=NULL) { if (!(chan->stat&(CHANACTIVE|CHANPEND))) mprintf(serv,"JOIN %s\n",chan->name); chan=chan->next; } check_expired_splits(); check_expired_ignores(); check_expired_bans(); check_for_split(); /* am *I* split? */ check_expired_chanbans(); #endif /* ifndef NO_IRC */ check_expired_dcc(); check_expired_tbufs(); auto_link_tandem(NULL); /* attempt autolinks */ 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) putlog(LOG_MISC,"*","(!) timer drift -- spun %d minutes",i); } context; if (((int)(nowtm->tm_min/5)*5) == (nowtm->tm_min)) { /* 5 min */ if (!fivemin) { fivemin=1; #ifndef NO_IRC log_chans(); #ifdef CHECK_STONED if (waiting_for_awake) { /* uh oh! never got ison (303) from last time, five minutes ago! */ /* server is probably stoned */ killsock(serv); serv=(-1); /* will reconnect about 50 lines down */ putlog(LOG_SERV,"*","Server got stoned; jumping..."); } else { #endif /* CHECK_STONED */ /* used to do stuff here to keep the server from marking me as */ /* idle. this is futile though, and better left to scripts */ /* which will all do different things and keep the irc ops */ /* guessing -- as opposed to doing just one thing here which */ /* all irc ops could then check for. */ /* now: verify server is not stoned */ if (newbotname[0]) mprintf(serv,"ISON %s %s\n",botname,newbotname); else mprintf(serv,"ISON %s\n",botname); waiting_for_awake=1; #ifdef CHECK_STONED } #endif /* CHECK_STONED */ #endif /* !NO_IRC */ check_botnet_pings(); } } else fivemin=0; context; miltime=(nowtm->tm_hour*100)+(nowtm->tm_min); if (miltime==0) { /* at midnight */ if (!midnite) { midnite=1; strcpy(s,ctime(&now)); s[strlen(s)-1]=0; strcpy(&s[11],&s[20]); putlog(LOG_MISC,"*","--- %s",s); } } else midnite=0; if (miltime==switch_logfiles_at) { if (!switched) { switched=1; putlog(LOG_MISC,"*","Backing up user file..."); strcpy(s,userfile); strcat(s,"~bak"); copyfile(userfile,s); putlog(LOG_MISC,"*","Switching logfiles..."); for (i=0; itm_min==save_users_at) { /* hourly! */ if (!hourly) { hourly=1; write_userfile(); } } else hourly=0; #ifdef MODERN_TCL /* now Tcl has an event loop too, whee */ Tcl_DoOneEvent(TCL_DONT_WAIT); #endif context; #ifndef NO_IRC if (serv<0) { clear_channels(); connect_server(); } context; #endif /* 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!=serv) dcc_activity(xx,buf,i); else { /* SERVER ACTIVITY */ context; if (trying_server) { putlog(LOG_SERV,"*","Connected to %s",botserver); if (initserver[0]) do_tcl("init-server",initserver); trying_server=0L; } strcpy(s,buf); parsemsg(buf,from,code,msg); fixfrom(from); #ifdef USE_CONSOLE_R if ((strcmp(code,"PRIVMSG")==0) || (strcmp(code,"NOTICE")==0)) { if (!match_ignore(from)) { putlog(LOG_RAW,"*","[@] %s",s); check_tcl_raw(s); } } else { putlog(LOG_RAW,"*","[@] %s",s); check_tcl_raw(s); } #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,"303")==0) got303(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,"405")==0) got405(from,msg); else if (strcmp(code,"432")==0) got432(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,NULL,FLOOD_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_modes(); /* 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 */ putlog(LOG_SERV,"*","Disconnected from %s",botserver); clear_channels(); /* we're not on any channels any more */ killsock(serv); connect_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; putlog(LOG_MISC,"*","* Socket error #%d; recovering.",errno); if (fcntl(serv,F_GETFD,0)==(-1)) { putlog(LOG_MISC,"*","Server socket expired -- pfft"); killsock(serv); serv=(-1); } for (i=0; i