/* stuff for adding commands via Tcl on the fly */ #define _TCLHASH #if HAVE_CONFIG_H #include #endif #include #include #include #include #include "../lush.h" #include "eggdrop.h" #include "proto.h" #include "cmdt.h" #include "tclegg.h" extern Tcl_Interp *interp; extern int dcc_total; extern struct dcc_t dcc[]; extern int require_x,require_p; extern cmd_t C_msg[],C_dcc[],C_file[]; extern int cx_line; extern char cx_file[]; Tcl_HashTable H_msg, H_dcc, H_fil, H_pub, H_msgm, H_pubm, H_join, H_part, H_sign, H_kick, H_topc, H_mode, H_ctcp, H_ctcr, H_nick, H_raw, H_bot, H_chon, H_chof, H_sent, H_rcvd, H_chat, H_link, H_disc, H_splt, H_rejn; int hashtot=0; int expmem_tclhash() { return hashtot; } /* initialize hash tables */ void init_hash() { Tcl_InitHashTable(&H_msg,TCL_STRING_KEYS); Tcl_InitHashTable(&H_dcc,TCL_STRING_KEYS); Tcl_InitHashTable(&H_fil,TCL_STRING_KEYS); Tcl_InitHashTable(&H_pub,TCL_STRING_KEYS); Tcl_InitHashTable(&H_msgm,TCL_STRING_KEYS); Tcl_InitHashTable(&H_pubm,TCL_STRING_KEYS); Tcl_InitHashTable(&H_join,TCL_STRING_KEYS); Tcl_InitHashTable(&H_part,TCL_STRING_KEYS); Tcl_InitHashTable(&H_sign,TCL_STRING_KEYS); Tcl_InitHashTable(&H_kick,TCL_STRING_KEYS); Tcl_InitHashTable(&H_topc,TCL_STRING_KEYS); Tcl_InitHashTable(&H_mode,TCL_STRING_KEYS); Tcl_InitHashTable(&H_ctcp,TCL_STRING_KEYS); Tcl_InitHashTable(&H_ctcr,TCL_STRING_KEYS); Tcl_InitHashTable(&H_nick,TCL_STRING_KEYS); Tcl_InitHashTable(&H_raw,TCL_STRING_KEYS); Tcl_InitHashTable(&H_bot,TCL_STRING_KEYS); Tcl_InitHashTable(&H_chon,TCL_STRING_KEYS); Tcl_InitHashTable(&H_chof,TCL_STRING_KEYS); Tcl_InitHashTable(&H_sent,TCL_STRING_KEYS); Tcl_InitHashTable(&H_rcvd,TCL_STRING_KEYS); Tcl_InitHashTable(&H_chat,TCL_STRING_KEYS); Tcl_InitHashTable(&H_link,TCL_STRING_KEYS); Tcl_InitHashTable(&H_disc,TCL_STRING_KEYS); Tcl_InitHashTable(&H_splt,TCL_STRING_KEYS); Tcl_InitHashTable(&H_rejn,TCL_STRING_KEYS); } void *tclcmd_alloc(size) int size; { tcl_cmd_t *x=(tcl_cmd_t *)nmalloc(sizeof(tcl_cmd_t)); hashtot+=sizeof(tcl_cmd_t); x->func_name=(char *)nmalloc(size); hashtot+=size; return (void *)x; } /* returns hashtable for that type */ /* also sets 'stk' if stackable, and sets 'name' the name, if non-NULL */ Tcl_HashTable *gethashtable(typ,stk,name) int typ,*stk; char *name; { char *nam=NULL; int st=0; Tcl_HashTable *ht=NULL; switch(typ) { case CMD_MSG: ht=&H_msg; nam="msg"; break; case CMD_DCC: ht=&H_dcc; nam="dcc"; break; case CMD_FIL: ht=&H_fil; nam="fil"; break; case CMD_PUB: ht=&H_pub; nam="pub"; break; case CMD_MSGM: ht=&H_msgm; nam="msgm"; st=1; break; case CMD_PUBM: ht=&H_pubm; nam="pubm"; st=1; break; case CMD_JOIN: ht=&H_join; nam="join"; st=1; break; case CMD_PART: ht=&H_part; nam="part"; st=1; break; case CMD_SIGN: ht=&H_sign; nam="sign"; st=1; break; case CMD_KICK: ht=&H_kick; nam="kick"; st=1; break; case CMD_TOPC: ht=&H_topc; nam="topc"; st=1; break; case CMD_MODE: ht=&H_mode; nam="mode"; st=1; break; case CMD_CTCP: ht=&H_ctcp; nam="ctcp"; break; case CMD_CTCR: ht=&H_ctcr; nam="ctcr"; break; case CMD_NICK: ht=&H_nick; nam="nick"; st=1; break; case CMD_RAW: ht=&H_raw; nam="raw"; st=1; break; case CMD_BOT: ht=&H_bot; nam="bot"; break; case CMD_CHON: ht=&H_chon; nam="chon"; st=1; break; case CMD_CHOF: ht=&H_chof; nam="chof"; st=1; break; case CMD_SENT: ht=&H_sent; nam="sent"; st=1; break; case CMD_RCVD: ht=&H_rcvd; nam="rcvd"; st=1; break; case CMD_CHAT: ht=&H_chat; nam="chat"; st=1; break; case CMD_LINK: ht=&H_link; nam="link"; st=1; break; case CMD_DISC: ht=&H_disc; nam="disc"; st=1; break; case CMD_SPLT: ht=&H_splt; nam="splt"; st=1; break; case CMD_REJN: ht=&H_rejn; nam="rejn"; st=1; break; } if (name!=NULL) strcpy(name,nam); if (stk!=NULL) *stk=st; return ht; } int get_bind_type(name) char *name; { int tp=(-1); if (strcasecmp(name,"dcc")==0) tp=CMD_DCC; if (strcasecmp(name,"msg")==0) tp=CMD_MSG; if (strcasecmp(name,"fil")==0) tp=CMD_FIL; if (strcasecmp(name,"pub")==0) tp=CMD_PUB; if (strcasecmp(name,"msgm")==0) tp=CMD_MSGM; if (strcasecmp(name,"pubm")==0) tp=CMD_PUBM; if (strcasecmp(name,"join")==0) tp=CMD_JOIN; if (strcasecmp(name,"part")==0) tp=CMD_PART; if (strcasecmp(name,"sign")==0) tp=CMD_SIGN; if (strcasecmp(name,"kick")==0) tp=CMD_KICK; if (strcasecmp(name,"topc")==0) tp=CMD_TOPC; if (strcasecmp(name,"mode")==0) tp=CMD_MODE; if (strcasecmp(name,"ctcp")==0) tp=CMD_CTCP; if (strcasecmp(name,"ctcr")==0) tp=CMD_CTCR; if (strcasecmp(name,"nick")==0) tp=CMD_NICK; if (strcasecmp(name,"bot")==0) tp=CMD_BOT; if (strcasecmp(name,"chon")==0) tp=CMD_CHON; if (strcasecmp(name,"chof")==0) tp=CMD_CHOF; if (strcasecmp(name,"sent")==0) tp=CMD_SENT; if (strcasecmp(name,"rcvd")==0) tp=CMD_RCVD; if (strcasecmp(name,"chat")==0) tp=CMD_CHAT; if (strcasecmp(name,"link")==0) tp=CMD_LINK; if (strcasecmp(name,"disc")==0) tp=CMD_DISC; if (strcasecmp(name,"rejn")==0) tp=CMD_REJN; if (strcasecmp(name,"splt")==0) tp=CMD_SPLT; #ifdef USE_CONSOLE_R if (strcasecmp(name,"raw")==0) tp=CMD_RAW; #endif return tp; } /* remove command */ int cmd_unbind(typ,flags,cmd,proc) int typ,flags; char *cmd,*proc; { tcl_cmd_t *tt,*last; Tcl_HashEntry *he; Tcl_HashTable *ht; context; ht=gethashtable(typ,NULL,NULL); he=Tcl_FindHashEntry(ht,cmd); if (he==NULL) return 0; /* no such binding */ tt=(tcl_cmd_t *)Tcl_GetHashValue(he); last=NULL; while (tt!=NULL) { /* if procs are same, erase regardless of flags */ if (strcasecmp(tt->func_name,proc)==0) { /* erase it */ if (last!=NULL) last->next=tt->next; else { if (tt->next==NULL) Tcl_DeleteHashEntry(he); else Tcl_SetHashValue(he,tt->next); } hashtot-=(strlen(tt->func_name)+1); nfree(tt->func_name); nfree(tt); hashtot-=sizeof(tcl_cmd_t); return 1; } last=tt; tt=tt->next; } return 0; /* no match */ } /* add command (remove old one if necessary) */ int cmd_bind(typ,flags,cmd,proc) int typ,flags; char *cmd,*proc; { tcl_cmd_t *tt; int new; Tcl_HashEntry *he; Tcl_HashTable *ht; int stk; if (proc[0]=='#') { log(LOG_MISC,"Note: binding to '#' is obsolete."); return 0; } cmd_unbind(typ,flags,cmd,proc); /* make sure we don't dup */ context; tt=(tcl_cmd_t *)nmalloc(sizeof(tcl_cmd_t)); hashtot+=sizeof(tcl_cmd_t); tt->flags_needed=flags; tt->next=NULL; tt->func_name=(char *)nmalloc(strlen(proc)+1); hashtot+=strlen(proc)+1; strcpy(tt->func_name,proc); ht=gethashtable(typ,&stk,NULL); he=Tcl_CreateHashEntry(ht,cmd,&new); if (!new) { tt->next=(tcl_cmd_t *)Tcl_GetHashValue(he); if (!stk) { /* remove old one -- these are not stackable */ hashtot-=(strlen(tt->next->func_name)+1); hashtot-=sizeof(tcl_cmd_t); nfree(tt->next->func_name); nfree(tt->next); tt->next=NULL; } } Tcl_SetHashValue(he,tt); return 1; } /* match types for check_tcl_bind */ #define MATCH_PARTIAL 0 #define MATCH_EXACT 1 #define MATCH_MASK 2 /* bitwise 'or' these: */ #define BIND_USE_ATTR 4 #define BIND_STACKABLE 8 #define BIND_HAS_BUILTINS 16 /* return values */ #define BIND_NOMATCH 0 #define BIND_AMBIGUOUS 1 #define BIND_MATCHED 2 /* but the proc couldn't be found */ #define BIND_EXECUTED 3 #define BIND_EXEC_LOG 4 /* proc returned 1 -> wants to be logged */ /* 10+ --> matches builtin # (retval-10) */ /* trigger (execute) a proc */ int trigger_bind(proc,param) char *proc,*param; { set_tcl_vars(); if (Tcl_VarEval(interp,proc,param,NULL)==TCL_ERROR) { log(LOG_MISC,"Tcl error [%s]: %s",proc,interp->result); return BIND_EXECUTED; } else { get_tcl_vars(); return (atoi(interp->result)>0)?BIND_EXEC_LOG:BIND_EXECUTED; } } /* check a tcl binding and execute the procs necessary */ int check_tcl_bind(hash,match,atr,param,match_type,builtin) Tcl_HashTable *hash; char *match,*param; int atr,match_type; cmd_t *builtin; { Tcl_HashSearch srch; Tcl_HashEntry *he; int cnt=0; char *proc=NULL; tcl_cmd_t *tt; int f=0,atrok; context; for (he=Tcl_FirstHashEntry(hash,&srch); (he!=NULL) && (!f); he=Tcl_NextHashEntry(&srch)) { int ok=0; switch (match_type&0x03) { case MATCH_PARTIAL: ok=(strncasecmp(match,Tcl_GetHashKey(hash,he),strlen(match))==0); break; case MATCH_EXACT: ok=(strcasecmp(match,Tcl_GetHashKey(hash,he))==0); break; case MATCH_MASK: ok=wild_match_per(Tcl_GetHashKey(hash,he),match); break; } if (ok) { tt=(tcl_cmd_t *)Tcl_GetHashValue(he); if (match_type & BIND_HAS_BUILTINS) atrok=flags_ok(tt->flags_needed,atr); else atrok=flags_eq(tt->flags_needed,atr); switch (match_type&0x03) { case MATCH_MASK: /* could be multiple triggers */ while (tt!=NULL) { if ((!(match_type&BIND_USE_ATTR)) || atrok) { cnt++; trigger_bind(tt->func_name,param); } tt=tt->next; } break; default: if ((!(match_type&BIND_USE_ATTR)) || atrok) { cnt++; proc=tt->func_name; if (strcasecmp(match,Tcl_GetHashKey(hash,he))==0) { cnt=1; f=1; /* perfect match */ } } break; } } } if (cnt==0) return BIND_NOMATCH; if ((match_type&0x03)==MATCH_MASK) return BIND_EXECUTED; if (cnt>1) return BIND_AMBIGUOUS; if ((match_type&BIND_HAS_BUILTINS) && (proc[0]=='*')) { /* calling builtin function */ int top=0,bot=0,try=0,xx; char pr[81]; strcpy(pr,&proc[1]); f=0; while (builtin[bot].access!=(-1)) bot++; /* find bottom */ /* binary search: */ while (!f) { try=(top+bot)/2; xx=strcasecmp(builtin[try].name,pr); if (xx==0) f=1; if (xx<0) top=try+1; if (xx>0) bot=try; if (top==bot) { log(LOG_MISC,"Tcl error [%s]: no such builtin function",proc); return BIND_MATCHED; } } return try+10; } return trigger_bind(proc,param); } /* check for tcl-bound msg command, return 1 if found */ /* msg: proc-name */ int check_tcl_msg(cmd,nick,uhost,hand,args) char *cmd,*nick,*uhost,*hand,*args; { int x,atr; atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_msg,cmd,atr," $_n $_uh $_h $_a", MATCH_PARTIAL|BIND_HAS_BUILTINS|BIND_USE_ATTR,C_msg); if (x==BIND_EXEC_LOG) log(LOG_CMDS,"(%s!%s) !%s! %s %s",nick,uhost,hand,cmd,args); if (x>=10) return (C_msg[x-10].func)(hand,nick,uhost,args); return ((x==BIND_MATCHED)||(x==BIND_EXECUTED)||(x==BIND_EXEC_LOG)); } /* check for tcl-bound dcc command, return 1 if found */ /* dcc: proc-name */ int check_tcl_dcc(cmd,idx,args) char *cmd,*args; int idx; { int x,atr; char s[5]; atr=get_attr_handle(dcc[idx].nick); sprintf(s,"%d",dcc[idx].sock); Tcl_SetVar(interp,"_n",dcc[idx].nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_i",s,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_dcc,cmd,atr," $_n $_i $_a", MATCH_PARTIAL|BIND_USE_ATTR|BIND_HAS_BUILTINS,C_dcc); if (x==BIND_AMBIGUOUS) { dprintf(idx,"Ambigious command.\n"); return 0; } if (x==BIND_NOMATCH) { dprintf(idx,"What? Try '.help'\n"); return 0; } if (x>=10) { if (C_dcc[x-10].func==CMD_LEAVE) return 1; (C_dcc[x-10].func)(idx,args); return 0; } if (x==BIND_EXEC_LOG) log(LOG_CMDS,"#%s# %s %s",dcc[idx].nick,cmd,args); return 0; } /* check for tcl-bound file command, return 1 if found */ /* fil: proc-name */ int check_tcl_fil(cmd,idx,args) char *cmd,*args; int idx; { int atr,x; char s[5]; atr=get_attr_handle(dcc[idx].nick); sprintf(s,"%d",dcc[idx].sock); Tcl_SetVar(interp,"_n",dcc[idx].nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_i",s,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_fil,cmd,atr," $_n $_i $_a", MATCH_PARTIAL|BIND_USE_ATTR|BIND_HAS_BUILTINS,C_file); if (x==BIND_AMBIGUOUS) { tprintf(dcc[idx].sock,"Ambigious command.\n"); return 0; } if (x==BIND_NOMATCH) { tprintf(dcc[idx].sock,"What? Try 'help'\n"); return 0; } if (x>=10) { if (C_file[x-10].func == CMD_LEAVE) return 1; (C_file[x-10].func)(idx,args); return 0; } if (x==BIND_EXEC_LOG) log(LOG_FILES,"#%s# files: %s %s",dcc[idx].nick,cmd,args); return 0; } int check_tcl_pub(nick,from,msg) char *nick,*from,*msg; { int x,atr; char args[512],cmd[512],host[161],handle[21]; strcpy(args,msg); nsplit(cmd,args); sprintf(host,"%s!%s",nick,from); get_handle_by_host(handle,host); atr=get_attr_handle(handle); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",from,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",handle,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_pub,cmd,atr," $_n $_uh $_h $_a", MATCH_EXACT|BIND_USE_ATTR,NULL); if (x==BIND_NOMATCH) return 0; if (x==BIND_EXEC_LOG) log(LOG_CMDS,"<<%s>> !%s! %s %s",nick,handle,cmd,args); return 1; } void check_tcl_pubm(nick,from,msg) char *nick,*from,*msg; { char args[512],host[161],handle[21]; int atr; strcpy(args,msg); sprintf(host,"%s!%s",nick,from); get_handle_by_host(handle,host); atr=get_attr_handle(handle); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",from,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",handle,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); check_tcl_bind(&H_pubm,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_msgm(cmd,nick,uhost,hand,arg) char *cmd,*nick,*uhost,*hand,*arg; { int atr; char args[512]; if (arg[0]) sprintf(args,"%s %s",cmd,arg); else strcpy(args,cmd); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); check_tcl_bind(&H_msgm,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_join(nick,uhost,hand) char *nick,*uhost,*hand; { int atr; char args[512]; sprintf(args,"%s!%s",nick,uhost); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); check_tcl_bind(&H_join,args,atr," $_n $_uh $_h", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_part(nick,uhost,hand) char *nick,*uhost,*hand; { int atr,x; char args[512]; sprintf(args,"%s!%s",nick,uhost); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_part,args,atr," $_n $_uh $_h", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_sign(nick,uhost,hand,reason) char *nick,*uhost,*hand,*reason; { int atr; char args[512]; sprintf(args,"%s!%s",nick,uhost); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",reason,TCL_GLOBAL_ONLY); check_tcl_bind(&H_sign,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_topc(nick,uhost,hand,topic) char *nick,*uhost,*hand,*topic; { int atr; atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",topic,TCL_GLOBAL_ONLY); check_tcl_bind(&H_topc,topic,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_nick(nick,uhost,hand,newnick) char *nick,*uhost,*hand,*newnick; { int atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",newnick,TCL_GLOBAL_ONLY); check_tcl_bind(&H_nick,newnick,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_kick(nick,uhost,hand,dest,reason) char *nick,*uhost,*hand,*dest,*reason; { Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",dest,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aa",reason,TCL_GLOBAL_ONLY); check_tcl_bind(&H_kick,dest,0," $_n $_uh $_h $_a $_aa", MATCH_MASK|BIND_STACKABLE,NULL); } #ifdef USE_CONSOLE_R void check_tcl_raw(raw) char *raw; { Tcl_SetVar(interp,"_a",raw,TCL_GLOBAL_ONLY); check_tcl_bind(&H_raw,raw,0," $_a",MATCH_MASK|BIND_STACKABLE,NULL); } #endif void check_tcl_tand(nick,code,param) char *nick,*code,*param; { Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",code,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",param,TCL_GLOBAL_ONLY); check_tcl_bind(&H_bot,code,0," $_n $_h $_a",MATCH_EXACT,NULL); } void check_tcl_mode(nick,uhost,hand,mode) char *nick,*uhost,*hand,*mode; { Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",mode,TCL_GLOBAL_ONLY); check_tcl_bind(&H_mode,mode,0," $_n $_uh $_h $_a", MATCH_MASK|BIND_STACKABLE,NULL); } int check_tcl_ctcp(nick,uhost,hand,dest,keyword,args) char *nick,*uhost,*hand,*dest,*keyword,*args; { int atr,x; atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",dest,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aa",keyword,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aaa",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_ctcp,keyword,atr," $_n $_uh $_h $_a $_aa $_aaa", MATCH_MASK|BIND_USE_ATTR,NULL); return ((x==BIND_MATCHED)||(x==BIND_EXECUTED)||(x==BIND_EXEC_LOG)); } int check_tcl_ctcr(nick,uhost,hand,dest,keyword,args) char *nick,*uhost,*hand,*dest,*keyword,*args; { int atr; atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",dest,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aa",keyword,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aaa",args,TCL_GLOBAL_ONLY); check_tcl_bind(&H_ctcr,keyword,atr," $_n $_uh $_h $_a $_aa $_aaa", MATCH_MASK|BIND_USE_ATTR,NULL); return 1; } void check_tcl_chon(hand,idx) char *hand; int idx; { int atr; char s[20]; sprintf(s,"%d",idx); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",s,TCL_GLOBAL_ONLY); check_tcl_bind(&H_chon,hand,atr," $_n $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_chof(hand,idx) char *hand; int idx; { int atr; char s[20]; sprintf(s,"%d",idx); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",s,TCL_GLOBAL_ONLY); check_tcl_bind(&H_chof,hand,atr," $_n $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_sent(hand,nick,path) char *hand,*nick,*path; { int atr; atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aa",path,TCL_GLOBAL_ONLY); check_tcl_bind(&H_sent,hand,atr," $_n $_a $_aa", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_rcvd(hand,nick,path) char *hand,*nick,*path; { int atr; atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",hand,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aa",path,TCL_GLOBAL_ONLY); check_tcl_bind(&H_rcvd,hand,atr," $_n $_a $_aa", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_chat(from,chan,text) char *from,*text; int chan; { char s[10]; sprintf(s,"%d",chan); Tcl_SetVar(interp,"_n",from,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",s,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_aa",text,TCL_GLOBAL_ONLY); check_tcl_bind(&H_chat,text,0," $_n $_a $_aa",MATCH_MASK|BIND_STACKABLE, NULL); } void check_tcl_link(bot,via) char *bot,*via; { Tcl_SetVar(interp,"_n",bot,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",via,TCL_GLOBAL_ONLY); check_tcl_bind(&H_link,bot,0," $_n $_a",MATCH_MASK|BIND_STACKABLE,NULL); } void check_tcl_disc(bot) char *bot; { Tcl_SetVar(interp,"_n",bot,TCL_GLOBAL_ONLY); check_tcl_bind(&H_disc,bot,0," $_n",MATCH_MASK|BIND_STACKABLE,NULL); } void check_tcl_splt(nick,uhost,hand) char *nick,*uhost,*hand; { int atr; char args[512]; sprintf(args,"%s!%s",nick,uhost); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); check_tcl_bind(&H_splt,args,atr," $_n $_uh $_h", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_rejn(nick,uhost,hand) char *nick,*uhost,*hand; { int atr; char args[512]; sprintf(args,"%s!%s",nick,uhost); atr=get_attr_handle(hand); Tcl_SetVar(interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_h",hand,TCL_GLOBAL_ONLY); check_tcl_bind(&H_rejn,args,atr," $_n $_uh $_h", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void tell_binds(idx,name) int idx; char *name; { Tcl_HashEntry *he; Tcl_HashSearch srch; Tcl_HashTable *ht; int i,fnd=0; tcl_cmd_t *tt; char typ[5],*s,*proc,flg[20]; int kind; context; kind=get_bind_type(name); for (i=0; ifunc_name; flags2str(tt->flags_needed,flg); if ((proc[0]!='*') || (strcmp(s,proc+1)!=0)) dprintf(idx," %-4s %-4s %-20s %s\n",typ,flg,s,tt->func_name); tt=tt->next; } } } if (!fnd) { if (kind==(-1)) dprintf(idx,"No command bindings.\n"); else dprintf(idx,"No bindings for %s.\n",name); } } int call_tcl_func(name,idx,args) char *name,*args; int idx; { char s[11]; set_tcl_vars(); sprintf(s,"%d",idx); Tcl_SetVar(interp,"_n",s,TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"_a",args,TCL_GLOBAL_ONLY); if (Tcl_VarEval(interp,name," $_n $_a",NULL)==TCL_ERROR) { log(LOG_MISC,"Tcl error [%s]: %s",name,interp->result); return -1; } get_tcl_vars(); return (atoi(interp->result)); }