/* * This is panasync's tcl code for BitchX. * (c) 1996 Colten Edwards * * Released under the 3-clause BSD license in 2012. See the COPYRIGHT file. */ #include "irc.h" #include "struct.h" #include "parse.h" #include "ircterm.h" #include "server.h" #include "chelp.h" #include "commands.h" #include "encrypt.h" #include "vars.h" #include "ircaux.h" #include "lastlog.h" #include "window.h" #include "screen.h" #include "who.h" #include "hook.h" #include "input.h" #include "ignore.h" #include "keys.h" #include "names.h" #include "alias.h" #include "history.h" #include "funny.h" #include "ctcp.h" #include "dcc.h" #include "output.h" #include "exec.h" #include "notify.h" #include "status.h" #include "if.h" #include "help.h" #include "stack.h" #include "queue.h" #include "timer.h" #include "list.h" #include "userlist.h" #include "misc.h" #include "who.h" #include "whowas.h" #include "hash2.h" #define MAIN_SOURCE #include "modval.h" char tcl_versionstr[] = "Tcl 2.1"; #ifdef WANT_TCL /*#define TCL_PLUS*/ #include "tcl_bx.h" Tcl_HashTable *gethashtable (int, int *, char *); TimerList *tcl_Pending_timers = NULL; TimerList *tcl_Pending_utimers = NULL; 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, H_filt, H_cmd, H_input, H_notice, H_alias, H_help, H_functions, H_hook; #define CMD_MSG 0 #define CMD_DCC 1 #define CMD_FIL 2 #define CMD_PUB 3 #define CMD_MSGM 4 #define CMD_PUBM 5 #define CMD_JOIN 6 #define CMD_PART 7 #define CMD_SIGN 8 #define CMD_KICK 9 #define CMD_TOPC 10 #define CMD_MODE 11 #define CMD_CTCP 12 #define CMD_CTCR 13 #define CMD_NICK 14 #define CMD_RAW 15 #define CMD_BOT 16 #define CMD_CHON 17 #define CMD_CHOF 18 #define CMD_SENT 19 #define CMD_RCVD 20 #define CMD_CHAT 21 #define CMD_LINK 22 #define CMD_DISC 23 #define CMD_SPLT 24 #define CMD_REJN 25 #define CMD_FILT 26 #define CMD_CMD 27 #define CMD_INPUT 28 #define CMD_ALIAS 29 #define CMD_HELP 30 #define CMD_HOOK 31 #define CMD_FUNCTION 32 #define BINDS 33 /* extra commands are stored in Tcl hash tables (one hash table for each type of command: msg, dcc, etc) */ typedef struct tct { int flags_needed; char *func_name; char *(*func) (char *, char *); struct tct *next; } tcl_cmd_t; typedef struct { char name; char *(*func) (void); } BuiltIns; BuiltInFunctions *find_func_alias (char *); BuiltIns *find_func_aliasvar(char *); IrcVariable *get_var_address(char *); IrcVariable *fget_var_address(char *); void add_tcl_fset(Tcl_Interp *); extern cmd_t C_msg[], C_ctcp[], C_notice[], C_dcc[]; int in_add_to_tcl = 0; int tcl_bots STDVAR { char buff[BIG_BUFFER_SIZE]; SocketList *s; int count = 0; int i; BADARGS(1, 1, ""); for (i = 0; i < get_max_fd()+1; i++) { if (!check_dcc_socket(i)) continue; s = get_socketinfo(i); if ((s->flags & DCC_TYPES) == DCC_BOTMODE) { DCC_int *n; n = (DCC_int *)s->info; snprintf(buff, sizeof buff, "%d %s", n->dccnum, s->server); Tcl_AppendElement(irp, buff); count++; } } if (count) return TCL_OK; Tcl_AppendResult(irp, "No bots linked", NULL); return TCL_ERROR; } int tcl_clients STDVAR { SocketList *s; DCC_int *n; int i; char buff[BIG_BUFFER_SIZE]; int count = 0; BADARGS(1, 1, ""); for (i = 0; i < get_max_fd()+1; i++) { if (!check_dcc_socket(i)) continue; s = get_socket(i); if ((s->flags & DCC_TYPES) == DCC_CHAT) { n = (DCC_int *) s->info; snprintf(buff, sizeof buff, "%d %s", n->dccnum, s->server); Tcl_AppendElement(irp, buff); count++; } } if (count) return TCL_OK; Tcl_AppendResult(irp, "No dcc chats", NULL); return TCL_ERROR; } void add_to_tcl(Window *tmp, char *buf) { Tcl_AppendElement(tcl_interp, stripansicodes(buf)); } int tcl_alias STDVAR { BuiltInFunctions *tmp; char *buffer = NULL; char *ret = NULL; int i; char *p; if (argc == 1) { Tcl_AppendResult(irp, " ?args?", NULL); return TCL_ERROR; } for (i = 1; i < argc; i++) m_s3cat(&buffer, space, argv[i]); p = argv[0]; p++; if (p && (tmp = find_func_alias(p))) { ret = (char *)(*tmp->func)(tmp->name, buffer); Tcl_AppendResult(irp, ret, NULL); new_free(&ret); } new_free(&buffer); return TCL_OK; } int tcl_aliasvar STDVAR { BuiltIns *tmp; char *ret = NULL; char *p; p = argv[0]; p++; if (*p && (tmp = find_func_aliasvar(p))) { ret = (char *)(*tmp->func)(); Tcl_AppendResult(irp, ret, NULL); new_free(&ret); } return TCL_OK; } int tcl_get_var STDVAR { char *s = NULL; BADARGS(2,2," ?variable?"); if (argv[1] && (s = make_string_var(argv[1]))) { Tcl_AppendResult(irp, s, NULL); new_free(&s); return TCL_OK; } Tcl_AppendResult(irp, " No such variable", NULL); return TCL_ERROR; } int tcl_set_var STDVAR { int ret = TCL_ERROR, i; char *buffer = NULL; IrcVariable *tmp = NULL; if (argc <= 2) { Tcl_AppendResult(irp, " ?args?", NULL); return TCL_ERROR; } for (i = 2; i < argc; i++) m_s3cat(&buffer, space, argv[i]); if ((tmp = get_var_address(argv[1]))) { switch (tmp->type) { case STR_TYPE_VAR: { ret = TCL_OK; if (buffer) malloc_strcpy(&tmp->string, buffer); else new_free(&tmp->string); break; } case BOOL_TYPE_VAR: case INT_TYPE_VAR: { ret = TCL_OK; if (buffer) { int j; j = my_atol(buffer); if (j && (tmp->type == BOOL_TYPE_VAR)) tmp->integer = 1; else tmp->integer = j; } else tmp->integer = 0; break; } } } new_free(&buffer); return ret; } int tcl_fget_var STDVAR { char *s = NULL; BADARGS(2,2," ?variable?"); if (argv[1] && (s = make_fstring_var(argv[1]))) { Tcl_AppendResult(irp, s, NULL); new_free(&s); return TCL_OK; } Tcl_AppendResult(irp, " No such variable", NULL); return TCL_ERROR; } int tcl_fset_var STDVAR { int ret = TCL_ERROR, i; char *buffer = NULL; IrcVariable *tmp = NULL; if (argc <= 2) { Tcl_AppendResult(irp, " ?args?", NULL); return TCL_ERROR; } for (i = 2; i < argc; i++) m_s3cat(&buffer, space, argv[i]); if ((tmp = fget_var_address(argv[1]))) { switch (tmp->type) { case STR_TYPE_VAR: { ret = TCL_OK; if (buffer) malloc_strcpy(&tmp->string, buffer); else new_free(&tmp->string); break; } case BOOL_TYPE_VAR: case INT_TYPE_VAR: { ret = TCL_OK; if (buffer) { int j; j = my_atol(buffer); if (j && (tmp->type == BOOL_TYPE_VAR)) tmp->integer = 1; else tmp->integer = j; } else tmp->integer = 0; break; } } } new_free(&buffer); return ret; } int tcl_cparse STDVAR { char *buf; char *buffer = NULL; int i; if (argc <= 2) { Tcl_AppendResult(irp, " ?args?", NULL); return TCL_ERROR; } for (i = 1; i < argc; i++) m_s3cat(&buffer, space, argv[i]); buf = convert_output_format(buffer, NULL, NULL); Tcl_AppendResult(irp, buf, NULL); new_free(&buffer); return TCL_OK; } extern void got_tcluserhost (UserhostItem *stuff, char *nick, char *userhost) { char *buffer = NULL; if (stuff && strcmp(stuff->host, "") && strcmp(stuff->user, "")) { malloc_sprintf(&buffer, "%s %s %s", nick, stuff->user, stuff->host); Tcl_SetVar(tcl_interp, "userhost", buffer, TCL_APPEND_VALUE|TCL_LIST_ELEMENT); new_free(&buffer); return; } Tcl_SetVar(tcl_interp, "un-userhost", nick, TCL_APPEND_VALUE|TCL_LIST_ELEMENT); return; } int tcl_userhost STDVAR { char *buffer = NULL; int i; if (argc <= 2) { Tcl_AppendResult(irp, " ?args?", NULL); return TCL_ERROR; } Tcl_UnsetVar(irp, "userhost", TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT); Tcl_UnsetVar(irp, "un-userhost", TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT); for (i = 1; i < argc; i++) m_s3cat(&buffer, space, argv[i]); userhostbase(buffer, got_tcluserhost, 1, "%s", buffer); new_free(&buffer); return TCL_OK; } int tcl_msg STDVAR { char *buffer = NULL; int i; if (argc <= 2) { Tcl_AppendResult(irp, " channel|nick ?args?", NULL); return TCL_ERROR; } for (i = 2; i < argc; i++) m_s3cat(&buffer, space, argv[i]); send_text(argv[1], buffer, !strcmp(argv[0], "notice")?"NOTICE":"PRIVMSG", 1, 1); new_free(&buffer); return TCL_OK; } int tcl_say STDVAR { char *buffer = NULL; int i; BADARGS(1,999," ?args?"); if (argc == 1) { Tcl_AppendResult(irp, " ?args?", NULL); return TCL_ERROR; } for (i = 1; i < argc; i++) m_s3cat(&buffer, space, argv[i]); send_text(get_current_channel_by_refnum(0), buffer, "PRIVMSG", 1, 1); new_free(&buffer); return TCL_OK; } int tcl_desc STDVAR { char *buffer = NULL; int i; if (argc <= 2) { Tcl_AppendResult(irp, " target ?args?", NULL); return TCL_ERROR; } for (i = 2; i < argc; i++) m_s3cat(&buffer, space, argv[i]); send_ctcp(CTCP_PRIVMSG, argv[1], CTCP_ACTION, "%s", buffer); new_free(&buffer); return TCL_OK; } int tcl_getchanmode STDVAR { ChannelList *chan; BADARGS(2,2, " channel"); chan = lookup_channel(argv[1], from_server, 0); if (chan) { Tcl_AppendResult(irp, recreate_mode(chan), NULL); return TCL_OK; } Tcl_AppendResult(irp, " not on that channel", NULL); return TCL_ERROR; } int tcl_setcomment STDVAR { UserList *tmp; void *tmp2 = NULL; int i = 0; int size = -1; BADARGS(2,999, " nick"); if (argc <= 2) { Tcl_AppendResult(irp, " nick args", NULL); return TCL_ERROR; } for (tmp = next_userlist(NULL, &size, &tmp2); tmp; tmp = next_userlist(tmp, &size, &tmp2)) { if (!my_stricmp(tmp->nick, argv[1])) { for (i = 2; i < argc; i++) m_s3cat(&tmp->comment, space, argv[i]); } } return TCL_OK; } int tcl_getcomment STDVAR { UserList *tmp; void *tmp2 = NULL; int size = -1; BADARGS(2,2, " nick"); Tcl_AppendResult(irp, "", NULL); for (tmp = next_userlist(NULL, &size, &tmp2); tmp; tmp = next_userlist(tmp, &size, &tmp2)) { if (tmp->comment) { Tcl_AppendResult(irp, tmp->comment, NULL); break; } } return TCL_OK; } int tcl_strftime STDVAR { char buf[BIG_BUFFER_SIZE]; struct tm *tm1; time_t t; BADARGS(3,3, " format time"); t = atol(argv[2]); tm1 = localtime(&t); if (strftime(buf, sizeof(buf)-1, argv[1], tm1)) { Tcl_AppendResult(irp, buf, NULL); return TCL_OK; } Tcl_AppendResult(irp, " error with strftime" , NULL); return TCL_ERROR; } int tcl_ircii STDVAR { char *buffer = NULL; int i; if (argc <= 2) { Tcl_AppendResult(irp, " command args", NULL); return TCL_ERROR; } for (i = 1; i < argc; i++) m_s3cat(&buffer, space, argv[i]); in_add_to_tcl++; parse_line(NULL, buffer, NULL, 0, 0, 1); in_add_to_tcl--; new_free(&buffer); if (get_string_var(BOT_RETURN_VAR)) { char *arg = NULL; malloc_sprintf(&arg, "set ircii %s", get_string_var(BOT_RETURN_VAR)); Tcl_Eval(tcl_interp, arg); new_free(&arg); } return TCL_OK; } int tcl_pushmode STDVAR { ChannelList *chan = NULL; char *mode; char plus; int num_modes = 3; BADARGS(3,4," channel mode ?arg?"); if (!(chan = lookup_channel(argv[1], from_server, CHAN_NOUNLINK))) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } plus=argv[2][0]; mode= (char *)&argv[2][1]; if ((plus!='+') && (plus!='-')) { mode=argv[2]; plus='+'; } if ((*mode < 'a') || (*mode > 'z')) { Tcl_AppendResult(irp,"invalid mode: ",argv[2],NULL); return TCL_ERROR; } if ((argc<4) && (!strchr(mode, 'o') || !strchr(mode, 'v') || !strchr(mode,'b'))) { Tcl_AppendResult(irp,"modes b/v/o require an argument",NULL); return TCL_ERROR; } num_modes = (*mode == 'b') ? get_int_var(NUM_BANMODES_VAR) : get_int_var(NUM_OPMODES_VAR); if (argc==4) add_mode(chan,(char *)mode,plus == '+'?1:0, argv[3], NULL, num_modes); else add_mode(chan,(char *)mode,plus == '+'?1:0, NULL, NULL, num_modes); return TCL_OK; } int tcl_flushmode STDVAR { ChannelList *chan; BADARGS(2,2," channel"); if (!(chan = lookup_channel(argv[1], from_server, CHAN_NOUNLINK))) { Tcl_AppendResult(irp,"invalid channel: ",argv[1],NULL); return TCL_ERROR; } flush_mode_all(chan); return TCL_OK; } int tcl_maskhost STDVAR { char buffer[BIG_BUFFER_SIZE+1]; char *uh, *h; BADARGS(2, 2, " nick!user@host"); strcpy(buffer, argv[1]); if (!(uh = strchr(buffer, '!')) || !(h = strchr(buffer, '@'))) return TCL_ERROR; *uh++ = '\0'; Tcl_AppendResult(irp, cluster(uh), NULL); return TCL_OK; } int tcl_onchansplit STDVAR { WhowasList *tmp; int found = 0; BADARGS(3, 3, " nickname channel"); for (tmp = next_userhost(&whowas_splitin_list, NULL); tmp; tmp = next_userhost(&whowas_splitin_list, tmp)) { if (!my_stricmp(tmp->nicklist->nick, argv[1]) && !my_stricmp(tmp->channel, argv[2])) { found = 1; break; } } Tcl_AppendResult(irp, found?one:zero, NULL); return TCL_OK; } int tcl_timers STDVAR { BADARGS(1, 1, ""); tcl_list_timer(irp, tcl_Pending_timers); return TCL_OK; } int tcl_utimers STDVAR { BADARGS(1, 1, ""); tcl_list_timer(irp, tcl_Pending_utimers); return TCL_OK; } int tcl_servers STDVAR { char *s = NULL; int i; for (i = 0; i < server_list_size(); i++) { malloc_sprintf(&s, "%d %s %d %d", i, get_server_name(i), get_server_port(i), is_server_connected(i)); Tcl_AppendElement(irp, s); } new_free(&s); return TCL_OK; } extern char *get_dcc_info(SocketList *, DCC_int *, int); int tcl_dcc_stat STDVAR { int i; for (i = 0; i < get_max_fd()+1; i++) { if (check_dcc_socket(i)) { SocketList *s; char *str; s = get_socket(i); str = get_dcc_info(s, s->info, i); Tcl_AppendElement(irp, str); new_free(&str); } } return TCL_OK; } int tcl_dcc_close STDVAR { int i; BADARGS(2, 2, " number"); i = atol(argv[1]); if (i) close_dcc_number(i); return TCL_OK; } void chan_struct(Tcl_Interp *irp, ChannelList *c) { char *s = NULL; malloc_sprintf(&s, "%s %d %lu %s %d %d %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %lu %d %lu %d %lu %d %lu %d %lu %d %d %d %d %d %d %d %lu %d %d %lu %d %d", c->channel, c->server, c->mode, c->s_mode, c->limit, (int)c->have_op, (int)c->voice, c->channel_create.tv_sec, c->join_time.tv_sec, c->stats_ops, c->stats_dops, c->stats_bans, c->stats_unbans, c->stats_sops, c->stats_sdops, c->stats_sbans, c->stats_sunbans, c->stats_topics, c->stats_kicks, c->stats_pubs, c->stats_parts, c->stats_signoffs, c->stats_joins, c->csets->set_ainv, c->csets->set_auto_rejoin, c->csets->set_deop_on_deopflood, c->csets->set_deop_on_kickflood, c->csets->set_deopflood, c->csets->set_deopflood_time, c->csets->set_hacking, c->csets->set_kick_on_deopflood, c->csets->set_kick_on_joinflood, c->csets->set_kick_on_kickflood, c->csets->set_kick_on_nickflood, c->csets->set_kick_on_pubflood, c->csets->set_kickflood, c->csets->set_kickflood_time, c->csets->set_nickflood, c->csets->set_nickflood_time, c->csets->set_joinflood, c->csets->set_joinflood_time, c->csets->set_pubflood, c->csets->set_pubflood_time, c->csets->set_pubflood_ignore, c->csets->set_userlist, c->csets->set_shitlist, c->csets->set_lamelist, c->csets->set_kick_if_banned, c->totalnicks, c->maxnicks, c->maxnickstime, c->totalbans, c->maxbans, c->maxbanstime, c->csets->set_aop, c->csets->bitch_mode); Tcl_AppendElement(irp, s); new_free(&s); } int tcl_chanstruct STDVAR { ChannelList *c; BADARGS(1, 1, ""); for (c = get_server_channels(from_server); c; c = c->next) chan_struct(irp, c); return TCL_OK; } int tcl_channels STDVAR { ChannelList *c; BADARGS(1, 1, ""); for (c = get_server_channels(from_server); c; c = c->next) Tcl_AppendElement(irp, c->channel); return TCL_OK; } int tcl_channel_modify(Tcl_Interp *irp, char *channel, ChannelList *chan, int argc, char **argv) { return TCL_OK; } ChannelList *tcl_channel_add(Tcl_Interp *irp, char *chan, char *options) { ChannelList *tmp = NULL; int argc = 0; char **argv = NULL; if (Tcl_SplitList(irp, options, &argc, &argv) != TCL_OK) return NULL; if (!(tmp = lookup_channel(chan, from_server, CHAN_NOUNLINK))) tmp = add_channel(chan, from_server, 0); if (tmp) tcl_channel_modify(irp, chan, tmp, argc, argv); return tmp ? tmp : NULL; } int tcl_channel STDVAR { ChannelList *chan = NULL; int server = from_server; if (argc <= 2) { Tcl_AppendResult(irp, " command ?options?", NULL); return TCL_ERROR; } if (!my_stricmp(argv[1], "add")) { BADARGS(3, 999, " add channel-name ?options?"); if (!(chan = tcl_channel_add(irp, argv[2], argc==3?"":argv[3]))) { Tcl_AppendResult(irp, " channel error in [channel]", NULL); return TCL_ERROR; } send_to_server("JOIN %s %s", chan->channel, chan->key?chan->key:""); return TCL_OK; } if (!my_stricmp(argv[1], "set")) { BADARGS(3, 3, " set channel-name ?options?"); if (!(chan = prepare_command(&server, argv[2], 3))) { WhowasChanList *whowaschan; if ((whowaschan = check_whowas_chan_buffer(argv[2], 0, 0)) == NULL) { Tcl_AppendResult(irp, " no such channel", NULL); return TCL_ERROR; } else chan = whowaschan->channellist; } return tcl_channel_modify(irp, chan->channel, chan, argc-3, &argv[3]); } if (!my_stricmp(argv[1], "info")) { BADARGS(3, 3, " info channel-name"); if (!(chan = prepare_command(&server, argv[2], 3))) { Tcl_AppendResult(irp, " no such channel", NULL); return TCL_ERROR; } chan_struct(irp, chan); return TCL_OK; } if (!my_stricmp(argv[1], "remove")) { BADARGS(3, 3, " remove channel-name"); if (!(chan = prepare_command(&server, argv[2], 3))) { Tcl_AppendResult(irp, " no such channel", NULL); return TCL_ERROR; } send_to_server("PART %s", chan->channel); return TCL_OK; } Tcl_AppendResult(irp,"unknown channel command: should be one of: ", "add, set, info, remove",NULL); return TCL_ERROR; } int tcl_getchanhost STDVAR { ChannelList *chan; NickList *nick; BADARGS(3,3," nickname channel"); if ((chan = lookup_channel(argv[2], from_server, 0))) { if ((nick = find_nicklist_in_channellist(argv[1], chan, 0))) { Tcl_AppendResult(irp, nick->host, NULL); return TCL_OK; } Tcl_AppendResult(irp, "no such nick: ", NULL); } else Tcl_AppendResult(irp, "illegal channel: ", NULL); return TCL_ERROR; } int is_user(char *nick) { UserList *tmp = NULL; void *tmp2 = NULL; int size = -1; for (tmp = next_userlist(NULL, &size, &tmp2); tmp; tmp = next_userlist(tmp, &size, &tmp2)) if (!my_stricmp(nick, tmp->nick)) break; return tmp?1:0; } int tcl_validuser STDVAR { BADARGS(2,2," handle"); if (is_user(argv[1])) Tcl_AppendResult(irp,one,NULL); else Tcl_AppendResult(irp,zero,NULL); return TCL_OK; } int tcl_finduser STDVAR { char *n, *host, *s = NULL; UserList *nick; BADARGS(2, 2, " nick!user@host"); n = argv[1]; if ((host = strchr(argv[1], '!'))) *host++ = '\0'; if ((nick = lookup_userlevelc("*", host, "*", NULL))) malloc_sprintf(&s, "%d %s%s%s", nick->flags, nick->channels,nick->password?" ":"",nick->password?nick->password:""); else malloc_strcat(&s, "*"); Tcl_AppendResult(irp, s, NULL); new_free(&s); return TCL_OK; } int tcl_findshit STDVAR { char *n, *host, *s = NULL; ShitList *nick; BADARGS(2, 2, " nick!user@host"); n = argv[1]; if ((host = strchr(argv[1], '!'))) *host++ = '\0'; nick = nickinshit(n, host); if (nick) malloc_sprintf(&s, "%d %s %s", nick->level, nick->channels, nick->reason); else malloc_strcat(&s, "*"); Tcl_AppendResult(irp, s, NULL); new_free(&s); return TCL_OK; } int matchattr STDVAR { int is_match = 0; unsigned int flags = 0; NickList *nick = NULL; ChannelList *chan; BADARGS(3, 3, " nickname level"); for (chan = get_server_channels(from_server); chan; chan = chan->next) { for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick)) if (wild_match(argv[1], nick->nick)) goto found; } found: if (!nick) { Tcl_AppendResult(irp, "no such nick: ", NULL); return TCL_ERROR; } flags = convert_str_to_flags(argv[2]); if (nick->userlist && (nick->userlist->flags & flags)) is_match = 1; Tcl_AppendResult(irp, is_match ? one:zero, NULL); return TCL_OK; } int tcl_isop STDVAR { ChannelList *chan; NickList *nick; BADARGS(3, 3, " nick channel"); if ((chan = lookup_channel(argv[2], from_server, 0))) { if ((nick = find_nicklist_in_channellist(argv[1], chan, 0))) { if (nick_isop(nick)) Tcl_AppendResult(irp, one, NULL); else Tcl_AppendResult(irp, zero, NULL); return TCL_OK; } Tcl_AppendResult(irp, "no such nick: ", NULL); return TCL_ERROR; } Tcl_AppendResult(irp, "illegal channel: ", NULL); return TCL_ERROR; } int tcl_date STDVAR { char s[81]; time_t t; BADARGS(1,1,""); t = now; strcpy(s,my_ctime(t)); s[10]=s[24]=0; strcpy(s,&s[8]); strcpy(&s[8],&s[20]); strcpy(&s[2],&s[3]); Tcl_AppendResult(irp,s,NULL); return TCL_OK; } int tcl_time STDVAR { char s[81]; time_t t; BADARGS(1,1,""); t = now; strcpy(s,my_ctime(t)); strcpy(s,&s[11]); s[5]=0; Tcl_AppendResult(irp,s,NULL); return TCL_OK; } int tcl_ctime STDVAR { BADARGS(2, 2, " unixtime"); Tcl_AppendResult(irp, my_ctime((time_t)atol(argv[1])), NULL); return TCL_OK; } int tcl_chanlist STDVAR { ChannelList *chan; NickList *nick; int level = 0; BADARGS(2, 3, " channel "); if (!(chan = lookup_channel(argv[1], from_server, 0))) { Tcl_AppendResult(irp, "invalid channel:", argv[1], NULL); return TCL_ERROR; } if (argc == 2) { for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick)) Tcl_AppendElement(irp, nick->nick); return TCL_OK; } if (isdigit(*argv[2])) { level = atoi(argv[2]); for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick)) { if ((level <= 0) || (level && nick->userlist && nick->userlist->flags >= level)) Tcl_AppendElement(irp, nick->nick); } } else if (tolower(*argv[2]) == 'o' || tolower(*argv[2]) =='v') { for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick)) { if (!nick_isop(nick) && !nick_isvoice(nick)) continue; switch(tolower(*argv[2])) { case 'o': if (nick_isop(nick)) Tcl_AppendElement(irp, nick->nick); break; case 'v': if (nick_isvoice(nick)) Tcl_AppendElement(irp, nick->nick); break; } } } return TCL_OK; } int tcl_onchan STDVAR { ChannelList *chan; NickList *nick; BADARGS(3, 3, " nickname channel"); if (!(chan = lookup_channel(argv[2], from_server, 0))) { Tcl_AppendResult(irp, "invalid channel:", argv[2], NULL); return TCL_ERROR; } if ((nick = find_nicklist_in_channellist(argv[1], chan, 0))) Tcl_AppendResult(irp, one, NULL); else Tcl_AppendResult(irp, zero, NULL); return TCL_OK; } int tcl_putlog STDVAR { char logtext[BIG_BUFFER_SIZE+1]; BADARGS(2,2," text"); strlcpy(logtext, argv[1], sizeof logtext); putlog(LOG_CRAP,"*","%s",logtext); return TCL_OK; } int tcl_putcmdlog STDVAR { char logtext[BIG_BUFFER_SIZE+1]; BADARGS(2,2," text"); strlcpy(logtext, argv[1], sizeof logtext); putlog(LOG_ALL,"*","%s",logtext); return TCL_OK; } int tcl_putloglev STDVAR { int i,lev=0; char logtext[BIG_BUFFER_SIZE + 1]; BADARGS(4,4," level channel text"); i=atoi(argv[1]); if (i < 1 || i > 5) { Tcl_AppendResult(irp,"level out of range (must be 1-5)",NULL); return TCL_ERROR; } switch(i) { case 1: lev=LOG_USER1; break; case 2: lev=LOG_USER2; break; case 3: lev=LOG_USER3; break; case 4: lev=LOG_USER4; break; case 5: lev=LOG_USER5; break; } strlcpy(logtext, argv[3], sizeof logtext); putlog(lev,argv[2],"%s",logtext); return TCL_OK; } int tcl_unixtime STDVAR { char s[60]; BADARGS(1,1,""); snprintf(s, sizeof s, "%lu", now); Tcl_AppendResult(irp,s,NULL); return TCL_OK; } int tcl_putserv STDVAR { char s[BIG_BUFFER_SIZE+1],*p; BADARGS(2,2," \"text\""); strlcpy(s, argv[1], sizeof s); if ((p=strchr(s,'\n'))) *p = 0; if ((p=strchr(s,'\r'))) *p=0; send_to_server("%s",s); return TCL_OK; } int tcl_putscr STDVAR { char s[BIG_BUFFER_SIZE+1],*p; BADARGS(2,2," \"text\""); strlcpy(s, argv[1], sizeof s); if ((p=strchr(s,'\n'))) *p = 0; if ((p=strchr(s,'\r'))) *p=0; put_it("%s",s); return TCL_OK; } int tcl_putdcc STDVAR { char s[BIG_BUFFER_SIZE+1]; int idx = 0; BADARGS(3,3 ," hand idx text"); strlcpy(s, argv[2], sizeof s - 1); strlcat(s, "\n", sizeof s); idx = atoi(argv[1]); send(idx, s, strlen(s), 0); return TCL_OK; } int tcl_putbot STDVAR { char *msg = NULL; SocketList *s = NULL; BADARGS(3,3," botnick message"); s = find_dcc(argv[1], "chat", NULL, DCC_BOTMODE, 0, 1, -1); if (!s) { Tcl_AppendResult(irp,"user is not connected",NULL); return TCL_ERROR; } malloc_sprintf(&msg, "zapf %s %s %s\n", get_server_nickname(from_server), argv[1], argv[2]); send(s->is_read, msg, strlen(msg), 0); new_free(&msg); return TCL_OK; } int tcl_putallbots STDVAR { char *msg = NULL; int i; SocketList *s; BADARGS(2,2," message"); malloc_sprintf(&msg, "zapf-broad %s %s\n", get_server_nickname(from_server), argv[1]); for (i = 0; i < get_max_fd()+1; i++) { if (!check_dcc_socket(i)) continue; s = get_socketinfo(i); if (((s->flags & DCC_TYPES) == DCC_BOTMODE) && (s->is_read != -1)) send(s->is_read, msg, strlen(msg), 0); } new_free(&msg); return TCL_OK; } /* 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); Tcl_InitHashTable(&H_filt,TCL_STRING_KEYS); Tcl_InitHashTable(&H_cmd,TCL_STRING_KEYS); Tcl_InitHashTable(&H_input, TCL_STRING_KEYS); Tcl_InitHashTable(&H_notice, TCL_STRING_KEYS); Tcl_InitHashTable(&H_alias, TCL_STRING_KEYS); Tcl_InitHashTable(&H_help, TCL_STRING_KEYS); Tcl_InitHashTable(&H_functions, TCL_STRING_KEYS); Tcl_InitHashTable(&H_hook, TCL_STRING_KEYS); } /* remove command */ int cmd_unbind(int typ,int flags,char *cmd, char *proc) { tcl_cmd_t *tt,*last; Tcl_HashEntry *he; Tcl_HashTable *ht; 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 (!my_stricmp(tt->func_name,proc)) { /* erase it */ if (last!=NULL) last->next=tt->next; else { if (tt->next==NULL) Tcl_DeleteHashEntry(he); else Tcl_SetHashValue(he,tt->next); } new_free((char **)&tt->func_name); new_free((char **)&tt); return 1; } last=tt; tt=tt->next; } return 0; /* no match */ } /* add command (remove old one if necessary) */ int cmd_bind(int typ,int flags,char *cmd, char *proc, char *(*func)(char *, char *)) { tcl_cmd_t *tt; int new; Tcl_HashEntry *he; Tcl_HashTable *ht; int stk; if (proc[0]=='#') return 0; cmd_unbind(typ,flags,cmd,proc); /* make sure we don't dup */ tt=(tcl_cmd_t *)new_malloc(sizeof(tcl_cmd_t)); tt->flags_needed=flags; tt->next=NULL; malloc_strcpy(&(tt->func_name), proc); tt->func = func; 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 */ new_free(&tt->next->func_name); new_free((char **)&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 #define BIND_WANTRET 32 /* 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(char *proc, char *param, char *(*func)(char *, char *)) { char *result = NULL; if (internal_debug & DEBUG_TCL) debugyell("Tcl exec [%s] with [%s]", proc, param); if (func) { result = (*func)(proc, param); Tcl_AppendResult(tcl_interp,result); new_free(&result); if (internal_debug & DEBUG_TCL) debugyell("Tcl return from [%s] with [%s]", proc, result); return BIND_EXECUTED; } if (Tcl_VarEval(tcl_interp,proc,param,NULL)==TCL_ERROR) { if (internal_debug & DEBUG_TCL) debugyell("Tcl return from [%s] with [%s]", proc, tcl_interp->result); putlog(LOG_ALL,"*","Tcl error [%s]: %s",proc,tcl_interp->result); return BIND_EXECUTED; } if (internal_debug & DEBUG_TCL) debugyell("Tcl return from [%s] with [%s]", proc, tcl_interp->result); return (atoi(tcl_interp->result)>0)?BIND_EXEC_LOG:BIND_EXECUTED; } void init_builtins() { int i, j, new; Tcl_HashTable *ht=NULL; Tcl_HashEntry *he; tcl_cmd_t *tt; cmd_t *cc=NULL; for (j = 0; j < 4; j++ ) { switch(j) { case 0: ht = &H_msg; cc = C_msg; break; case 1: ht = &H_dcc; cc = C_dcc; break; case 2: ht = &H_ctcp; cc = C_ctcp; break; case 3: ht = &H_notice; cc = C_notice; break; } i = 0; while (cc[i].access != -1) { tt = (tcl_cmd_t *) new_malloc(sizeof(tcl_cmd_t)); tt->func_name = m_sprintf("*%s", cc[i].name); tt->flags_needed=cc[i].access; tt->next=NULL; he=Tcl_CreateHashEntry(ht,cc[i].name,&new); if (!new) { /* append old entry */ tcl_cmd_t *ttx=(tcl_cmd_t *)Tcl_GetHashValue(he); Tcl_DeleteHashEntry(he); tt->next=ttx; } Tcl_SetHashValue(he,tt); i++; } } } int flags_needed(unsigned long atr, unsigned long needed) { #if 0 if (atr & ADD_OWNER) return 1; if (atr & ADD_MASTER) return 1; #endif if ((atr & needed) == needed) return 1; return 0; } /* check a tcl binding and execute the procs necessary */ int check_tcl_bind(Tcl_HashTable *hash, char *mat, int atr, char *param, int 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,x; for (he=Tcl_FirstHashEntry(hash,&srch); (he!=NULL) && (!f); he=Tcl_NextHashEntry(&srch)) { int ok=0; switch (match_type&0x03) { case MATCH_PARTIAL: ok=(my_strnicmp(mat,Tcl_GetHashKey(hash,he),strlen(mat))==0); break; case MATCH_EXACT: ok=(my_stricmp(mat,Tcl_GetHashKey(hash,he))==0); break; case MATCH_MASK: ok=wild_match(Tcl_GetHashKey(hash,he), mat); break; } if (ok) { tt=(tcl_cmd_t *)Tcl_GetHashValue(he); switch (match_type&0x03) { case MATCH_MASK: /* could be multiple triggers */ while (tt!=NULL) { if (match_type & BIND_HAS_BUILTINS) atrok = flags_needed(atr, tt->flags_needed); else atrok = ((atr & tt->flags_needed) == tt->flags_needed); #if 0 if (match_type & BIND_HAS_BUILTINS) atrok= (atr > tt->flags_needed); else atrok= (atr >= tt->flags_needed); #endif if ((!(match_type&BIND_USE_ATTR)) || atrok) { cnt++; x=trigger_bind(tt->func_name,param, tt->func); if ((match_type & BIND_WANTRET) && (x==BIND_EXEC_LOG)) return x; } tt=tt->next; } break; default: if (match_type & BIND_HAS_BUILTINS) atrok = flags_needed(atr, tt->flags_needed); else atrok = ((atr & tt->flags_needed) == tt->flags_needed); #if 0 else atrok=(atr >= tt->flags_needed); #endif if ((!(match_type&BIND_USE_ATTR)) || atrok) { cnt++; proc=tt->func_name; if (my_stricmp(mat,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=my_stricmp(builtin[try].name,pr); if (xx==0) f=1; if (xx<0) top=try+1; if (xx>0) bot=try; if (top==bot) return BIND_MATCHED; } return try+10; } return trigger_bind(proc,param, NULL); } int tcl_timer STDVAR { char *x; char s[80]; BADARGS(3,3," minutes command"); if (atoi(argv[1]) <= 0) { Tcl_AppendResult(irp,"time value must be positive, nonzero",NULL); return TCL_ERROR; } if (argv[2][0]!='#') { x = tcl_add_timer(&tcl_Pending_timers, atol(argv[1])*60, argv[2], 0L); snprintf(s, sizeof s, "timer%s", x); Tcl_AppendResult(irp,s,NULL); } return TCL_OK; } int tcl_rand STDVAR { unsigned long x; char s[80]; BADARGS(2,2," limit"); if (strtoul(argv[1], NULL, 10) <= 0) { Tcl_AppendResult(irp,"limit must be greater than 0",NULL); return TCL_ERROR; } x = rand() % (strtoul(argv[1], NULL, 10)); snprintf(s, sizeof s, "%lu", x); Tcl_AppendResult(irp,s,NULL); return TCL_OK; } int tcl_utimer STDVAR { char *x; char s[80]; BADARGS(3,3," seconds command"); if (atoi(argv[1]) <= 0) { Tcl_AppendResult(irp,"time value must be positive, nonzero",NULL); return TCL_ERROR; } if (argv[2][0]!='#') { x=tcl_add_timer(&tcl_Pending_utimers, atol(argv[1]), argv[2], 0L); snprintf(s, sizeof s, "timer%s", x); Tcl_AppendResult(irp,s,NULL); } return TCL_OK; } int tcl_killtimer STDVAR { BADARGS(2,2," timerID"); if (strncmp(argv[1],"timer",5)!=0) { Tcl_AppendResult(irp,"argument is not a timerID",NULL); return TCL_ERROR; } if (tcl_remove_timer(&tcl_Pending_timers, atol(&argv[1][5]))) return TCL_OK; Tcl_AppendResult(irp,"invalid timerID",NULL); return TCL_ERROR; } int tcl_killutimer STDVAR { BADARGS(2,2," timerID"); if (strncmp(argv[1],"timer",5)!=0) { Tcl_AppendResult(irp,"argument is not a timerID",NULL); return TCL_ERROR; } if (tcl_remove_timer(&tcl_Pending_utimers, atol(&argv[1][5]))) return TCL_OK; Tcl_AppendResult(irp,"invalid timerID",NULL); return TCL_ERROR; } /* check for tcl-bound msg command, return 1 if found */ /* msg: proc-name */ int check_tcl_msg(char *cmd, char *nick, char *uhost, char *hand, char *args) { int x, atr = 0; UserList *n; if (!cmd) return 0; if ((n = lookup_userlevelc("*", uhost, "*", NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",!n?hand:n->nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_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) putlog(LOG_TCL, "*", "(%s!%s) !%s! %s %s",nick,uhost,hand,cmd,args); if (x>=10) { if (internal_debug & DEBUG_TCL) debugyell("Tcl func [%s] with [%s %s %s %s]", C_msg[x-10].name , hand, nick, uhost, args); 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 msg command, return 1 if found */ /* msg: proc-name */ int check_tcl_dcc(char *cmd, char *nick, char *host, int idx) { int x, atr = 1; char *c, *args; UserList *n; DCC_int *info; info = get_socketinfo(idx); if (info->ul) atr = info->ul->flags; #if 0 if ((n = lookup_userlevelc("*", host, "*", NULL))) { DCC_int *info; info = get_socketinfo(idx); atr = n->flags; } #endif if (!cmd || !*cmd) return 0; c = next_arg(cmd, &cmd); if (!c || !*c) return 0; args = cmd; Tcl_SetVar(tcl_interp,"_i",ltoa(idx), TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",host,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_dcc,c,atr," $_n $_i $_a", MATCH_PARTIAL|BIND_HAS_BUILTINS|BIND_USE_ATTR, C_dcc); if (x==BIND_AMBIGUOUS || x==BIND_NOMATCH) return 0; if (x>=10) { if (C_dcc[x-10].func == NULL) return 1; if (internal_debug & DEBUG_TCL) debugyell("Tcl func [%s] with [%d %s]", C_dcc[x-10].name , idx, args); (C_dcc[x-10].func)(idx,args); return 1; } return 1; } int check_tcl_ctcp(char *nick, char *uhost, char *hand, char *dest, char *keyword, char *args) { int atr = 0,x; UserList *n; if ((n = lookup_userlevelc("*", uhost, "*", NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",dest,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",keyword,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aaa",args,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_ctcp,keyword,atr," $_n $_uh $_h $_a $_aa $_aaa", MATCH_MASK|BIND_HAS_BUILTINS|BIND_USE_ATTR,NULL); return ((x==BIND_MATCHED)||(x==BIND_EXECUTED)||(x==BIND_EXEC_LOG)); } int check_tcl_pub(char *nick, char *from, char *chname, char *msg) { int x,atr = 0; char *args,*cmd, *free_me; UserList *n; free_me = args = m_strdup(msg); cmd = next_arg(args, &args); if (!cmd || !*cmd) { new_free(&free_me); return 0; } if ((n = lookup_userlevelc("*",from, chname, NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n", nick, TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh", from, TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h", n?n->nick:nick, TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a", chname, TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa", args, TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_pub,cmd,atr," $_n $_uh $_h $_a $_aa", MATCH_EXACT|BIND_USE_ATTR,NULL); new_free(&free_me); if (x==BIND_NOMATCH) return 0; return 1; } void check_tcl_pubm(char *nick, char *uhost, char *chname, char *msg) { char *args = NULL; int atr = 0; UserList *n; malloc_sprintf(&args, "%s %s", chname, msg); if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",msg,TCL_GLOBAL_ONLY); check_tcl_bind(&H_pubm,args,atr," $_n $_uh $_h $_a $_aa", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); new_free(&args); } void check_tcl_msgm(char *cmd, char *nick, char *uhost, char *hand, char *arg) { int atr = 0; char *args = NULL; UserList *n; if (!cmd) return; malloc_sprintf(&args, "%s%s%s", cmd, arg ?" ":"", arg?arg:""); if ((n = lookup_userlevelc("*",uhost, "*", NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_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); new_free(&args); } int check_on_hook(int which, char *buffer) { char name[BIG_BUFFER_SIZE]; if (!buffer || !*buffer) return 0; if (which > -1 && which < NUMBER_OF_LISTS) { Tcl_SetVar(tcl_interp, "_a", hook_functions[which].name, TCL_GLOBAL_ONLY); strcpy(name, hook_functions[which].name); } else { strcpy(name, ltoa(which)); Tcl_SetVar(tcl_interp, "_a", name, TCL_GLOBAL_ONLY); } strcat(name, " "); Tcl_SetVar(tcl_interp, "_aa", buffer, TCL_GLOBAL_ONLY); strlcat(name, buffer, sizeof name); return check_tcl_bind(&H_hook, name, -1, " $_a $_aa", MATCH_MASK | BIND_STACKABLE | BIND_WANTRET, NULL); } void check_tcl_join(char *nick,char *uhost, char *hand, char *channel) { int atr = 0; char args[BIG_BUFFER_SIZE+1]; UserList *n; if ((n = lookup_userlevelc("*", uhost, channel, NULL))) atr=n->flags; snprintf(args, sizeof args, "%s %s!%s", channel, nick, uhost); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",channel,TCL_GLOBAL_ONLY); check_tcl_bind(&H_join,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_part(char *nick, char *uhost, char *hand, char *chname) { int atr = 0; char args[BIG_BUFFER_SIZE+1]; UserList *n; int x; snprintf(args, sizeof args, "%s %s!%s", chname, nick, uhost); if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); x = check_tcl_bind(&H_part,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_sign(char *nick, char *uhost,char *hand, char *chname,char *reason) { int atr = 0; char args[BIG_BUFFER_SIZE+1]; UserList *n; if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; snprintf(args, sizeof args, "%s %s!%s", chname, nick, uhost); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",reason,TCL_GLOBAL_ONLY); check_tcl_bind(&H_sign,args,atr," $_n $_uh $_h $_a $_aa", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_topc(char *nick,char *uhost,char *hand,char *chname,char *topic) { int atr = 0; char args[BIG_BUFFER_SIZE+1]; UserList *n; snprintf(args, sizeof args, "%s %s", chname, topic); if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",topic,TCL_GLOBAL_ONLY); check_tcl_bind(&H_topc,args,atr," $_n $_uh $_h $_a $_aa", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_nick(char *nick,char *uhost,char *hand,char *chname, char *newnick) { int atr = 0; char args[BIG_BUFFER_SIZE]; UserList *n; if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; snprintf(args, sizeof args, "%s %s", chname, newnick); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",newnick,TCL_GLOBAL_ONLY); check_tcl_bind(&H_nick,args,atr," $_n $_uh $_h $_a $_aa", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_kick(char *nick,char *uhost,char *hand,char *chname,char *dest,char *reason) { char args[BIG_BUFFER_SIZE]; int atr = 0; UserList *n; if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; snprintf(args, sizeof args, "%s %s", chname, dest); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",dest,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aaa",reason,TCL_GLOBAL_ONLY); check_tcl_bind(&H_kick,args,atr," $_n $_uh $_h $_a $_aa $_aaa", MATCH_MASK|BIND_STACKABLE,NULL); } int check_tcl_raw(char *raw, char *comm) { int ret = 0; if (raw && *raw) { Tcl_SetVar(tcl_interp,"_a",raw,TCL_GLOBAL_ONLY); ret = check_tcl_bind(&H_raw,comm, -1," $_a",MATCH_MASK|BIND_STACKABLE|BIND_WANTRET,NULL); } return (ret == BIND_EXEC_LOG)? 1 : 0; } char *check_tcl_alias(char *command, char *args) { Tcl_SetVar(tcl_interp, "_a", args?args:empty_string, TCL_GLOBAL_ONLY); if (check_tcl_bind(&H_functions, command, -1, " $_a", MATCH_MASK|BIND_STACKABLE, NULL)) return m_strdup(tcl_interp->result?tcl_interp->result:empty_string); return NULL; } int check_tcl_input(char *raw) { int ret = 0; if (raw && *raw) { Tcl_SetVar(tcl_interp,"_a",raw,TCL_GLOBAL_ONLY); ret = check_tcl_bind(&H_input,raw, -1," $_a",MATCH_MASK|BIND_STACKABLE,NULL); } return (ret == BIND_EXEC_LOG)? 1 : 0; } int check_help_bind(char *command) { int x = 0; if (command && *command) { char *comm; comm = m_sprintf("%s_help", lower(command)); x=check_tcl_bind(&H_help,comm,-1,NULL, MATCH_EXACT|BIND_HAS_BUILTINS,NULL); new_free(&comm); } return (x ? 0 : 1); } void check_tcl_mode(char *nick,char *uhost,char *hand,char *chname,char *mode) { char args[BIG_BUFFER_SIZE+1]; UserList *n; n = lookup_userlevelc("*",uhost, chname, NULL); snprintf(args, sizeof args, "%s %s", chname, mode); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",mode,TCL_GLOBAL_ONLY); check_tcl_bind(&H_mode,args,0," $_n $_uh $_h $_a $_aa", MATCH_MASK|BIND_STACKABLE,NULL); } int check_tcl_ctcr(char *nick,char *uhost,char *hand,char *dest,char *keyword,char *args) { int atr = 0; UserList *n; if ((n = lookup_userlevelc("*",uhost, "*", NULL))) atr = n->flags; Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",dest,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_aa",keyword,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_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_chat(char *from,int chan,char *text) { Tcl_SetVar(tcl_interp,"_n",from,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",zero,TCL_GLOBAL_ONLY); /* chan 0 always */ Tcl_SetVar(tcl_interp,"_aa",text,TCL_GLOBAL_ONLY); check_tcl_bind(&H_chat,text,0," $_n $_a $_aa",MATCH_MASK|BIND_STACKABLE, NULL); } #if 0 void check_tcl_link(bot,via) char *bot,*via; { Tcl_SetVar(tcl_interp,"_n",bot,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_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(tcl_interp,"_n",bot,TCL_GLOBAL_ONLY); check_tcl_bind(&H_disc,bot,0," $_n",MATCH_MASK|BIND_STACKABLE,NULL); } #endif void check_tcl_split(char *nick,char *uhost,char *hand,char *chname) { int atr = 0; char args[BIG_BUFFER_SIZE+1]; UserList *n; if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; snprintf(args, sizeof args, "%s %s!%s", chname, nick, uhost); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); check_tcl_bind(&H_splt,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } void check_tcl_rejoin(char *nick,char *uhost,char *hand,char *chname) { int atr = 0; char args[BIG_BUFFER_SIZE+1]; UserList *n; if ((n = lookup_userlevelc("*",uhost, chname, NULL))) atr = n->flags; snprintf(args, sizeof args, "%s %s!%s", chname, nick, uhost); Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_uh",uhost,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",n?n->nick:hand,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",chname,TCL_GLOBAL_ONLY); check_tcl_bind(&H_rejn,args,atr," $_n $_uh $_h $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE,NULL); } #if 0 int check_tcl_filt(idx,text) int idx; char *text; { char s[10]; int x,atr; atr=get_attr_handle(dcc[idx].nick); snprintf(s, sizeof s, "%d", dcc[idx].sock); Tcl_SetVar(tcl_interp,"_n",s,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",text,TCL_GLOBAL_ONLY); x=check_tcl_bind(&H_filt,text,atr," $_n $_a", MATCH_MASK|BIND_USE_ATTR|BIND_STACKABLE|BIND_WANTRET,NULL); return (x==BIND_EXEC_LOG); } #endif void check_tcl_tand(char *nick, char *opcode, char *param) { Tcl_SetVar(tcl_interp,"_n",nick,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_h",opcode,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"_a",param,TCL_GLOBAL_ONLY); check_tcl_bind(&H_bot,opcode,0," $_n $_h $_a",MATCH_EXACT,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; case CMD_FILT: ht=&H_filt; nam="filt"; st=1; break; case CMD_CMD: ht = &H_cmd; nam = "cmd"; st = 1; break; case CMD_INPUT: ht=&H_input; nam = "input"; st = 1; break; case CMD_ALIAS: ht=&H_alias; nam = "alias"; st = 1; break; case CMD_HELP: ht=&H_help; nam = "help"; st = 1; break; case CMD_FUNCTION: ht=&H_functions; nam = "func"; st = 1; break; case CMD_HOOK: ht=&H_hook; nam = "hook"; st = 1; break; } if (name!=NULL) strcpy(name,nam); if (stk!=NULL) *stk=st; return ht; } int get_bind_type(char *name) { int tp = -1; if (!my_stricmp(name,"dcc")) tp=CMD_DCC; else if (!my_stricmp(name,"msg")) tp=CMD_MSG; else if (!my_stricmp(name,"fil")) tp=CMD_FIL; else if (!my_stricmp(name,"pub")) tp=CMD_PUB; else if (!my_stricmp(name,"msgm")) tp=CMD_MSGM; else if (!my_stricmp(name,"pubm")) tp=CMD_PUBM; else if (!my_stricmp(name,"join")) tp=CMD_JOIN; else if (!my_stricmp(name,"part")) tp=CMD_PART; else if (!my_stricmp(name,"sign")) tp=CMD_SIGN; else if (!my_stricmp(name,"kick")) tp=CMD_KICK; else if (!my_stricmp(name,"topc")) tp=CMD_TOPC; else if (!my_stricmp(name,"mode")) tp=CMD_MODE; else if (!my_stricmp(name,"ctcp")) tp=CMD_CTCP; else if (!my_stricmp(name,"ctcr")) tp=CMD_CTCR; else if (!my_stricmp(name,"nick")) tp=CMD_NICK; else if (!my_stricmp(name,"bot")) tp=CMD_BOT; else if (!my_stricmp(name,"chon")) tp=CMD_CHON; else if (!my_stricmp(name,"chof")) tp=CMD_CHOF; else if (!my_stricmp(name,"sent")) tp=CMD_SENT; else if (!my_stricmp(name,"rcvd")) tp=CMD_RCVD; else if (!my_stricmp(name,"chat")) tp=CMD_CHAT; else if (!my_stricmp(name,"link")) tp=CMD_LINK; else if (!my_stricmp(name,"disc")) tp=CMD_DISC; else if (!my_stricmp(name,"rejn")) tp=CMD_REJN; else if (!my_stricmp(name,"splt")) tp=CMD_SPLT; else if (!my_stricmp(name,"filt")) tp=CMD_FILT; else if (!my_stricmp(name, "raw")) tp =CMD_RAW; else if (!my_stricmp(name,"cmd")) tp = CMD_CMD; else if (!my_stricmp(name,"input")) tp = CMD_INPUT; else if (!my_stricmp(name,"alias")) tp = CMD_ALIAS; else if (!my_stricmp(name,"help")) tp = CMD_HELP; else if (!my_stricmp(name,"func")) tp = CMD_FUNCTION; else if (!my_stricmp(name, "hook")) tp = CMD_HOOK; return tp; } int tcl_bind STDVAR { int fl = 0,tp; BADARGS(5,5," type flags cmdName procName"); fl=convert_str_to_flags(argv[2]); tp=get_bind_type(argv[1]); if (tp<0) { Tcl_AppendResult(irp,"bad type, should be one of: dcc, msg, fil, pub, ", "msgm, pubm, join, part, sign, kick, topc, mode, ctcp, ", "nick, bot, chon, chof, sent, rcvd, chat, link, disc, ", "splt, rejn, filt, cmd, raw, input, alias, help, func, hook",NULL); return TCL_ERROR; } if ((long int)cd == 1) { if (!cmd_unbind(tp,fl,argv[3],argv[4])) { /* don't error if trying to re-unbind a builtin */ if (strcmp(argv[3],&argv[4][1])!=0) { Tcl_AppendResult(irp,"no such binding",NULL); return TCL_ERROR; } } } else { if (tp != CMD_ALIAS) cmd_bind(tp,fl,argv[3],argv[4], NULL); else { BuiltInFunctions *tmp; if ((tmp = find_func_alias(argv[4]))) cmd_bind(tp, fl, argv[3], argv[4], tmp->func); } } Tcl_AppendResult(irp,argv[3],NULL); return TCL_OK; } int tcl_tellbinds STDVAR { Tcl_HashEntry *he; Tcl_HashSearch srch; Tcl_HashTable *ht; int i,fnd=0; tcl_cmd_t *tt; char typ[5],*s,*proc; int kind = -1; if (argc > 1) kind = get_bind_type(argv[1]); for (i=0; ifunc_name; if ((proc[0]!='*') || (strcmp(s,proc+1)!=0)) put_it(" %-4s %-16s %-20s %s",typ,convert_flags_to_str(tt->flags_needed),s,tt->func_name); tt=tt->next; } } if (!fnd) { if (kind==(-1)) put_it("No TCL command bindings."); else put_it("No bindings for %s.",argv[1]); } } } return 0; } void tcl_init(void) { static int done = 0; if (tcl_interp != NULL && !done) { done++; #ifdef TCL_PLUS Tcl_InitStandAlone(tcl_interp); #else Tcl_Init(tcl_interp); #endif init_hash(); init_builtins(); init_public_tcl(tcl_interp); add_tcl_fset(tcl_interp); Tcl_SetVar(tcl_interp,"botnick",nickname,TCL_GLOBAL_ONLY); Tcl_SetVar(tcl_interp,"nick",nickname,TCL_GLOBAL_ONLY); } if (tcl_interp) init_public_var(tcl_interp); } static int tcl_echo = 1; BUILT_IN_COMMAND(tcl_version) { put_it("%s", convert_output_format("BitchX Tcl Interpreter %GVersion $1%n (c)1997 Colten Edwards", "%s", tcl_versionstr)); } BUILT_IN_COMMAND(tcl_command) { int result = 0; tcl_init(); if (args && *args) { if (*args == '-' && *(args + 1)) { char *bla; if (!my_strnicmp(args+1, "file", 4)) { bla = next_arg(args, &args); if (get_string_var(LOAD_PATH_VAR)) bla = path_search(args, get_string_var(LOAD_PATH_VAR)); if ((result = Tcl_EvalFile(tcl_interp, bla ? bla : args)) != TCL_OK) put_it("Tcl: [%s]",tcl_interp->result); else if (tcl_echo && *tcl_interp->result) put_it("Tcl: [%s]", tcl_interp->result); } else if (!my_strnicmp(args+1, "xecho", 4)) { tcl_echo = (tcl_echo ? 0:1); put_it("Tcl: xecho %s", tcl_echo?"on": "off"); } else if (!my_strnicmp(args+1, "version", 4)) tcl_version(NULL, NULL, NULL, NULL); else put_it("Tcl: unknown cmd [%s]", args); return; } if ((result = Tcl_Eval(tcl_interp, args)) != TCL_OK) put_it("Tcl: %s %s", args, tcl_interp->result); else if (tcl_echo && *tcl_interp->result) put_it("Tcl: [%s] %s", args, tcl_interp->result); } else { userage("tcl", "<-version | -file filename> "); tcl_version(NULL, NULL, NULL, NULL); } } int Tcl_Invoke(Tcl_Interp *irp, char *cmdname, char *rest) { int result = TCL_ERROR, argc = 0; char **ArgList; char *TrueArgs[41] = {NULL}; Tcl_CmdInfo info = {0}; char *p; char *copy; char *com; copy = LOCAL_COPY(rest); com = LOCAL_COPY(cmdname); ArgList = TrueArgs; ArgList[argc] = com; for (argc = 1; argc < 39; argc++) { p = new_next_arg(copy, ©); if (!p || !*p) break; ArgList[argc] = p; } if (copy && *copy) ArgList[argc] = copy; Tcl_ResetResult(irp); lower(com); if (internal_debug & DEBUG_TCL) debugyell("Invoking tcl [%s] with [%s]", com, rest); if (Tcl_GetCommandInfo(irp, com, &info) && info.proc) { result = (*info.proc)(info.clientData, irp, argc, ArgList); if (internal_debug & DEBUG_TCL) debugyell("Tcl returning with [%d]", result); } else Tcl_AppendResult(irp, "Unknown command \"", com, "\"", NULL); return result; } int tcl_cset STDVAR { extern char *set_cset(char *, ChannelList *, char *); ChannelList *chan = NULL; char *s = NULL; BADARGS(2, 4, " channel variable [value]"); if (!(chan = lookup_channel(argv[1], from_server, 0))) { Tcl_AppendResult(irp, "No such channel \"", argv[1], "\"", NULL); return TCL_ERROR; } if (argv[2]) { if (!(s = get_cset(argv[2], chan, NULL))) { Tcl_AppendResult(irp, "No such channel variable \"", argv[2], "\"", NULL); return TCL_ERROR; } } switch(argc) { case 2: /* no variable, do em all*/ break; case 3: /* variable name only */ break; case 4: /* set variable for channel */ if (set_cset(argv[2], chan, argv[3])) malloc_strcpy(&s, argv[3]); else { Tcl_AppendResult(irp, "Error setting variable \"", argv[2], "\"", NULL); new_free(&s); return TCL_ERROR; } break; } if (s) Tcl_AppendResult(irp, s, NULL); new_free(&s); return TCL_OK; } #endif #ifdef WANT_TCLMODULE int Tcl_Init() { } #endif