/* eggdrop in alpha-stages... now using mtgets */ #include #include #include #include #include #include #include "eggdrop.h" /* linux machines are too stupid to know standard signal operations: */ #ifdef LINUX #define sigvec sigaction #define sv_mask sa_mask #define sv_flags sa_flags #define sv_handler sa_handler #endif #define msgrate 2 #define STDIN 0 #define STDOUT 1 #define STDERR 2 char version[81]="Eggdrop v0.7d (c)1994 Robey Pointer"; /* 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]="config"; /* name of the log file */ char logfile[121]="eggdrop.log"; /* 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]; /* unix-time that the bot loaded up */ time_t online_since; 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 int log_joins; extern char admin[]; extern char gainops[]; extern char notefile[]; extern char newserver[]; extern int newserverport; int use_stderr=1; void fatal(s) char *s; { int i; console("* %s",s); if (stderr) fprintf(stderr,"* %s\n",s); if (serv!=-1) close(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); } /* 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; /* 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."); botname[strlen(botname)-1]=*p; } console("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'; } console("NICK IN USE: Trying '%s'",botname); } tprintf(serv,"NICK %s\n",botname); } #define _NICK 1 #define _PRIVMSG 2 #define _NOTICE 3 #define _CTCP 4 /* do on NICK, PRIVMSG, and NOTICE */ int detect_flood(from,which,tochan) char *from; int which,tochan; { char *p; time_t t; static int lastmsgs=0; char h[121]; int thr=5; static char lastmsghost[81]=""; static time_t lastmsgtime=0L; /* 10 in 1 second to kick from channel */ if (((which==_PRIVMSG) || (which==_NOTICE)) && (tochan)) thr=10; p=strchr(from,'!'); if (p!=NULL) { p++; p=strchr(p,'@'); } if (p!=NULL) { p++; t=time(NULL); if (strcasecmp(lastmsghost,p)!=0) { /* new */ strcpy(lastmsghost,p); lastmsgtime=t; lastmsgs=0; } else { /* old */ if (lastmsgtime < t-60) { lastmsgtime=t; lastmsgs=0; } else { lastmsgs++; if (lastmsgs>=thr) { /* FLOOD */ if (((which==_PRIVMSG) || (which==_NOTICE)) && (!tochan)) { /* private msg */ sprintf(h,"*!*@%s",p); lastmsgs=0; lastmsgtime=0; lastmsghost[0]=0; console("Flood from @%s! Placing on ignore!",p); prog_ignore(h); return 1; } else if (which==_CTCP) { /* ctcp flood! */ sprintf(h,"*!*@%s",p); lastmsgs=0; lastmsgtime=0; lastmsghost[0]=0; console("CTCP flood from @%s! Placing on ignore and kicking!",p); prog_ignore(h); p=strchr(from,'!'); if (p!=NULL) { *p=0; tprintf(serv,"KICK %s %s :CTCP flood\n",curchan,from); *p='!'; } return 1; } else { /* flooding chan! either by public, notice, or nick */ lastmsgs=0; lastmsgtime=0; lastmsghost[0]=0; p=strchr(from,'!'); if (p!=NULL) { console("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() { console("BUS ERROR -- CRASHING!"); exit(1); } void got_segv() { console("SEGMENT VIOLATION -- CRASHING!"); exit(1); } void got_term() { console("RECEIVED TERMINATE SIGNAL (IGNORING)"); return; } void got_quit() { console("RECEIVED QUIT SIGNAL (IGNORING)"); return; } void got_hup() { console("RECEIVED HANGUP SIGNAL (IGNORING)"); return; } void got_pipe() { console("PIPE FAULT -- attempting to ignore"); return; } void got_tterr() { console("ATTEMPTED READ/WRITE TTY CONSOLE FROM BACKGROUND"); console("Notify Robey of this error! It's a major goof!"); return; } void do_arg(s) char *s; { int i; if (s[0]=='-') for (i=1; i1) for (i=1; i0) { dcc[dcc_total].addr=0L; dcc[dcc_total].port=telnet_port; dcc[dcc_total].sock=i; dcc[dcc_total].type=DCC_TELNET; dcc[dcc_total].status=dcc[dcc_total].used=0; strcpy(dcc[dcc_total].nick,"TELNET"); strcpy(dcc[dcc_total].host,""); strcpy(dcc[dcc_total].param,""); dcc_total++; } else telnet_port++; } if (i>0) console("Listening at telnet port %d.",telnet_port); else { console("Failed to find an open telnet port near %d.",telnet_port); telnet_port=0; } } /* terminal emulating dcc chat */ if ((!backgrd) && (term_z)) { dcc[dcc_total].addr=0L; dcc[dcc_total].port=0; dcc[dcc_total].sock=STDOUT; dcc[dcc_total].type=DCC_CHAT; dcc[dcc_total].status=STAT_MASTER | STAT_CONSOLE; dcc[dcc_total].used=0; dcc[dcc_total].msgs_per_sec=0; strcpy(dcc[dcc_total].nick,"HQ"); strcpy(dcc[dcc_total].host,"local console"); strcpy(dcc[dcc_total].param,""); dcc_total++; tprintf(STDOUT,"\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_chatter(STDOUT); } /* now connect: */ console("Attempting connection to %s:%d",botserver,botserverport); serv=open_telnet(botserver,botserverport); if (serv<0) { neterror(s); console("Failed connect to %s (%s)",botserver,s); next_server(&curserv,botserver,&botserverport); sprintf(s1,"%s:%d",botserver,botserverport); while ((serv<0) && (strcmp(oldserv,s1)!=0)) { console("Attempting connection to %s:%d",botserver,botserverport); serv=open_telnet(botserver,botserverport); if (serv<0) { neterror(s); console("Failed connect to %s (%s)",botserver,s); next_server(&curserv,botserver,&botserverport); sprintf(s1,"%s:%d",botserver,botserverport); } else console("Successful connection to %s",botserver); } if (strcmp(oldserv,s1)==0) fatal("NO SERVERS WILL ACCEPT MY CONNECTION."); } else console("Successful connection to %s",botserver); /* connect helpbot if applicable */ if (helpbot[0]) { helpsock=open_telnet(helpserver,helpserverport); if (helpsock<0) { next_server(&helpserv,helpserver,&helpserverport); sprintf(s1,"%s:%d",helpserver,helpserverport); while ((helpsock<0) && (strcmp(oldserv1,s1)!=0)) { helpsock=open_telnet(helpserver,helpserverport); if (helpsock<0) { next_server(&helpserv,helpserver,&helpserverport); sprintf(s1,"%s:%d",helpserver,helpserverport); } } if (strcmp(oldserv1,s1)==0) { console("Helpbot fatally failed to connect to a server."); helpbot[0]=0; } } if (helpbot[0]) { tprintf(helpsock,"USER %s 1 1 :%s\n",botuser,botrealname); tprintf(helpsock,"NICK %s\n",helpbot); console("Helpbot '%s' online to %s:%d",helpbot,helpserver, helpserverport); } } tprintf(serv,"USER %s 1 1 :%s\n",botuser,botrealname); tprintf(serv,"NICK %s\n",botname); tprintf(serv,"JOIN %s\n",botchan); then=time(NULL); online_since=time(NULL); while(1) { now=time(NULL); if (now!=then) { /* once a second */ static cnt=0; 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,0); } } if (now-online_since == 60) { /* one minute after loading */ online=1; /* considered to be successfully online by now */ } else if (((int)(((float)(now-online_since))/60.0)*60)==(now-online_since)) { /* once a minute */ 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); } check_lonely_channel(); 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\n",botchan); } check_expired_splits(); check_expired_dcc(); check_for_split(); /* are WE split? */ { static int cnt=0; cnt++; if (cnt>=5) { /* EVERY FIVE MINUTES */ cnt=0; if (!log_joins) log_chan(); } } } } nowtm=localtime(&now); then=now; if ((nowtm->tm_hour==0) && (nowtm->tm_min==0)) { /* at midnight */ if (!midnite) { midnite=1; console("Switching logfiles..."); sprintf(s,"%s.yesterday",logfile); unlink(s); sprintf(s,"mv %s %s.yesterday",logfile,logfile); system(s); strcpy(s,ctime(&now)); s[strlen(s)-1]=0; strcpy(&s[11],&s[20]); console("--- %s",s); } } else midnite=0; if (nowtm->tm_min==0) { /* hourly! */ if (!hourly) { hourly=1; } } else hourly=0; /* check for server or dcc activity */ for (i=0; i0) { /* non-error */ if (xx==helpsock) helpbot_activity(buf); else if (xx!=serv) dcc_activity(xx,buf,i); else { /* SERVER ACTIVITY */ strcpy(s,buf); parsemsg(buf,from,code,msg); fixfrom(from); /* check for flood */ 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,"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,"473")==0) got473(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,"PING")==0) { fixcolon(msg); tprintf(serv,"PONG :%s\n",msg); } } } else if (xx==-1) { /* EOF from someone */ if (i==serv) { /* we lost this server, dammit */ console("Disconnected from %s",botserver); curchan[0]=0; /* we're not on a channel any more */ close(serv); sprintf(oldserv,"%s:%d",botserver,botserverport); if (newserverport) { curserv=(-1); strcpy(botserver,newserver); botserverport=newserverport; newserver[0]=0; newserverport=0; } next_server(&curserv,botserver,&botserverport); serv=-1; sleep(3); /* give irc a chance to recover? */ sprintf(s1,"%s:%d",botserver,botserverport); while ((serv<0) && (strcmp(oldserv,s1)!=0)) { console("Attempting connection to %s:%d",botserver,botserverport); serv=open_telnet(botserver,botserverport); if (serv<0) { neterror(s); console("Failed connect to %s (%s)",botserver,s); next_server(&curserv,botserver,&botserverport); sprintf(s1,"%s:%d",botserver,botserverport); } else console("Successful connection to %s",botserver); } if (strcmp(oldserv,s1)==0) fatal("NO SERVERS WILL ACCEPT MY CONNECTION."); tprintf(serv,"USER %s 1 1 :%s\n",botuser,botrealname); tprintf(serv,"NICK %s\n",botname); tprintf(serv,"JOIN %s\n",botchan); } else if (i==helpsock) { /* helpbot vanished */ close(helpsock); sprintf(oldserv1,"%s:%d",helpserver,helpserverport); next_server(&helpserv,helpserver,&helpserverport); helpsock=-1; sleep(3); sprintf(s1,"%s:%d",helpserver,helpserverport); while ((helpsock<0) && (strcmp(oldserv1,s1)!=0)) { helpsock=open_telnet(helpserver,helpserverport); if (helpsock<0) { next_server(&helpserv,helpserver,&helpserverport); sprintf(s1,"%s:%d",helpserver,helpserverport); } else console("Helpbot -> %s:%d",helpserver,helpserverport); } if (strcmp(oldserv1,s1)==0) { console("Helpbot fatally failed to connect to a server."); helpbot[0]=0; } if (helpbot[0]) { tprintf(helpsock,"USER %s 1 1 :%s\n",botuser,botrealname); tprintf(helpsock,"NICK %s\n",helpbot); } } else if (i!=STDOUT) eof_dcc(i); else fatal("END OF FILE ON TERMINAL"); } } }