/* 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; extern char motdfile[]; extern char cx_file[]; extern int cx_line; extern char ver[]; /* 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; } } #define upcase(c) (((c)>='a' && (c)<='z') ? (c)-'a'+'A' : (c)) /* determine if littles is contained in bigs (ignoring case) */ /* if so: return pointer to the littles in bigs */ /* if not: return NULL */ char *stristr(bigs,littles) char *bigs,*littles; { char *st=bigs,*p,*q; while (1) { if (!*st) return NULL; p=littles; q=st; while ((*p) && (*q) && (upcase(*p)==upcase(*q))) { p++; q++; } if ((!*q) && (*p)) return NULL; /* premature end of bigs */ if (!*p) return st; /* found it! */ st++; /* try again */ } } /* log something */ void log(va_alist) va_dcl { FILE *f; va_list va; int i,type; char *format,s[570],s1[40],s2[570]; 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; static int warned=0; 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) { if (!warned) log(LOG_MISC,"!!! OVER MAXIMUM MSG QUEUE"); warned=1; /* only log that once until Q can recover */ return qq; } warned=0; 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(hq,serv,s); if (q!=NULL) { hq=q; htot++; } } } /* 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--; } /*** RESYNC BUFFERS ***/ /* 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_TAND,"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_TAND,"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 (q==NULL) { /* form xx@yy -> very bizarre */ sprintf(nw,"*!%s",xx); return; } 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[121]; if (get_attr_handle(who) & USER_TANDEM) return; get_handle_info(who,s1); strcpy(s,s1); if (s[0]=='@') strcpy(s,&s[1]); if (s[0]) { if (stristr(s,nick)==NULL) { sprintf(s1,"[%s] %s",nick,s); strcpy(s,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; } /* 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; } if (!is_user(to)) { if (z>=0) tprintf(z,"I don't know anyone by that name.\n"); return 0; } for (i=0; iaway!=NULL) && (z!=(-2))) { /* only check away if it's not from a bot */ 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) && (z!=(-2))) { 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=8; helpbot[i+1]=0; j=(random()/16)%(strlen(oknicks)+26); if (jstatus&STAT_PARTY), dcc[idx].u.chat->status&STAT_MASTER); if (s[0]) tprintf(dcc[idx].sock,"%s\n",s); } } fclose(vv); tprintf(dcc[idx].sock,"\n"); } } /* notes */ /* rd=-1 : index rd=0 : read all msgs rd>0 : read msg #n */ void notes_read(hand,nick,rd,z) char *hand,*nick; int rd,z; { FILE *f; char s[513],to[15],dt[81],from[81]; time_t tt; int idx=1; if (!notefile[0]) { if (z) tprintf(z,"You have no messages.\n"); else hprintf(helpsock,"NOTICE %s :You have no messages.\n",nick); return; } f=fopen(notefile,"r"); if (f==NULL) { if (z) tprintf(z,"You have no messages.\n"); else hprintf(helpsock,"NOTICE %s :You have no messages.\n",nick); 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,hand)==0) { split(from,s); split(dt,s); tt=atol(dt); strcpy(dt,ctime(&tt)); dt[16]=0; strcpy(dt,&dt[4]); if ((idx==rd) || (rd==0)) { if (z) tprintf(z,"%2d. %s (%s): %s\n",idx,from,dt,s); else hprintf(helpsock,"NOTICE %s :%2d. %s (%s): %s\n",nick,idx,from, dt,s); } if (rd<0) { if (z) { if (idx==1) tprintf(z,"### You have the following notes waiting:\n"); tprintf(z," %2d. %s (%s)\n",idx,from,dt); } else hprintf(helpsock,"NOTICE %s :%2d. %s (%s)\n",nick,idx,from,dt); } idx++; } } } } fclose(f); if ((rd>=idx) && (rd>0)) { if (z) tprintf(z,"You don't have that many messages.\n"); else hprintf(helpsock,"NOTICE %s :You don't have that many messages.\n",nick); } if (rd<0) { if (idx==1) { if (z) tprintf(z,"You have no messages waiting.\n"); else hprintf(helpsock,"NOTICE %s :You have no messages.\n",nick); } else { if (z) tprintf(z,"### Use '.notes read' to read them.\n"); else hprintf(helpsock,"NOTICE %s :(%d total)\n",nick,idx-1); } } } void notes_del(hand,nick,dl,z) char *nick,*hand; int dl,z; { FILE *f,*g; char s[513],to[81]; int idx=1; if (!notefile[0]) { if (z) tprintf(z,"You have no messages.\n"); else hprintf(helpsock,"NOTICE %s :You have no messages.\n",nick); return; } f=fopen(notefile,"r"); if (f==NULL) { if (z) tprintf(z,"You have no messages.\n"); else hprintf(serv,"NOTICE %s :You have no messages.\n",nick); return; } sprintf(s,"%s~new",notefile); g=fopen(s,"w"); if (g==NULL) { if (z) tprintf(z,"Can't modify the note file. :(\n"); else hprintf(helpsock,"NOTICE %s :Can't modify the note file. :(\n",nick); 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,hand)==0) { if ((dl>0) && (idx!=dl)) fprintf(g,"%s %s\n",to,s); idx++; } 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 if ((dl>=idx) && (dl>0)) { if (z) tprintf(z,"You don't have that many messages.\n"); else hprintf(helpsock,"NOTICE %s :You don't have that many messages.\n", nick); } else if (idx==1) { if (z) tprintf(z,"You have no messages.\n"); else hprintf(helpsock,"NOTICE %s :You have no messages.\n",nick); } else { if (dl==0) { if (z) tprintf(z,"Erased all notes.\n"); else hprintf(helpsock,"NOTICE %s :Erased all notes.\n",nick); } else { if (z) tprintf(z,"Erased #%d; %d left.\n",dl,idx-2); else hprintf(helpsock,"NOTICE %s :Erased #%d; %d left.\n",nick,dl,idx-2); } } }