/* tclchan.c -- handles: Tcl stubs for the channel-oriented commands dprintf'ized, 1aug96 */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include "../lush.h" #include "eggdrop.h" #include "users.h" #include "chan.h" #include "proto.h" #include "cmdt.h" #include "tclegg.h" extern Tcl_Interp *interp; extern struct chanset_t *chanset; extern char origbotname[]; extern char newserver[]; extern int newserverport; extern char newserverpass[]; extern char cx_file[]; extern int cx_line; extern int serv; extern struct userrec *userlist; /***********************************************************************/ /* streamlined by answer */ int tcl_chanlist STDVAR { memberlist *m; int f=0,atr; char s1[121],handle[21]; struct chanset_t *chan; BADARGS(2,3," channel ?flags?"); chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } m=chan->channel.member; if (argc==2) { /* no flag restrictions so just whiz it thru quick */ while (m->nick[0]) { Tcl_AppendElement(irp,m->nick); m=m->next; } return TCL_OK; } f=str2flags(argv[2]); /* return empty set if asked for flags but flags don't exist */ if ((f==0) && (argv[2][0]) && (argv[2][0]!='-')) return TCL_OK; while (m->nick[0]) { if (m->user==NULL) { sprintf(s1,"%s!%s",m->nick,m->userhost); get_handle_by_host(handle,s1); /* updates m->user */ } if (m->user==NULL) atr=0; else atr=m->user->flags; if ((atr & f)==f) Tcl_AppendElement(irp,m->nick); m=m->next; } return TCL_OK; } int tcl_botisop STDVAR { struct chanset_t *chan; BADARGS(2,2," channel"); chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[1],NULL); return TCL_ERROR; } if (me_op(chan)) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_isop STDVAR { struct chanset_t *chan; BADARGS(3,3," nick channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } if (member_op(chan->name,argv[1])) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_isvoice STDVAR { struct chanset_t *chan; BADARGS(3,3," nick channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } if (member_voice(chan->name,argv[1])) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_onchan STDVAR { struct chanset_t *chan; BADARGS(3,3," nickname channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } if (!ischanmember(chan->name,argv[1])) Tcl_AppendResult(irp,"0",NULL); else Tcl_AppendResult(irp,"1",NULL); return TCL_OK; } int tcl_handonchan STDVAR { struct chanset_t *chan; BADARGS(3,3," handle channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } if (!hand_on_chan(chan,argv[1])) Tcl_AppendResult(irp,"0",NULL); else Tcl_AppendResult(irp,"1",NULL); return TCL_OK; } int tcl_ischanban STDVAR { struct chanset_t *chan; BADARGS(3,3," ban channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } if (isbanned(chan,argv[1])) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_getchanhost STDVAR { struct chanset_t *chan; char s[UHOSTLEN]; BADARGS(3,3," nickname channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } getchanhost(chan->name,argv[1],s); Tcl_AppendResult(irp,s,NULL); return TCL_OK; } int tcl_onchansplit STDVAR { struct chanset_t *chan; BADARGS(3,3," nickname channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } if (is_split(chan->name,argv[1])) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_maskhost STDVAR { char new[121]; BADARGS(2,2," nick!user@host"); maskhost(argv[1],new); Tcl_AppendResult(irp,new,NULL); return TCL_OK; } int tcl_delglban STDVAR { struct chanset_t *chan; BADARGS(2,2," ban"); if (unprog_ban(argv[1])>0) { chan=chanset; while (chan!=NULL) { if (me_op(chan)) add_mode(chan,'-','b',argv[1]); chan=chan->next; } Tcl_AppendResult(irp,"1",NULL); } else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_delban STDVAR { struct chanset_t *chan; BADARGS(3,3," ban channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } if (u_unprog_ban(chan->bans,argv[1])>0) { if (me_op(chan)) add_mode(chan,'-','b',argv[1]); Tcl_AppendResult(irp,"1",NULL); } else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_isban STDVAR { struct chanset_t *chan; int ok=0; BADARGS(2,3," ban ?channel?"); if (argc==3) { chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } if (u_equals_ban(chan->bans,argv[1])) ok=1; } if (equals_ban(argv[1])) ok=1; if (ok) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_ispermban STDVAR { struct chanset_t *chan; int ok=0; BADARGS(2,3," ban ?channel?"); if (argc==3) { chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } if (u_equals_ban(chan->bans,argv[1])==2) ok=1; } if (equals_ban(argv[1])==2) ok=1; if (ok) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_matchban STDVAR { struct chanset_t *chan; int ok=0; BADARGS(2,3," user!nick@host ?channel?"); if (argc==3) { chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } if (u_match_ban(chan->bans,argv[1])) ok=1; } if (match_ban(argv[1])) ok=1; if (ok) Tcl_AppendResult(irp,"1",NULL); else Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_addban STDVAR { time_t t=time(NULL); char ban[161],cmt[71]; struct chanset_t *chan; BADARGS(3,4," ban channel ?comment?"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } strncpy(ban,argv[1],160); ban[160]=0; if (argc==3) sprintf(cmt,"%s: no comment",origbotname); else { strcpy(cmt,origbotname); strcat(cmt,": "); strncpy(&cmt[strlen(cmt)],argv[3],59); cmt[70]=0; } u_prog_ban(chan->bans,ban,t,cmt); if (me_op(chan)) { add_mode(chan,'+','b',ban); recheck_channel(chan); } return TCL_OK; } int tcl_addglban STDVAR { char ban[161],cmt[71]; struct chanset_t *chan; BADARGS(2,3," ban ?comment?"); strncpy(ban,argv[1],160); ban[160]=0; if (argc==2) sprintf(cmt,"%s: no comment",origbotname); else { strcpy(cmt,origbotname); strcat(cmt,": "); strncpy(&cmt[strlen(cmt)],argv[2],59); cmt[70]=0; } prog_ban(ban,0L,cmt); chan=chanset; while (chan!=NULL) { if (me_op(chan)) { add_mode(chan,'+','b',ban); recheck_channel(chan); } chan=chan->next; } return TCL_OK; } int tcl_jump STDVAR { BADARGS(1,4," ?server? ?port? ?pass?"); if (argc>=2) { strcpy(newserver,argv[1]); if (argc>=3) newserverport=atoi(argv[2]); else newserverport=6667; if (argc==4) strcpy(newserverpass,argv[3]); } tprintf(serv,"QUIT :changing servers\n"); sleep(1); killsock(serv); serv=(-1); return TCL_OK; } int tcl_getchanidle STDVAR { memberlist *m; time_t now=time(NULL); struct chanset_t *chan; BADARGS(3,3," nickname channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } m=chan->channel.member; while (m->nick[0]) { if (strcasecmp(m->nick,argv[1])==0) { char s[20]; int x; x=(now-(m->last))/60; sprintf(s,"%d",x); Tcl_AppendResult(irp,s,NULL); return TCL_OK; } m=m->next; } Tcl_AppendResult(irp,"0",NULL); return TCL_OK; } int tcl_chanbans STDVAR { banlist *b; struct chanset_t *chan; BADARGS(2,2," channel"); chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"illegal channel: ",argv[2],NULL); return TCL_ERROR; } b=chan->channel.ban; while (b->ban[0]) { Tcl_AppendElement(irp,b->ban); b=b->next; } return TCL_OK; } int tcl_hand2nick STDVAR { memberlist *m; char s[161],h[21]; struct chanset_t *chan; BADARGS(3,3," handle channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } m=chan->channel.member; while (m->nick[0]) { sprintf(s,"%s!%s",m->nick,m->userhost); get_handle_by_host(h,s); if (strcasecmp(h,argv[1])==0) { Tcl_AppendResult(irp,m->nick,NULL); return TCL_OK; } m=m->next; } return TCL_OK; /* blank */ } int tcl_nick2hand STDVAR { memberlist *m; char s[161],h[21]; struct chanset_t *chan; BADARGS(3,3," nick channel"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[2],NULL); return TCL_ERROR; } m=ismember(chan,argv[1]); if (m==NULL) return TCL_OK; sprintf(s,"%s!%s",m->nick,m->userhost); get_handle_by_host(h,s); Tcl_AppendResult(irp,h,NULL); return TCL_OK; } int tcl_channel_info(irp,chan) Tcl_Interp *irp; struct chanset_t *chan; { char s[121]; context; get_mode_protect(chan,s); Tcl_AppendElement(irp,s); sprintf(s,"%d",chan->idle_kick); Tcl_AppendElement(irp,s); Tcl_AppendElement(irp,chan->need_op); Tcl_AppendElement(irp,chan->need_invite); if (chan->stat&CHAN_CLEARBANS) Tcl_AppendElement(irp,"+clearbans"); else Tcl_AppendElement(irp,"-clearbans"); if (chan->stat&CHAN_ENFORCEBANS) Tcl_AppendElement(irp,"+enforcebans"); else Tcl_AppendElement(irp,"-enforcebans"); if (chan->stat&CHAN_DYNAMICBANS) Tcl_AppendElement(irp,"+dynamicbans"); else Tcl_AppendElement(irp,"-dynamicbans"); if (chan->stat&CHAN_NOUSERBANS) Tcl_AppendElement(irp,"-userbans"); else Tcl_AppendElement(irp,"+userbans"); if (chan->stat&CHAN_OPONJOIN) Tcl_AppendElement(irp,"+autoop"); else Tcl_AppendElement(irp,"-autoop"); if (chan->stat&CHAN_BITCH) Tcl_AppendElement(irp,"+bitch"); else Tcl_AppendElement(irp,"-bitch"); if (chan->stat&CHAN_GREET) Tcl_AppendElement(irp,"+greet"); else Tcl_AppendElement(irp,"-greet"); if (chan->stat&CHAN_PROTECTOPS) Tcl_AppendElement(irp,"+protectops"); else Tcl_AppendElement(irp,"-protectops"); if (chan->stat&CHAN_LOGSTATUS) Tcl_AppendElement(irp,"+statuslog"); else Tcl_AppendElement(irp,"-statuslog"); if (chan->stat&CHAN_STOPNETHACK) Tcl_AppendElement(irp,"+stopnethack"); else Tcl_AppendElement(irp,"-stopnethack"); if (chan->stat&CHAN_REVENGE) Tcl_AppendElement(irp,"+revenge"); else Tcl_AppendElement(irp,"-revenge"); return TCL_OK; } /* parse options for a channel */ int tcl_channel_modify(irp,chan,items,item) Tcl_Interp *irp; struct chanset_t *chan; int items; char **item; { int i; context; for (i=0; i=items) { Tcl_AppendResult(irp,"channel need-op needs argument",NULL); return TCL_ERROR; } strncpy(chan->need_op,item[i],120); chan->need_op[120]=0; } else if (strcmp(item[i],"need-invite")==0) { i++; if (i>=items) { Tcl_AppendResult(irp,"channel need-invite needs argument",NULL); return TCL_ERROR; } strncpy(chan->need_invite,item[i],120); chan->need_invite[120]=0; } else if (strcmp(item[i],"chanmode")==0) { i++; if (i>=items) { Tcl_AppendResult(irp,"channel chanmode needs argument",NULL); return TCL_ERROR; } if (strlen(item[i])>120) item[i][120]=0; set_mode_protect(chan,item[i]); } else if (strcmp(item[i],"idle-kick")==0) { i++; if (i>=items) { Tcl_AppendResult(irp,"channel idle-kick needs argument",NULL); return TCL_ERROR; } chan->idle_kick=atoi(item[i]); } else if (strcmp(item[i],"dont-idle-kick")==0) chan->idle_kick=0; else if (strcmp(item[i],"+clearbans")==0) chan->stat|=CHAN_CLEARBANS; else if (strcmp(item[i],"-clearbans")==0) chan->stat&=~CHAN_CLEARBANS; else if (strcmp(item[i],"+enforcebans")==0) chan->stat|=CHAN_ENFORCEBANS; else if (strcmp(item[i],"-enforcebans")==0) chan->stat&=~CHAN_ENFORCEBANS; else if (strcmp(item[i],"+dynamicbans")==0) chan->stat|=CHAN_DYNAMICBANS; else if (strcmp(item[i],"-dynamicbans")==0) chan->stat&=~CHAN_DYNAMICBANS; else if (strcmp(item[i],"-userbans")==0) chan->stat|=CHAN_NOUSERBANS; else if (strcmp(item[i],"+userbans")==0) chan->stat&=~CHAN_NOUSERBANS; else if (strcmp(item[i],"+autoop")==0) chan->stat|=CHAN_OPONJOIN; else if (strcmp(item[i],"-autoop")==0) chan->stat&=~CHAN_OPONJOIN; else if (strcmp(item[i],"+bitch")==0) chan->stat|=CHAN_BITCH; else if (strcmp(item[i],"-bitch")==0) chan->stat&=~CHAN_BITCH; else if (strcmp(item[i],"+greet")==0) chan->stat|=CHAN_GREET; else if (strcmp(item[i],"-greet")==0) chan->stat&=~CHAN_GREET; else if (strcmp(item[i],"+protectops")==0) chan->stat|=CHAN_PROTECTOPS; else if (strcmp(item[i],"-protectops")==0) chan->stat&=~CHAN_PROTECTOPS; else if (strcmp(item[i],"+statuslog")==0) chan->stat|=CHAN_LOGSTATUS; else if (strcmp(item[i],"-statuslog")==0) chan->stat&=~CHAN_LOGSTATUS; else if (strcmp(item[i],"+stopnethack")==0) chan->stat|=CHAN_STOPNETHACK; else if (strcmp(item[i],"-stopnethack")==0) chan->stat&=~CHAN_STOPNETHACK; else if (strcmp(item[i],"+revenge")==0) chan->stat|=CHAN_REVENGE; else if (strcmp(item[i],"-revenge")==0) chan->stat&=~CHAN_REVENGE; else { Tcl_AppendResult(irp,"illegal channel option: ",item[i],NULL); return TCL_ERROR; } } return TCL_OK; } /* create new channel and parse commands */ int tcl_channel_add(irp,newname,options) Tcl_Interp *irp; char *newname,*options; { int i; struct chanset_t *chan; int items; char **item; context; if (Tcl_SplitList(irp,options,&items,&item) != TCL_OK) return TCL_ERROR; chan=newchanset(); chan->name[0]=0; chan->need_op[0]=0; chan->need_invite[0]=0; chan->mode_pls_prot=0; chan->mode_mns_prot=0; chan->limit_prot=(-1); chan->key_prot[0]=0; chan->stat=CHAN_ENFORCEBANS|CHAN_GREET|CHAN_PROTECTOPS|CHAN_LOGSTATUS| CHAN_STOPNETHACK; chan->pls[0]=0; chan->mns[0]=0; chan->key[0]=0; chan->rmkey[0]=0; chan->limit=(-1); chan->idle_kick=0; for (i=0; icmode[i].op=NULL; chan->cmode[i].type=0; } chan->deopnick[0]=0; chan->deoptime=0L; chan->deops=0; chan->kicknick[0]=0; chan->kicktime=0L; chan->kicks=0; strncpy(chan->name,newname,80); chan->name[80]=0; if (findchan(newname)!=NULL) { /* could be from rehash: ignore re-definition of channel */ nfree(chan); /* BUT go ahead and re-parse the settings */ chan=findchan(newname); chan->stat &= ~CHANFLAGGED; /* don't delete me! :) */ if (tcl_channel_modify(irp,chan,items,item) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* okay, parse those commands */ if (tcl_channel_modify(irp,chan,items,item) != TCL_OK) { nfree(chan); return TCL_ERROR; } /* initialize chan->channel info */ init_channel(chan); addchanset(chan); chan->bans=NULL; /* channel name is stored in info field for sharebot stuff */ chan->bans=adduser(chan->bans,"null","none","-",0); set_handle_info(chan->bans,"null",chan->name); if (serv>=0) mprintf(serv,"JOIN %s %s\n",chan->name,chan->key_prot); return TCL_OK; } int tcl_channel STDVAR { struct chanset_t *chan; context; BADARGS(2,999," command ?options?"); if (strcmp(argv[1],"add")==0) { BADARGS(3,999," add channel-name ?options?"); if (argc==3) return tcl_channel_add(irp,argv[2],""); return tcl_channel_add(irp,argv[2],argv[3]); } if (strcmp(argv[1],"set")==0) { BADARGS(3,999," set channel-name ?options?"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"no such channel record",NULL); return TCL_ERROR; } return tcl_channel_modify(irp,chan,argc-3,&argv[3]); } if (strcmp(argv[1],"info")==0) { BADARGS(3,3," info channel-name"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"no such channel record",NULL); return TCL_ERROR; } return tcl_channel_info(irp,chan); } if (strcmp(argv[1],"remove")==0) { BADARGS(3,3," remove channel-name"); chan=findchan(argv[2]); if (chan==NULL) { Tcl_AppendResult(irp,"no such channel record",NULL); return TCL_ERROR; } if (serv>=0) mprintf(serv,"PART %s\n",chan->name); clear_channel(chan,0); freeuser(chan->bans); killchanset(argv[2]); return TCL_OK; } Tcl_AppendResult(irp,"unknown channel command: should be one of: ", "add, set, info, remove",NULL); return TCL_ERROR; } int tcl_banlist STDVAR { struct chanset_t *chan; struct userrec *u; struct eggqueue *q; char s[256],hst[UHOSTLEN],ts[21],ts1[21],ts2[21]; char *list[5],*p; context; BADARGS(1,2," ?channel?"); if (argc==2) { chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } u=chan->bans; } else u=get_user_by_handle(userlist,BAN_NAME); if (u==NULL) return TCL_OK; q=u->host; while ((q!=NULL) && (strcmp(q->item,"none")!=0)) { strcpy(s,q->item); splitc(hst,s,':'); splitc(ts,s,':'); if (s[0]=='+') { /* extended format */ strcpy(s,&s[1]); splitc(ts1,s,':'); splitc(ts2,s,':'); } else { strcpy(ts1,"0"); strcpy(ts2,"0"); } if (s[0]) { /* decode gibberish stuff */ p=strchr(s,'~'); while (p!=NULL) { *p=' '; p=strchr(s,'~'); } p=strchr(s,'`'); while (p!=NULL) { *p=','; p=strchr(s,'`'); } } list[0]=hst; list[1]=s; list[2]=ts; list[3]=ts1; list[4]=ts2; p=Tcl_Merge(5,list); Tcl_AppendElement(irp,p); n_free(p,"",0); q=q->next; } return TCL_OK; } int tcl_channels STDVAR { struct chanset_t *chan; context; BADARGS(1,1,""); chan=chanset; while (chan!=NULL) { Tcl_AppendElement(irp,chan->name); chan=chan->next; } return TCL_OK; } int tcl_getchanmode STDVAR { struct chanset_t *chan; BADARGS(2,2," channel"); chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } Tcl_AppendResult(irp,getchanmode(chan),NULL); return TCL_OK; } /* flushmode */ int tcl_flushmode STDVAR { struct chanset_t *chan; BADARGS(2,2," channel"); chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } flush_mode(chan,NORMAL); return TCL_OK; } int tcl_pushmode STDVAR { struct chanset_t *chan; char plus,mode; BADARGS(3,4," channel mode ?arg?"); chan=findchan(argv[1]); if (chan==NULL) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } plus=argv[2][0]; mode=argv[2][1]; if ((plus!='+') && (plus!='-')) { mode=plus; plus='+'; } if ((mode < 'a') || (mode > 'z')) { Tcl_AppendResult(irp,"invalid mode: ",argv[2],NULL); return TCL_ERROR; } if ((argc<4) && (strchr("bvo",mode)!=NULL)) { Tcl_AppendResult(irp,"modes b/v/o require an argument",NULL); return TCL_ERROR; } if (argc==4) add_mode(chan,plus,mode,argv[3]); else add_mode(chan,plus,mode,""); return TCL_OK; }