/* * functions.c -- Built-in functions for ircII * * Written by Michael Sandrof * Copyright(c) 1990 Michael Sandrof * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT * */ #include "irc.h" static char cvsrevision[] = "$Id$"; CVS_REVISION(functions_c) #include "struct.h" #include "alias.h" #include "alist.h" #include "array.h" #include "dcc.h" #include "commands.h" #include "files.h" #include "history.h" #include "hook.h" #include "ignore.h" #include "input.h" #include "ircaux.h" #include "names.h" #include "output.h" #include "list.h" #include "parse.h" #include "screen.h" #include "server.h" #include "status.h" #include "vars.h" #include "window.h" #include "ircterm.h" #include "notify.h" #include "misc.h" #include "userlist.h" #include "numbers.h" #include "ignore.h" #include "hash2.h" #include "struct.h" #include "cset.h" #include "log.h" #include "gui.h" #define MAIN_SOURCE #include "modval.h" #include "options.h" #include #ifdef HAVE_REGEX_H #include #endif #ifdef HAVE_UNAME #include #endif #ifdef WANT_HEBREW #include "hebrew.h" #endif #include "tcl_bx.h" static char *alias_detected (void); static char *alias_sent_nick (void); static char *alias_recv_nick (void); static char *alias_msg_body (void); static char *alias_joined_nick (void); static char *alias_public_nick (void); static char *alias_dollar (void); static char *alias_channel (void); static char *alias_server (void); static char *alias_query_nick (void); static char *alias_target (void); static char *alias_nick (void); static char *alias_invite (void); static char *alias_cmdchar (void); static char *alias_line (void); static char *alias_away (void); static char *alias_oper (void); static char *alias_chanop (void); static char *alias_modes (void); static char *alias_buffer (void); static char *alias_time (void); static char *alias_version (void); static char *alias_currdir (void); static char *alias_current_numeric (void); static char *alias_server_version (void); static char *alias_show_userhost (void); static char *alias_show_realname (void); static char *alias_online (void); static char *alias_idle (void); static char *alias_version_str (void); static char *alias_version_str1 (void); static char *alias_thingansi (void); static char *alias_uptime (void); static char *alias_serverport (void); static char *alias_tclsupport (void); static char *alias_current_network (void); static char *alias_bitchx (void); static char *alias_hookname (void); static char *alias_awaytime (void); static char *alias_thisaliasname (void); static char *alias_serverlag (void); static char *alias_currentwindow (void); static char *alias_serverlistsize (void); typedef struct { char name; char *(*func) (void); } BuiltIns; static BuiltIns built_in[] = { { '.', alias_sent_nick }, { ',', alias_recv_nick }, { ':', alias_joined_nick }, { ';', alias_public_nick }, { '`', alias_uptime }, { '$', alias_dollar }, { 'A', alias_away }, { 'B', alias_msg_body }, { 'C', alias_channel }, { 'D', alias_detected }, { 'E', alias_idle }, { 'F', alias_online }, { 'G', alias_thingansi }, { 'H', alias_current_numeric }, { 'I', alias_invite }, { 'J', alias_version_str }, { 'K', alias_cmdchar }, { 'L', alias_line }, { 'M', alias_modes }, { 'N', alias_nick }, { 'O', alias_oper }, { 'P', alias_chanop }, { 'Q', alias_query_nick }, { 'R', alias_server_version }, { 'S', alias_server }, { 'T', alias_target }, { 'U', alias_buffer }, { 'V', alias_version }, { 'W', alias_currdir }, { 'X', alias_show_userhost }, { 'Y', alias_show_realname }, { 'Z', alias_time }, { 'a', alias_version_str1 }, { 'b', alias_bitchx }, { 'h', alias_hookname }, { 'l', alias_serverlag }, { 'n', alias_current_network }, { 's', alias_serverport }, { 't', alias_thisaliasname }, { 'u', alias_awaytime }, { 'v', alias_tclsupport }, { 'w', alias_currentwindow }, { 'z', alias_serverlistsize }, { 0, NULL } }; /* the 30 "standard" functions */ static char *function_channels (char *, char *); static char *function_connect (char *, char *); static char *function_curpos (char *, char *); char *function_decode (char *, unsigned char *); static char *function_encode (char *, unsigned char *); static char *function_index (char *, char *); static char *function_ischannel (char *, char *); static char *function_ischanop (char *, char *); static char *function_ishalfop (char *, char *); static char *function_left (char *, char *); static char *function_listen (char *, char *); static char *function_match (char *, char *); static char *function_mid (char *, char *); static char *function_notify (char *, char *); static char *function_pid (char *, char *); static char *function_ppid (char *, char *); static char *function_rand (char *, char *); static char *function_right (char *, char *); static char *function_rindex (char *, char *); static char *function_rmatch (char *, char *); static char *function_servers (char *, char *); static char *function_srand (char *, char *); static char *function_stime (char *, char *); static char *function_strip (char *, char *); static char *function_tdiff (char *, char *); static char *function_tdiff2 (char *, char *); static char *function_time (char *, char *); static char *function_tolower (char *, char *); static char *function_toupper (char *, char *); static char *function_userhost (char *, char *); static char *function_winnum (char *, char *); static char *function_winnam (char *, char *); static char *function_winnames (char *, char *); static char *function_word (char *, char *); static char *function_utime (char *, char *); static char *function_umode (char *, char *); /* CDE added functions */ static char *function_uptime (char *, char *); static char *function_cluster (char *, char *); static char *function_checkshit (char *, char *); static char *function_checkuser (char *, char *); static char *function_rot13 (char *, char *); char *function_addtabkey (char *, char *); char *function_gettabkey (char *, char *); static char *function_lastnotice (char *, char *); static char *function_lastmessage (char *, char *); static char *function_help (char *, char *); static char *function_isuser (char *, char *); /* Thanks Jordy */ static char *function_pad (char *, char *); static char *function_isban (char *, char *); static char *function_isop (char *, char *); static char *function_isvoice (char *, char *); static char *function_randomnick (char *, char *); static char *function_openserver (char *, char *); static char *function_readserver (char *, char *); static char *function_readchar (char *, char *); static char *function_writeserver (char *, char *); static char *function_closeserver (char *, char *); static char *function_getreason (char *, char *); /* the 53 "extended" functions */ static char * function_after (char *, char *); static char * function_afterw (char *, char *); static char * function_aliasctl (char *, char *); static char * function_ascii (char *, char *); static char * function_before (char *, char *); static char * function_beforew (char *, char *); static char * function_center (char *, char *); static char * function_cexist (char *, char *); static char * function_currchans (char *, char *); static char * function_channelmode (char *, char *); static char * function_channelnicks (char *, char *); static char * function_chngw (char *, char *); static char * function_chop (char *, char *); static char * function_chops (char *, char *); static char * function_chr (char *, char *); static char * function_close (char *, char *); static char * function_common (char *, char *); static char * function_convert (char *, char *); static char * function_copattern (char *, char *); static char * function_crypt (char *, char *); static char * function_diff (char *, char *); static char * function_epic (char *, char *); static char * function_eof (char *, char *); static char * function_fnexist (char *, char *); static char * function_glob (char *, char *); static char * function_fexist (char *, char *); static char * function_filter (char *, char *); static char * function_fromw (char *, char *); static char * function_fsize (char *, char *); static char * function_geom (char *, char *); static char * function_info (char *, char *); static char * function_insertw (char *, char *); static char * function_iptoname (char *, char *); static char * function_isalpha (char *, char *); static char * function_isdigit (char *, char *); static char * function_jot (char *, char *); static char * function_key (char *, char *); static char * function_lastserver (char *, char *); static char * function_leftw (char *, char *); static char * function_mkdir (char *, char *); static char * function_midw (char *, char *); static char * function_nametoip (char *, char *); static char * function_nochops (char *, char *); static char * function_notw (char *, char *); static char * function_numonchannel (char *, char *); static char * function_numwords (char *, char *); static char * function_numsort (char *, char *); static char * function_onchannel (char *, char *); static char * function_open (char *, char *); static char * function_pass (char *, char *); static char * function_pattern (char *, char *); static char * function_read (char *, char *); static char * function_remw (char *, char *); static char * function_rename (char *, char *); static char * function_restw (char *, char *); static char * function_reverse (char *, char *); static char * function_revw (char *, char *); static char * function_rfilter (char *, char *); static char * function_rightw (char *, char *); static char * function_rmdir (char *, char *); static char * function_rpattern (char *, char *); static char * function_sar (char *, char *); static char * function_server_version (char *, char *); static char * function_servername (char *, char *); static char * function_sort (char *, char *); static char * function_split (char *, char *); static char * function_splice (char *, char *); static char * function_stripansi (char *, char *); static char * function_stripansicodes (char *, char *); static char * function_strftime (char *, char *); static char * function_strlen (char *, char *); static char * function_tow (char *, char *); static char * function_translate (char *, char *); static char * function_truncate (char *, char *); static char * function_unlink (char *, char *); static char * function_umask (char *, char *); static char * function_which (char *, char *); static char * function_winserv (char *, char *); static char * function_winsize (char *, char *); static char * function_write (char *, char *); static char * function_writeb (char *, char *); static char * function_idle (char *, char *); static char * function_repeat (char *, char *); static char * function_bcopy (char *, char *); char * function_cparse (char *, char *); static char * function_chmod (char *, char *); static char * function_twiddle (char *, char *); static char * function_uniq (char *, char *); static char * function_uhost (char *, char *); static char * function_numdiff (char *, char *); char * function_getkey (char *, char *); static char * function_winvisible (char *, char *); static char * function_mircansi (char *, char *); static char * function_banonchannel (char *, char *); static char * function_chanwin (char *, char *); static char * function_gethost (char *, char *); static char * function_getenv (char *, char *); static char * function_getvar (char *, char *); static char * function_status (char *, char *); char * function_push (char *, char *); char * function_pop (char *, char *); char * function_shift (char *, char *); char * function_unshift (char *, char *); static char * function_get_info (char *, char *); static char * function_set_info (char *, char *); static char * function_statsparse (char *, char *); static char * function_absstrlen (char *, char *); static char * function_findw (char *, char *); static char * function_countansi (char *, char *); static char * function_strstr (char *, char *); static char * function_substr (char *, char *); static char * function_longip (char *, char *); static char * function_iplong (char *, char *); static char * function_rword (char *, char *); static char * function_winlen (char *, char *); static char * function_isignored (char *, char *); static char * function_channel (char *, char *); static char * function_ftime (char *, char *); static char * function_irclib (char *, char *); static char * function_winbound (char *, char *); static char * function_rstrstr (char *, char *); static char * function_rsubstr (char *, char *); static char * function_country (char *, char *); static char * function_servernick (char *, char *); static char * function_fparse (char *, char *); static char * function_isconnected (char *, char *); static char * function_bmatch (char *, char *); static char * function_regcomp (char *, char *); static char * function_regexec (char *, char *); static char * function_regerror (char *, char *); static char * function_regfree (char *, char *); char * function_cdcc (char *, char *); char * function_sendcdcc (char *, char *); static char * function_count (char *, char *); static char * function_msar (char *, char *); static char * function_getcset (char *, char *); static char * function_leftpc (char *, char *); static char * function_mask (char *, char *); static char * function_querywin (char *, char *); static char * function_uname (char *, char *); static char * function_winrefs (char *, char *); static char * function_getgid (char *, char *); static char * function_getlogin (char *, char *); static char * function_getpgrp (char *, char *); static char * function_getuid (char *, char *); static char * function_iscurchan (char *, char *); static char * function_remws (char *, char *); static char * function_uhc (char *, char *); static char * function_deuhc (char *, char *); static char * function_getfsets (char *, char *); static char * function_rest (char *, char *); static char * function_isnumber (char *, char *); static char * function_getsets (char *, char *); static char * function_servref (char *, char *); static char * function_getflags (char *, char *); static char * function_numlines (char *, char *); static char * function_winlevel (char *, char *); static char * function_stripc (char *, char *); static char * function_topic (char *, char *); static char * function_stripcrap (char *, char *); #if 0 static char * function_parse_and_return (char *, char *); #endif static char * function_dccitem (char *, char *); static char * function_winitem (char *, char *); static char * function_servgroup (char *, char *); static char * function_ajoinitem (char *, char *); static char * function_long_to_comma (char *, char *); static char * function_nohighlight (char *, char *); static char * function_getopt (char *, char *); static char * function_isaway (char *, char *); static char * function_banwords (char *, char *); static char * function_hash_32bit (char *, char *); static char * function_nickcomp (char *, char *); static char * function_filecomp (char *, char *); static char * function_log (char *, char *); static char * function_indextoword (char *, char *); static char * function_ttyname (char *, char *); static char * function_functioncall (char *, char *); static char * function_prefix (char *, char *); static char * function_stat (char *, char *); static char * function_maxlen (char *, char *); static char * function_insert (char *, char *); static char * function_realpath (char *, char *); static char * function_serverlag (char *, char *); static char * function_servports (char *, char *); static char * function_isalnum (char *, char *); static char * function_isspace (char *, char *); static char * function_isxdigit (char *, char *); static char * function_serverpass (char *, char *); static char * function_igmask (char *, char *); static char * function_rigmask (char *, char *); static char * function_igtype (char *, char *); static char * function_rigtype (char *, char *); extern char * function_istimer (char *, char *); static char * function_strchar (char *, char *); static char * function_watch (char *, char *); static char * function_getcap (char *, char *); static char * function_isdisplaying (char *, char *); static char * function_getset (char *, char *); static char * function_builtin (char *, char *); extern char * function_timer (char *, char *); static char * function_runlevel (char *, char *); static char * function_ovserver (char *, char *); #ifdef GUI static char * function_mciapi (char *, char *); static char * function_lastclickline (char *, char *); static char * function_lastclickx (char *, char *); static char * function_lastclicky (char *, char *); static char * function_screensize (char *, char *); static char * function_menucontrol (char *, char *); #endif static char * function_ipv6 (char *, char *); #undef BUILT_IN_FUNCTION #define BUILT_IN_FUNCTION(x, y) static char * x (char *fn, char * y) /* * This is the built-in function list. This list *must* be sorted because * it is binary searched. See the code for each function to see how it * is used. Or see the help files. Or see both. Or look at the code * and see how it REALLY works, irregardless of the documentation >;-) */ static BuiltInFunctions built_in_functions[] = { { "ABSSTRLEN", function_absstrlen }, { "ADDTABKEY", function_addtabkey }, { "AFTER", function_after }, { "AFTERW", function_afterw }, { "AJOINITEM", function_ajoinitem }, { "ALIASCTL", function_aliasctl }, { "ASCII", function_ascii }, { "BANONCHANNEL", function_banonchannel }, { "BANWORDS", function_banwords }, { "BCOPY", function_bcopy }, { "BEFORE", function_before }, { "BEFOREW", function_beforew }, { "BITCHX", function_epic }, { "BMATCH", function_bmatch }, { "BUILTIN_EXPANDO", function_builtin }, { "CENTER", function_center }, { "CEXIST", function_cexist }, { "CHANMODE", function_channelmode }, { "CHANNEL", function_channel }, { "CHANNICKS", function_channelnicks }, { "CHANUSERS", function_onchannel }, { "CHANWIN", function_chanwin }, { "CHANWINDOW", function_chanwin }, { "CHECKSHIT", function_checkshit }, { "CHECKUSER", function_checkuser }, { "CHMOD", function_chmod }, { "CHNGW", function_chngw }, { "CHOP", function_chop }, { "CHOPS", function_chops }, { "CHR", function_chr }, { "CLOSE", function_close }, #ifndef BITCHX_LITE { "CLOSESOCKET", function_closeserver }, #endif { "CLUSTER", function_cluster }, { "COMMON", function_common }, { "CONNECT", function_connect }, { "CONVERT", function_convert }, { "COPATTERN", function_copattern }, { "COUNT", function_count }, { "COUNTANSI", function_countansi }, { "COUNTRY", function_country }, { "CPARSE", function_cparse }, { "CRYPT", function_crypt }, { "CURPOS", function_curpos }, { "CURRCHANS", function_currchans }, { "DCCITEM", function_dccitem }, { "DECODE", (bf *)function_decode }, { "DELARRAY", function_delarray }, { "DELITEM", function_delitem }, { "DEUHC", function_deuhc }, { "DIFF", function_diff }, { "ENCODE", (bf *)function_encode }, { "EOF", function_eof }, { "EPIC", function_epic }, { "FEXIST", function_fexist }, { "FILECOMP", function_filecomp }, { "FILTER", function_filter }, { "FINDITEM", function_finditem }, { "FINDW", function_findw }, { "FNEXIST", function_fnexist }, { "FPARSE", function_fparse }, { "FROMW", function_fromw }, { "FSIZE", function_fsize }, { "FTIME", function_ftime }, { "FUNCTIONCALL", function_functioncall }, { "GEOM", function_geom }, { "GETARRAYS", function_getarrays }, { "GETCAP", function_getcap }, { "GETCDCC", function_cdcc }, { "GETCSET", function_getcset }, { "GETGID", function_getgid }, { "GETENV", function_getenv }, { "GETFLAGS", function_getflags }, { "GETFSETS", function_getfsets }, { "GETHOST", function_gethost }, { "GETINFO", function_get_info }, { "GETITEM", function_getitem }, { "GETKEY", function_getkey }, { "GETLOGIN", function_getlogin }, { "GETMATCHES", function_getmatches }, { "GETOPT", function_getopt }, { "GETPGRP", function_getpgrp }, { "GETREASON", function_getreason }, { "GETRMATCHES", function_getrmatches }, { "GETSET", function_getset }, { "GETSETS", function_getsets }, { "GETTABKEY", function_gettabkey }, { "GETTMATCH", function_gettmatch }, { "GETUID", function_getuid }, { "GETVAR", function_getvar }, { "GLOB", function_glob }, #ifdef GTK { "GTKBITCHX", function_epic }, #endif { "HASH_32BIT", function_hash_32bit }, { "HELP", function_help }, { "IDLE", function_idle }, { "IFINDFIRST", function_ifindfirst }, { "IFINDITEM", function_ifinditem }, { "IGETITEM", function_igetitem }, { "IGETMATCHES", function_igetmatches }, { "IGMASK", function_igmask }, { "IGTYPE", function_igtype }, { "INDEX", function_index }, { "INDEXTOITEM", function_indextoitem }, { "INDEXTOWORD", function_indextoword }, { "INFO", function_info }, { "INSERT", function_insert }, { "INSERTW", function_insertw }, { "IPLONG", function_iplong }, { "IPTONAME", function_iptoname }, { "IPV6", function_ipv6 }, { "IRCLIB", function_irclib }, { "ISALNUM", function_isalnum }, { "ISALPHA", function_isalpha }, { "ISAWAY", function_isaway }, { "ISBAN", function_isban }, { "ISCHANNEL", function_ischannel }, { "ISCHANOP", function_ischanop }, { "ISCHANVOICE", function_isvoice }, { "ISCONNECTED", function_isconnected }, { "ISCURCHAN", function_iscurchan }, { "ISDIGIT", function_isdigit }, { "ISDISPLAYING", function_isdisplaying }, { "ISHALFOP", function_ishalfop }, { "ISIGNORED", function_isignored }, { "ISNUMBER", function_isnumber }, { "ISOP", function_isop }, { "ISSPACE", function_isspace }, { "ISTIMER", function_istimer }, { "ISUSER", function_isuser }, { "ISVOICE", function_isvoice }, { "ISXDIGIT", function_isxdigit }, { "ITEMTOINDEX", function_itemtoindex }, { "JOT", function_jot }, { "KEY", function_key }, { "LAG", function_serverlag }, #ifdef GUI { "LASTCLICKLINE", function_lastclickline }, { "LASTCLICKX", function_lastclickx }, { "LASTCLICKY", function_lastclicky }, #endif { "LASTLOG", function_lastlog }, { "LASTMESSAGE", function_lastmessage }, { "LASTNOTICE", function_lastnotice }, { "LASTSERVER", function_lastserver }, { "LEFT", function_left }, { "LEFTPC", function_leftpc }, { "LEFTW", function_leftw }, { "LENGTH", function_strlen }, { "LINE", function_line }, { "LISTARRAY", function_listarray }, { "LISTEN", function_listen }, { "LOG", function_log }, { "LONGCOMMA", function_long_to_comma }, { "LONGIP", function_longip }, { "MASK", function_mask }, { "MATCH", function_match }, { "MATCHITEM", function_matchitem }, { "MAXLEN", function_maxlen }, #ifdef GUI { "MCIAPI", function_mciapi }, { "MENUCONTROL", function_menucontrol }, #endif { "MID", function_mid }, { "MIDW", function_midw }, #ifndef BITCHX_LITE { "MIRCANSI", function_mircansi }, #endif { "MKDIR", function_mkdir }, { "MSAR", function_msar }, { "MYCHANNELS", function_channels }, { "MYSERVERS", function_servers }, { "NAMETOIP", function_nametoip }, { "NICKCOMP", function_nickcomp }, { "NOCHOPS", function_nochops }, { "NOHIGHLIGHT", function_nohighlight }, { "NOTIFY", function_notify }, { "NOTW", function_notw }, { "NUMARRAYS", function_numarrays }, { "NUMDIFF", function_numdiff }, { "NUMITEMS", function_numitems }, { "NUMLINES", function_numlines }, { "NUMONCHANNEL", function_numonchannel }, { "NUMSORT", function_numsort }, { "NUMWORDS", function_numwords }, { "ONCHANNEL", function_onchannel }, { "OPEN", function_open }, #ifndef BITCHX_LITE { "OPENSOCKET", function_openserver }, #endif { "OVSERVER", function_ovserver }, { "PAD", function_pad }, #if 0 { "PARSE", function_parse_and_return}, #endif { "PASS", function_pass }, { "PATTERN", function_pattern }, { "PID", function_pid }, #ifdef __EMXPM__ { "PMBITCHX", function_epic }, #endif { "POP", function_pop }, { "PPID", function_ppid }, { "PREFIX", function_prefix }, { "PRINTLEN", function_countansi }, { "PUSH", function_push }, { "QUERYWIN", function_querywin }, { "RAND", function_rand }, { "RANDOMNICK", function_randomnick }, { "READ", function_read }, { "REALPATH", function_realpath }, { "REGCOMP", function_regcomp }, { "REGERROR", function_regerror }, { "REGEXEC", function_regexec }, { "REGFREE", function_regfree }, #ifndef BITCHX_LITE { "READCHAR", function_readchar }, { "READSOCKET", function_readserver }, #endif { "REMW", function_remw }, { "REMWS", function_remws }, { "RENAME", function_rename }, { "REPEAT", function_repeat }, { "REST", function_rest }, { "RESTW", function_restw }, { "REVERSE", function_reverse }, { "REVW", function_revw }, { "RFILTER", function_rfilter }, { "RIGHT", function_right }, { "RIGHTW", function_rightw }, { "RIGMASK", function_rigmask }, { "RIGTYPE", function_rigtype }, { "RINDEX", function_rindex }, { "RMATCH", function_rmatch }, { "RMATCHITEM", function_rmatchitem }, { "RMDIR", function_rmdir }, { "ROT13", function_rot13 }, { "RPATTERN", function_rpattern }, { "RSTRSTR", function_rstrstr }, { "RSUBSTR", function_rsubstr }, { "RUNLEVEL", function_runlevel }, { "RWORD", function_rword }, { "SAR", function_sar }, #ifdef GUI { "SCREENSIZE", function_screensize }, #endif { "SENDCDCC", function_sendcdcc }, { "SERVERGROUP", function_servgroup }, { "SERVERNAME", function_servername }, { "SERVERNICK", function_servernick }, { "SERVERNUM", function_servref }, { "SERVERPASS", function_serverpass }, { "SERVPORTS", function_servports }, { "SETINFO", function_set_info }, { "SERVERPORT", function_servports }, { "SETITEM", function_setitem }, { "SHIFT", function_shift }, { "SORT", function_sort }, { "SPLICE", function_splice }, { "SPLIT", function_split }, { "SRAND", function_srand }, { "STAT", function_stat }, { "STATSPARSE", function_statsparse }, { "STATUS", function_status }, { "STIME", function_stime }, { "STRCHR", function_strchar }, { "STRFTIME", function_strftime }, { "STRIP", function_strip }, { "STRIPANSI", function_stripansi }, { "STRIPANSICODES", function_stripansicodes }, { "STRIPC", function_stripc }, { "STRIPCRAP", function_stripcrap }, #ifndef BITCHX_LITE { "STRIPMIRC", function_stripc }, #endif { "STRLEN", function_strlen }, { "STRRCHR", function_strchar }, { "STRSTR", function_strstr }, { "SUBSTR", function_substr }, { "TDIFF", function_tdiff }, { "TDIFF2", function_tdiff2 }, { "TIME", function_time }, { "TIMER", function_timer }, { "TIMEREXISTS", function_istimer }, { "TOLOWER", function_tolower }, { "TOPIC", function_topic }, { "TOUPPER", function_toupper }, { "TOW", function_tow }, { "TR", function_translate }, { "TRUNC", function_truncate }, { "TTYNAME", function_ttyname }, { "TWIDDLE", function_twiddle }, { "UHC", function_uhc }, { "UHOST", function_uhost }, { "UMASK", function_umask }, { "UNAME", function_uname }, { "UNIQ", function_uniq }, { "UNLINK", function_unlink }, { "UNSHIFT", function_unshift }, { "UPTIME", function_uptime }, { "USERHOST", function_userhost }, { "USERMODE", function_umode }, { "UTIME", function_utime }, { "VERSION", function_server_version }, { "WATCH", function_watch }, { "WHICH", function_which }, { "WINBOUND", function_winbound }, { "WINCHAN", function_chanwin }, { "WINITEM", function_winitem }, { "WINLEN", function_winlen }, { "WINLEVEL", function_winlevel }, { "WINNAM", function_winnam }, { "WINNICKLIST", function_winnames }, { "WINNUM", function_winnum }, { "WINREFS", function_winrefs }, { "WINSERV", function_winserv }, { "WINSIZE", function_winsize }, { "WINVISIBLE", function_winvisible }, { "WORD", function_word }, { "WRITE", function_write }, { "WRITEB", function_writeb }, #ifndef BITCHX_LITE { "WRITESOCKET", function_writeserver }, #endif { NULL, NULL } }; #define NUMBER_OF_FUNCTIONS (sizeof(built_in_functions) / sizeof(BuiltInFunctions)) - 2 #include "hash2.h" #define FUNCTION_HASHSIZE 251 HashEntry functions[FUNCTION_HASHSIZE] = { { NULL } }; int done_init_functions = 0; static int func_exist (char *name) { int cnt, pos; char *tmp; tmp = LOCAL_COPY(name); upper(tmp); find_fixed_array_item(built_in_functions, sizeof(BuiltInFunctions), NUMBER_OF_FUNCTIONS + 1, tmp, &cnt, &pos); if (cnt < 0) return 1; return 0; } int in_cparse = 0; #ifdef WANT_TCL void add_tcl_alias (Tcl_Interp *tcl_interp, void *func1, void *func2) { int i = 0; char str[80]; while (built_in_functions[i].func) { snprintf(str, sizeof str, "_%s", built_in_functions[i].name); Tcl_CreateCommand(tcl_interp, lower(str), func1?func1:built_in_functions[i].func, NULL, NULL); i++; } i = 0; while (built_in[i].func) { snprintf(str, sizeof str, "_%c", built_in[i].name); Tcl_CreateCommand(tcl_interp, str, func2?func2:built_in[i].func, NULL, NULL); i++; } } #endif typedef struct _built_in_new { struct _built_in_new *next; char *name; char *(*func)(char *, char *); } NewBuiltInFunctions; static inline void move_link_to_top(NewBuiltInFunctions *tmp, NewBuiltInFunctions *prev, HashEntry *location) { if (prev) { NewBuiltInFunctions *old_list; old_list = (NewBuiltInFunctions *) location->list; location->list = (void *) tmp; prev->next = tmp->next; tmp->next = old_list; } } static void init_functions(void) { int i; unsigned long hash; NewBuiltInFunctions *new; for (i = 0; i <= NUMBER_OF_FUNCTIONS; i++) { if (!built_in_functions[i].func) break; hash = hash_nickname(built_in_functions[i].name, FUNCTION_HASHSIZE); new = (NewBuiltInFunctions *)new_malloc(sizeof(NewBuiltInFunctions)); new->name = built_in_functions[i].name; new->func = built_in_functions[i].func; new->next = (NewBuiltInFunctions *)functions[hash].list; functions[hash].list = (void *) new; functions[hash].links++; } done_init_functions++; } BUILT_IN_COMMAND(debugfunc) { NewBuiltInFunctions *ptr; int i; for (i = 0; i < FUNCTION_HASHSIZE; i++) { if (!(ptr = (NewBuiltInFunctions *)functions[i].list)) continue; while (ptr) { put_it("DEBUG_FUNC[%d]: %s %d links %d hits", i, ptr->name, functions[i].links, functions[i].hits); ptr = ptr->next; } } } BuiltIns *find_func_aliasvar(char *name) { BuiltIns *tmp = NULL; int i = 0; while (built_in[i].func) { if (!(*name == built_in[i].name)) { i++; continue; } tmp = &built_in[i]; break; } return tmp; } BuiltInFunctions *find_func_alias(char *name) { unsigned long hash = 0; HashEntry *location; register NewBuiltInFunctions *tmp, *prev = NULL; static BuiltInFunctions new; if (!done_init_functions) init_functions(); hash = hash_nickname(name, FUNCTION_HASHSIZE); location = &functions[hash]; for (tmp = (NewBuiltInFunctions *)location->list; tmp; tmp = tmp->next) { if (!my_stricmp(name, tmp->name)) { move_link_to_top(tmp, prev, location); location->hits++; new.name = tmp->name; new.func = tmp->func; return &new; } } return NULL; #if 0 while (built_in_functions[i].func && i <= NUMBER_OF_FUNCTIONS) { if (!my_stricmp(name, built_in_functions[i].name)) return &built_in_functions[i]; i++; } #endif return NULL; } char **get_builtins(char *name, int *cnt) { char *last_match = NULL; int matches_size = 5; int i = 0; int len; char **matches = NULL; #ifdef WANT_DLL BuiltInDllFunctions *dll = NULL; #endif len = strlen(name); *cnt = 0; RESIZE(matches, char *, matches_size); while (built_in_functions[i].func && i <= NUMBER_OF_FUNCTIONS) { if (strncmp(name, built_in_functions[i].name, len) == 0) { matches[*cnt] = NULL; malloc_strcpy(&(matches[*cnt]), built_in_functions[i].name); last_match = matches[*cnt]; if (++(*cnt) == matches_size) { matches_size += 5; RESIZE(matches, char *, matches_size); } } else if (*cnt) break; i++; } #ifdef WANT_DLL for (dll = dll_functions; dll; dll = dll->next) { if (strncasecmp(name, dll->name, len) == 0) { matches[*cnt] = NULL; malloc_strcpy(&(matches[*cnt]), dll->name); if (++(*cnt) == matches_size) { matches_size += 5; RESIZE(matches, char *, matches_size); } } } #endif return matches; } char *built_in_alias (char c, int *returnval) { BuiltIns *tmp; for (tmp = built_in;tmp->name;tmp++) { if (c == tmp->name) { if (returnval) { *returnval = 1; return NULL; } else return tmp->func(); } } return NULL; } char *call_function (char *name, const char *args, int *args_flag) { extern char *check_tcl_alias (char *command, char *args); char *tmp; char *result = NULL; char *debug_copy = NULL; BuiltInFunctions *funcptr = NULL; #ifdef WANT_DLL register BuiltInDllFunctions *dll = NULL; #endif char *lparen, *rparen; if ((lparen = strchr(name, '('))) { if ((rparen = MatchingBracket(lparen + 1, '(', ')'))) *rparen++ = 0; else debugyell("Unmatched lparen in function call [%s]", name); *lparen++ = 0; } else lparen = empty_string; tmp = expand_alias(lparen, args, args_flag, NULL); if ((internal_debug & DEBUG_FUNC) && !in_debug_yell) debug_copy = LOCAL_COPY(tmp); upper(name); #ifdef WANT_DLL for (dll = dll_functions; dll; dll = dll->next) if (!strcasecmp(name, dll->name)) break; if (dll) result = (dll->func)(name, tmp); else #endif { #ifdef WANT_TCL if (!(result = check_tcl_alias(name, tmp))) #endif { if ((funcptr = find_func_alias(name))) result = funcptr->func(name, tmp); else result = call_user_function(name, tmp); } } if (debug_copy && alias_debug) { #if 0 if (!alias_debug) debugyell("Function %s(%s) returned %s", name, debug_copy, result); else #endif debugyell("%3d %s(%s) -> %s", debug_count++, name, debug_copy, result); } new_free(&tmp); return result; } extern char hook_name[]; /* built in expando functions */ static char *alias_version_str1 (void) { return m_strdup(_VERSION_); } static char *alias_line (void) { return m_strdup(get_input()); } static char *alias_buffer (void) { return m_strdup(cut_buffer); } static char *alias_time (void) { return m_strdup(update_clock(GET_TIME)); } static char *alias_dollar (void) { return m_strdup("$"); } static char *alias_detected (void) { return m_strdup(last_notify_nick); } static char *alias_nick (void) { return m_strdup((current_window->server != -1? get_server_nickname(current_window->server) : empty_string)); } char *alias_away (void) { return m_strdup(get_server_away(from_server)); } static char *alias_sent_nick (void) { return m_strdup(get_server_sent_nick(from_server)); } static char *alias_recv_nick (void) { return m_strdup(get_server_recv_nick(from_server)); } static char *alias_msg_body (void) { return m_strdup(get_server_sent_body(from_server)); } static char *alias_joined_nick (void) { return m_strdup((joined_nick) ? joined_nick : empty_string); } static char *alias_public_nick (void) { return m_strdup((public_nick) ? public_nick : empty_string); } static char *alias_show_realname (void) { return m_strdup(realname); } static char *alias_version_str (void) { return m_strdup(irc_version); } static char *alias_invite (void) { return m_strdup((invite_channel) ? invite_channel : empty_string); } static char *alias_oper (void) { return m_strdup(get_server_operator(from_server) ? get_string_var(STATUS_OPER_VAR) : empty_string); } static char *alias_version (void) { return m_strdup(internal_version); } static char *alias_online (void) { return m_sprintf("%ld",(long)start_time); } static char *alias_idle (void) { return m_sprintf("%ld",(long)(now - idle_time)); } static char *alias_show_userhost (void) { return m_strdup(get_server_userhost(from_server)); } static char *alias_current_numeric (void) { return m_sprintf("%03d", -current_numeric); } static char *alias_hookname (void) { return m_sprintf("%s", *hook_name?hook_name:empty_string); } static char *alias_thingansi (void) { return m_strdup(numeric_banner()); } static char *alias_uptime (void) { return m_sprintf("%s", convert_time(now-start_time)); } static char *alias_bitchx (void) { return m_strdup("[BX]"); } extern char *return_this_alias (void); static char *alias_thisaliasname (void) { return m_strdup(return_this_alias()); } static char *alias_serverlag (void) { return m_sprintf("%d", get_server_lag(from_server)); } static char *alias_currentwindow (void) { return m_sprintf("%d", current_window ? current_window->refnum : 0); } static char *alias_serverlistsize (void) { return m_sprintf("%d", server_list_size()); } #ifdef WANT_TCL extern char tcl_versionstr[]; static char *alias_tclsupport (void) { return m_strdup(tcl_versionstr); } #else static char *alias_tclsupport (void) { return m_strdup(empty_string); } #endif static char *alias_currdir (void) { char *tmp = (char *)new_malloc(MAXPATHLEN+1); return getcwd(tmp, MAXPATHLEN); } static char *alias_channel (void) { char *tmp; char buffer[BIG_BUFFER_SIZE+1]; if ((tmp = get_current_channel_by_refnum(0))) { strlcpy(buffer, tmp, BIG_BUFFER_SIZE); tmp = double_quote(tmp, "{}()\"", buffer); #ifdef WANT_HEBREW if (get_int_var(HEBREW_TOGGLE_VAR)) hebrew_process(tmp); #endif return m_strdup(tmp); } else return m_strdup(zero); } static char *alias_server (void) { return m_strdup((parsing_server_index != -1) ? get_server_itsname(parsing_server_index) : (get_window_server(0) != -1) ? get_server_itsname(get_window_server(0)) : empty_string); } static char *alias_awaytime (void) { return m_sprintf("%ld", parsing_server_index != -1 ? (long)get_server_awaytime(parsing_server_index): get_window_server(0) != -1 ? (long)get_server_awaytime(get_window_server(0)): 0); } static char *alias_current_network (void) { return m_strdup((parsing_server_index != -1) ? get_server_network(parsing_server_index) : (get_window_server(0) != -1) ? get_server_network(get_window_server(0)) : empty_string); } static char *alias_serverport (void) { return m_sprintf("%d", (parsing_server_index != -1) ? get_server_port(parsing_server_index): (get_window_server(0) != -1) ? get_server_port(get_window_server(0)) : 0); } static char *alias_query_nick (void) { char *tmp; return m_strdup((tmp = current_window->query_nick) ? tmp : empty_string); } static char *alias_target (void) { char *tmp; return m_strdup((tmp = get_target_by_refnum(0)) ? tmp : empty_string); } static char *alias_cmdchar (void) { char *cmdchars, tmp[2]; if ((cmdchars = get_string_var(CMDCHARS_VAR)) == NULL) cmdchars = DEFAULT_CMDCHARS; tmp[0] = cmdchars[0]; tmp[1] = 0; return m_strdup(tmp); } static char *alias_chanop (void) { char *tmp; return m_strdup(((tmp = get_current_channel_by_refnum(0)) && get_channel_oper(tmp, from_server)) ? "@" : empty_string); } static char *alias_modes (void) { char *tmp; return m_strdup((tmp = get_current_channel_by_refnum(0)) ? get_channel_mode(tmp, from_server) : empty_string); } static char *alias_server_version (void) { int s = from_server; if (s == -1) { if (primary_server != -1) s = primary_server; else return m_strdup(empty_string); } return m_strdup(get_server_version_string(s)); } /* * * * * * * * * * These are the built-in functions. About 80 of them are here, the rest are in array.c. All of the stock client's functions are supported, as well as about 60 more. Most of the 30 stock client's functions have been re-written for optimization reasons, and also to further distance ircii's code from EPIC. * * * * * * * * * */ /* * These are defined to make the construction of the built-in functions * easier and less prone to bugs and unexpected behaviors. As long as * you consistently use these macros to do the dirty work for you, you * will never have to do bounds checking as the macros do that for you. >;-) * * Yes, i realize it makes the code slightly less efficient, but i feel that * the cost is minimal compared to how much time i have spent over the last * year debugging these functions and the fact i wont have to again. ;-) */ #define EMPTY empty_string #define EMPTY_STRING m_strdup(EMPTY) #define RETURN_EMPTY return EMPTY_STRING #define RETURN_IF_EMPTY(x) if (empty( x )) RETURN_EMPTY #define GET_INT_ARG(x, y) {RETURN_IF_EMPTY(y); x = atol(safe_new_next_arg(y, &y));} #define GET_FLOAT_ARG(x, y) {RETURN_IF_EMPTY(y); x = atof(safe_new_next_arg(y, &y));} #define GET_STR_ARG(x, y) {RETURN_IF_EMPTY(y); x = new_next_arg(y, &y);RETURN_IF_EMPTY(x);} #define RETURN_STR(x) return m_strdup((x) ? (x) : EMPTY) #define RETURN_MSTR(x) return ((x) ? (x) : EMPTY_STRING); #define RETURN_INT(x) return m_strdup(ltoa(x)) #undef BUILT_IN_FUNCTION #define BUILT_IN_FUNCTION(x, y) static char * x (char *fn, char * y) /* * Usage: $left(number text) * Returns: the leftmost characters in . * Example: $left(5 the quick brown frog) returns "the q" * * Note: the difference between $[10]foo and $left(10 foo) is that the former * is padded and the latter is not. */ BUILT_IN_FUNCTION(function_left, input) { long count; GET_INT_ARG(count, input); RETURN_IF_EMPTY(input); if (count < 0) RETURN_EMPTY; if (strlen(input) > count) input[count] = 0; RETURN_STR(input); } char *function_getkey(char *n, char *input) { char *temp; RETURN_IF_EMPTY(input); temp = get_channel_key(input, from_server); RETURN_STR(temp); } /* * Usage: $right(number text) * Returns: the rightmost characters in . * Example: $right(5 the quick brown frog) returns " frog" */ BUILT_IN_FUNCTION(function_right, word) { long count; GET_INT_ARG(count, word); RETURN_IF_EMPTY(word); if (count < 0) RETURN_EMPTY; if (strlen(word) > count) word += strlen(word) - count; RETURN_STR(word); } /* * Usage: $mid(start number text) * Returns: the th through +th characters in . * Example: $mid(3 4 the quick brown frog) returns " qui" * * Note: the first character is numbered zero. */ BUILT_IN_FUNCTION(function_mid, word) { long start, length; GET_INT_ARG(start, word); GET_INT_ARG(length, word); RETURN_IF_EMPTY(word); if (start < strlen(word)) { word += start; if (length < 0) RETURN_EMPTY; if (length < strlen(word)) word[length] = 0; } else word = EMPTY; RETURN_STR(word); } /* * Usage: $rand(max) * Returns: A random number from zero to max-1. * Example: $rand(10) might return any number from 0 to 9. */ BUILT_IN_FUNCTION(function_rand, word) { long tempin; unsigned long rand_n; int result; GET_INT_ARG(tempin, word); switch (get_int_var(RANDOM_SOURCE_VAR)) { case 0: default: rand_n = randd(0); break; case 1: rand_n = randm(0); break; case 2: rand_n = randt(0); break; } if (tempin) result = rand_n % tempin; else result = rand_n; RETURN_INT(result); } /* * Usage: $srand(seed) * Returns: Nothing. * Side effect: seeds the random number generater. * Note: the argument is ignored. */ BUILT_IN_FUNCTION(function_srand, word) { /* randd() and randt() do not accept seeding */ randm((long)now); RETURN_EMPTY; } /* * Usage: $time() * Returns: The number of seconds that has elapsed since Jan 1, 1970, GMT. * Example: $time() returned something around 802835348 at the time I * wrote this comment. */ BUILT_IN_FUNCTION(function_time, input) { RETURN_INT(time(NULL)); } /* * Usage: $stime(time) * Returns: The human-readable form of the date based on the