/* miscellaneous things that don't really fit anywhere else */ /* info, notes, logfile dumping, helpbot, queued output */ #include #include #include #include #include #include "eggdrop.h" extern int serv; extern char curchan[]; extern char notefile[]; extern int dcc_total; extern struct dcc_t dcc[]; extern char helpbot[]; extern char helpdir[]; extern int helpsock; extern char version[]; extern char botname[]; extern char origbotname[]; extern char admin[]; extern char botchan[]; extern int require_p; extern int backgrd; extern int con_chan; extern int term_z; extern int use_stderr; /* whether or not to display the time with console output */ int shtime=0; /* whether or not to use console output at all */ int use_console=1; /* logfile names */ char *logfile[MAXLOGS]; /* logfile masks */ int logmask[MAXLOGS]; /* console mask */ int conmask=LOG_MODES|LOG_CMDS|LOG_MISC; /* total messages queued on main server */ int mtot=0; /* total messages queued on helpbot server */ int htot=0; struct msgq { int sock; char *msg; struct msgq *next; } *mq=NULL,*hq=NULL; /* store info for clone bots */ struct tandbuf { char bot[10]; time_t timer; struct msgq *q; } tbuf[5]; /* expected memory usage */ int expmem_misc() { int tot=0; struct msgq *m=mq,*h=hq; while (m!=NULL) { tot+=strlen(m->msg)+1; tot+=sizeof(struct msgq); m=m->next; } while (h!=NULL) { tot+=strlen(h->msg)+1; tot+=sizeof(struct msgq); h=h->next; } return tot; } void init_misc() { int i; for (i=0; i<5; i++) { tbuf[i].q=NULL; tbuf[i].bot[0]=0; } } void nsplit(x,y) char *x,*y; { split(x,y); if (!x[0]) { strcpy(x,y); y[0]=0; } } /* log something */ void log(va_alist) va_dcl { FILE *f; va_list va; int i,type; char *format,s[512],s1[40],s2[512]; time_t tt; va_start(va); type=va_arg(va,int); format=va_arg(va,char *); vsprintf(s,format,va); if (s[0]==0) strcpy(s,"\n"); else if (shtime) { tt=time(NULL); strcpy(s1,ctime(&tt)); strcpy(s1,&s1[11]); s1[5]=0; sprintf(s2,"[%s] %s\n",s1,s); strcpy(s,s2); } else strcat(s,"\n"); for (i=0; icon_flags&type)) tprintf(dcc[i].sock,"%s",s); if ((type&LOG_MISC) && (use_stderr)) tprintf(STDERR,"%s",s); } /* queue a msg on one of the msg queues */ struct msgq *q_msg(qq,sock,s) struct msgq *qq; int sock; char *s; { struct msgq *q; int cnt; if (qq==NULL) { q=(struct msgq *)nmalloc(sizeof(struct msgq)); q->sock=sock; q->next=NULL; q->msg=(char *)nmalloc(strlen(s)+1); strcpy(q->msg,s); return q; } cnt=0; q=qq; while (q->next!=NULL) { q=q->next; cnt++; } if (cnt>MAXQMSG) { log(LOG_MISC,"!!! OVER MAXIMUM MSG QUEUE"); return qq; } q->next=(struct msgq *)nmalloc(sizeof(struct msgq)); q=q->next; q->sock=sock; q->next=NULL; q->msg=(char *)nmalloc(strlen(s)+1); strcpy(q->msg,s); return qq; } /* use when sending msgs... will spread them out so there's no flooding */ void mprintf(va_alist) va_dcl { char s[512]; int sock; char *format; va_list va; struct msgq *q; va_start(va); sock=va_arg(va,int); format=va_arg(va,char *); vsprintf(s,format,va); va_end(va); q=q_msg(mq,sock,s); if (q!=NULL) { mq=q; mtot++; } } /* use when sending msgs via the helpbot */ void hprintf(va_alist) va_dcl { char s[512]; int sock; char *format; va_list va; struct msgq *q; va_start(va); sock=va_arg(va,int); format=va_arg(va,char *); vsprintf(s,format,va); va_end(va); if (helpbot[0]) { q=q_msg(hq,sock,s); if (q!=NULL) { hq=q; htot++; } } else { q=q_msg(mq,serv,s); if (q!=NULL) { mq=q; mtot++; } } } /* call this once a second to send out another msg if any are still queued */ void deq_msg() { struct msgq *q; if (mq==NULL) return; write(mq->sock,mq->msg,strlen(mq->msg)); q=mq; mq=mq->next; nfree(q->msg); nfree(q); mtot--; } /* call this once a second to send out another msg from the helpbot */ void deq_helpmsg() { struct msgq *h; if (hq==NULL) return; write(hq->sock,hq->msg,strlen(hq->msg)); h=hq; hq=hq->next; nfree(h->msg); nfree(h); htot--; } /* create a tandem buffer for 'bot' */ void new_tbuf(bot) char *bot; { int i; for (i=0; i<5; i++) if (tbuf[i].bot[0]==0) { /* this one is empty */ strcpy(tbuf[i].bot,bot); tbuf[i].q=NULL; tbuf[i].timer=time(NULL); log(LOG_MISC,"Creating resync buffer for %s.",bot); return; } } /* flush a certain bot's tbuf */ void flush_tbuf(bot) char *bot; { int i; struct msgq *q; for (i=0; i<5; i++) if (strcasecmp(tbuf[i].bot,bot)==0) { while (tbuf[i].q!=NULL) { q=tbuf[i].q; tbuf[i].q=tbuf[i].q->next; nfree(q->msg); nfree(q); } tbuf[i].bot[0]=0; } } /* flush all tbufs older than 15 minutes */ void check_expired_tbufs() { int i; time_t now=time(NULL); struct msgq *q; for (i=0; i<5; i++) if (tbuf[i].bot[0]) { if (now-tbuf[i].timer > 900) { /* EXPIRED */ while (tbuf[i].q!=NULL) { q=tbuf[i].q; tbuf[i].q=tbuf[i].q->next; nfree(q->msg); nfree(q); } log(LOG_MISC,"Flushing resync buffer for clonebot %s.",tbuf[i].bot); tbuf[i].bot[0]=0; } } } /* add stuff to the resync buffers */ void q_resync(s) char *s; { int i; struct msgq *q; for (i=0; i<5; i++) if (tbuf[i].bot[0]) { q=q_msg(tbuf[i].q,0,s); if (q!=NULL) tbuf[i].q=q; } } /* is bot in resync list? */ int can_resync(bot) char *bot; { int i; for (i=0; i<5; i++) if (strcasecmp(bot,tbuf[i].bot)==0) return 1; return 0; } /* dump the resync buffer for a bot */ void dump_resync(z,bot) int z; char *bot; { int i; struct msgq *q; for (i=0; i<5; i++) if (strcasecmp(bot,tbuf[i].bot)==0) { while (tbuf[i].q!=NULL) { q=tbuf[i].q; tbuf[i].q=tbuf[i].q->next; tprintf(z,"%s",q->msg); nfree(q->msg); nfree(q); } tbuf[i].bot[0]=0; return; } } /* convert "abc!user@host" into "*!user@*host" or "abc!user@1.2.3.4" into "*!user@1.2.3.*" */ void maskhost(s,nw) char *s; char *nw; { char *p,*q,xx[150]; strcpy(xx,s); p=strchr(xx,'!'); if (p!=NULL) strcpy(xx,p+1); p=strchr(xx,'@'); if (p!=NULL) { q=strchr(p,'.'); if (strchr(q+1,'.')==NULL) { /* form xx@yy.com -> don't truncate */ sprintf(nw,"*!%s",xx); return; } if ((xx[strlen(xx)-1] >= '0') && (xx[strlen(xx)-1]<='9')) { /* ip number -> xx@#.#.#.* */ q=strrchr(p,'.'); if (q!=NULL) strcpy(q,".*"); sprintf(nw,"*!%s",xx); return; } /* form xx@yy.zz.etc.edu or whatever -> xx@*zz.etc.edu */ if (q!=NULL) { *(p+1)='*'; strcpy(p+2,q+1); } sprintf(nw,"*!%s",xx); } else strcpy(nw,"*"); } /* find info for a user and display it if there is one */ void showinfo(who,nick) char *who,*nick; { char s[121],s1[81],mtch[21]; if (match_attr_handle(who,USER_TANDEM)) return; get_handle_info(who,s1); strcpy(s,s1); if (s[0]=='@') strcpy(s,&s[1]); if (s[0]) { sprintf(mtch,"*%s*",nick); if (!wild_match(mtch,s1)) sprintf(s,"[%s] %s",nick,s1); mprintf(serv,"PRIVMSG %s :%s\n",curchan,s); } } /* determine how many notes are waiting for a user */ int num_notes(user) char *user; { int tot=0; FILE *f; char s[513],to[15]; if (!notefile[0]) return 0; f=fopen(notefile,"r"); if (f==NULL) return 0; while (!feof(f)) { fgets(s,512,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { rmspace(s); if ((s[0]) && (s[0]!='#') & (s[0]!=';')) { /* not comment */ split(to,s); if (strcasecmp(to,user)==0) tot++; } } } fclose(f); return tot; } /* show all notes for 'user' to z */ /* (delete them in the process) */ void tell_notes(z,user) int z; char *user; { FILE *f,*g; char s[513],from[40],to[40],timestr[81]; time_t t; if (!notefile[0]) return; f=fopen(notefile,"r"); if (f==NULL) return; sprintf(s,"%s~new",notefile); g=fopen(s,"w"); if (g==NULL) { fclose(f); return; } while (!feof(f)) { fgets(s,512,f); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(f)) { rmspace(s); if ((s[0]) && (s[0]!='#') && (s[0]!=';')) { /* not comment */ split(to,s); if (strcasecmp(to,user)==0) { split(from,s); split(timestr,s); t=atol(timestr); strcpy(timestr,ctime(&t)); timestr[16]=0; strcpy(timestr,×tr[4]); tprintf(z,"### NOTE from %s (%s): %s\n",from,timestr,s); } else fprintf(g,"%s %s\n",to,s); } else fprintf(g,"%s\n",s); } } fclose(f); fclose(g); unlink(notefile); #ifdef RENAME sprintf(s,"%s~new",notefile); rename(s,notefile); #else sprintf(s,"mv %s~new %s",notefile,notefile); system(s); #endif } /* add note to notefile */ int add_note(to,from,msg,z) char *to,*from,*msg; int z; { FILE *f; int i,ok; char *p,botf[81]; p=strchr(to,'@'); if (p!=NULL) { /* cross-bot note */ *p=0; p++; if (strcasecmp(p,origbotname)==0) /* to us?? */ return add_note(to,from,msg,z); /* start over, dimwit. */ sprintf(botf,"%s@%s",from,origbotname); i=nextbot(p); if (i<0) { if (z>=0) tprintf(z,"I don't think that bot is connected, but I'll try.\n"); tandout("priv %s %s@%s %s\n",botf,to,p,msg); } else tprintf(dcc[i].sock,"priv %s %s@%s %s\n",botf,to,p,msg); return 1; } ok=0; if (match_attr_handle(to,USER_MASTER)) ok=1; if ((match_attr_handle(to,USER_OP)) && (!require_p)) ok=1; if (match_attr_handle(to,USER_PARTY)) ok=1; if (strcasecmp(to,"hq")==0) ok=1; if (match_attr_handle(to,USER_TANDEM)) ok=0; if (!ok) { if (z>=0) tprintf(z,"Nobody called %s has access to the party line!\n",to); return 0; } for (i=0; iaway!=NULL) { aok=0; if (z>=0) tprintf(z,"%s is away: %s\n",dcc[i].nick,dcc[i].u.chat->away); } if (dcc[i].type==DCC_FILES) if (dcc[i].u.file->chat->away!=NULL) { aok=0; if (z>=0) tprintf(z,"%s is away: %s\n",dcc[i].nick,dcc[i].u.file->chat->away); } if (aok) { if (z==(-2)) tprintf(dcc[i].sock,"*** [%s] %s\n",from,msg); else tprintf(dcc[i].sock,"%cNote [%s]: %s\n",7,from,msg); if (z>=0) tprintf(z,"-> %s: %s\n",to,msg); return 1; } } } if (notefile[0]==0) { if (z>=0) tprintf(z,"Notes are not supported by this bot.\n"); return 0; } if (z==(-2)) return; /* error msg from a tandembot: don't store */ f=fopen(notefile,"a"); if (f==NULL) f=fopen(notefile,"w"); if (f==NULL) { if (z>=0) tprintf(z,"Can't create notefile. Sorry.\n"); log(LOG_MISC,"Notefile unreachable!"); return 0; } fprintf(f,"%s %s %lu %s\n",to,from,time(NULL),msg); fclose(f); if (z>=0) tprintf(z,"Stored message.\n"); return 2; } /* nick in use: 433 */ void helpbot_433(from,msg) char *from,*msg; { int i,j; char *oknicks="0^1-2_\\3[45]67`89"; /* just change the last character randomly */ i=strlen(helpbot); if (i==9) i--; helpbot[i+1]=0; j=(random()/16)%(strlen(oknicks)+26); if (j