bitchx/source/functions.c

7415 lines
174 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 "bitchx"
#include <sys/stat.h>
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#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_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_serverport (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 },
{ "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_serverport },
{ "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)
{
sprintf(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)
{
sprintf(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;
matches = 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;
matches = (char **) 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;
matches = (char **) 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((sent_nick) ? sent_nick : empty_string); }
static char *alias_recv_nick (void) { return m_strdup((recv_nick) ? recv_nick : empty_string); }
static char *alias_msg_body (void) { return m_strdup((sent_body) ? sent_body : empty_string); }
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",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("%ld", 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("%lu", parsing_server_index != -1 ?
get_server_awaytime(parsing_server_index):
get_window_server(0) != -1 ?
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 = (char *)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 <number> leftmost characters in <text>.
* 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 <number> rightmost characters in <text>.
* 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 <start>th through <start>+<number>th characters in <text>.
* 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;
int result;
GET_INT_ARG(tempin, word);
if (tempin == 0)
tempin = (unsigned long) -1; /* This is cheating. :P */
result = random_number(0L) % tempin;
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)
{
random_number((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 <time> argument.
* Example: $stime(1000) returns what time it was 1000 seconds froM the epoch.
*
* Note: $stime() is really useful when you givE it the argument $time(), ala
* $stime($time()) is the human readable form for now.
*/
BUILT_IN_FUNCTION(function_stime, input)
{
time_t ltime;
GET_INT_ARG(ltime, input);
RETURN_STR(my_ctime(ltime));
}
/*
* Usage: $tdiff(seconds)
* Returns: The time that has elapsed represented in days/hours/minutes/seconds
* corresponding to the number of seconds passed as the argument.
* Example: $tdiff(3663) returns "1 hour 1 minute 3 seconds"
*/
BUILT_IN_FUNCTION(function_tdiff, input)
{
long ltime;
long days = 0,
hours = 0,
minutes = 0,
seconds = 0;
char *tstr, *tmp;
char *after = NULL;
tmp = alloca(strlen(input) + 180);
*tmp = 0;
ltime = strtol(input, &after, 10);
tstr = tmp;
if (after > input)
{
seconds = ltime % 60;
ltime = (ltime - seconds) / 60;
minutes = ltime % 60;
ltime = (ltime - minutes) / 60;
hours = ltime % 24;
days = (ltime - hours) / 24;
if (days)
{
sprintf(tstr, "%ld day%s ", days, plural(days));
tstr += strlen(tstr);
}
if (hours)
{
sprintf(tstr, "%ld hour%s ", hours, plural(hours));
tstr += strlen(tstr);
}
if (minutes)
{
sprintf(tstr, "%ld minute%s ", minutes, plural(minutes));
tstr += strlen(tstr);
}
}
if (seconds || (!days && !hours && !minutes) || (*after == '.' && is_number(after + 1)))
{
long number = 0;
/*
* If we have a decmial point, and is_number() returns 1,
* then we know that we have a real, authentic number AFTER
* the decmial point. As long as it isnt zero, we want it.
*/
if (*after == '.')
number = atol(after + 1);
/*
* *IF* and *ONLY IF* either the seconds OR the decmial
* part of the number is non zero do we tack on the seconds
* argument. If both are zero, we do nothing.
*/
if (seconds != 0 || number != 0)
{
if (number == 0)
sprintf(tstr, "%ld second%s", seconds, plural(seconds));
else
sprintf(tstr, "%ld%s seconds", seconds, after);
}
}
else
*--tstr = 0;
RETURN_STR(tmp);
}
/*
* Usage: $index(characters text)
* Returns: The number of leading characters in <text> that do not occur
* anywhere in the <characters> argument.
* Example: $index(f three fine frogs) returns 6 (the 'f' in 'fine')
* $index(frg three fine frogs) returns 2 (the 'r' in 'three')
*/
BUILT_IN_FUNCTION(function_index, input)
{
char *schars;
char *iloc;
GET_STR_ARG(schars, input);
iloc = sindex(input, schars);
RETURN_INT(iloc ? iloc - input : -1);
}
/*
* Usage: $rindex(characters text)
* Returns: The number of leading characters in <text> that occur before the
* *last* occurance of any of the characters in the <characters>
* argument.
* Example: $rindex(f three fine frogs) returns 12 (the 'f' in 'frogs')
* $rindex(frg three fine frogs) returns 15 (the 'g' in 'froGs')
*/
BUILT_IN_FUNCTION(function_rindex, word)
{
char *chars, *last;
/* need to find out why ^x doesnt work */
GET_STR_ARG(chars, word);
last = rsindex(word + strlen(word) - 1, word, chars, 1);
RETURN_INT(last ? last - word : -1);
}
/*
* Usage: $match(pattern list of words)
* Returns: if no words in the list match the pattern, it returns 0.
* Otherwise, it returns the number of the word that most
* exactly matches the pattern (first word is numbered one)
* Example: $match(f*bar foofum barfoo foobar) returns 3
* $match(g*ant foofum barfoo foobar) returns 0
*
* Note: it is possible to embed spaces inside of a word or pattern simply
* by including the entire word or pattern in quotation marks. (")
*/
BUILT_IN_FUNCTION(function_match, input)
{
char *pattern, *word;
long current_match, best_match = 0, match = 0, match_index = 0;
GET_STR_ARG(pattern, input);
while (input && *input)
{
while (input && my_isspace(*input))
input++;
match_index++;
GET_STR_ARG(word, input);
if ((current_match = wild_match(pattern, word)) > best_match)
{
match = match_index;
best_match = current_match;
}
}
RETURN_INT(match);
}
/*
* Usage: $rmatch(word list of patterns)
* Returns: if no pattern in the list matches the word, it returns 0.
* Otherwise, it returns the number of the pattern that most
* exactly matches the word (first word is numbered one)
* Example: $rmatch(foobar f*bar foo*ar g*ant) returns 2
* $rmatch(booya f*bar foo*ar g*ant) returns 0
*
* Note: It is possible to embed spaces into a word or pattern simply by
* including the entire word or pattern within quotation marks (")
*/
BUILT_IN_FUNCTION(function_rmatch, input)
{
char *pattern, *word;
int current_match, best_match = 0, match = 0, rmatch_index = 0;
GET_STR_ARG(word, input);
while (input && *input)
{
while (input && my_isspace(*input))
input++;
rmatch_index++;
GET_STR_ARG(pattern, input);
if ((current_match = wild_match(pattern, word)) > best_match)
{
match = rmatch_index;
best_match = current_match;
}
/* WARNING WARNING HACK IN PROGRESS WARNING WARNING */
while (input && my_isspace(*input))
input++;
}
RETURN_INT(match);
}
/*
* Usage: $userhost()
* Returns: the userhost (if any) of the most previously recieved message.
* Caveat: $userhost() changes with every single line that appears on
* your screen, so if you want to save it, you will need to assign
* it to a variable.
*/
BUILT_IN_FUNCTION(function_userhost, input)
{
if (input && *input)
{
char *retval = NULL;
char *nick;
const char *userhost;
while (input && *input)
{
GET_STR_ARG(nick, input);
if ((userhost = fetch_userhost(from_server, nick)))
m_s3cat(&retval, space, userhost);
else
m_s3cat(&retval, space, unknown_userhost);
}
return retval; /* DONT USE RETURN_STR HERE! */
}
RETURN_STR(FromUserHost);
}
/*
* Usage: $strip(characters text)
* Returns: <text> with all instances of any characters in the <characters>
* argument removed.
* Example: $strip(f free fine frogs) returns "ree ine rogs"
*
* Note: it can be difficult (actually, not possible) to remove spaces from
* a string using this function. To remove spaces, simply use this:
* $tr(/ //$text)
*
* Actually, i recommend not using $strip() at all and just using
* $tr(/characters//$text)
* (but then again, im biased. >;-)
*/
BUILT_IN_FUNCTION(function_strip, input)
{
char *result;
char *chars;
char *cp, *dp;
GET_STR_ARG(chars, input);
RETURN_IF_EMPTY(input);
result = (char *)new_malloc(strlen(input) + 1);
for (cp = input, dp = result; *cp; cp++)
{
/* This is expensive -- gotta be a better way */
if (!strchr(chars, *cp))
*dp++ = *cp;
}
*dp = '\0';
return result; /* DONT USE RETURN_STR HERE! */
}
/*
* Usage: $encode(text)
* Returns: a string, uniquely identified with <text> such that the string
* can be used as a variable name.
* Example: $encode(fe fi fo fum) returns "GGGFCAGGGJCAGGGPCAGGHFGN"
*
* Note: $encode($decode(text)) returns text (most of the time)
* $decode($encode(text)) also returns text.
*/
static char * function_encode (char *n, unsigned char * input)
{
char *result;
int i = 0;
result = (char *)new_malloc(strlen((char *)input) * 2 + 1);
while (*input)
{
result[i++] = (*input >> 4) + 0x41;
result[i++] = (*input & 0x0f) + 0x41;
input++;
}
result[i] = '\0';
return result; /* DONT USE RETURN_STR HERE! */
}
/*
* Usage: $decode(text)
* Returns: If <text> was generated with $encode(), it returns the string
* you originally encoded. If it wasnt, you will probably get
* nothing useful in particular.
* Example: $decode(GGGFCAGGGJCAGGGPCAGGHFGN) returns "fe fi fo fum"
*
* Note: $encode($decode(text)) returns "text"
* $decode($encode(text)) returns "text" too.
*
* Note: Yes. $decode(plain-text) does compress the data by a factor of 2.
* But it ignores non-ascii text, so use this as compression at your
* own risk and peril.
*/
char *function_decode(char *n, unsigned char * input)
{
unsigned char *result;
int i = 0;
result = (unsigned char *)new_malloc(strlen((char *)input) / 2 + 1);
while (input[0] && input[1])
{
/* oops, this isnt quite right. */
result[i] = ((input[0] - 0x41) << 4) | (input[1] - 0x41);
input += 2;
i++;
}
result[i] = '\0';
return result; /* DONT USE RETURN_STR HERE! */
}
/*
* Usage: $ischannel(text)
* Returns: If <text> could be a valid channel name, 1 is returned.
* If <text> is an illegal channel name, 0 is returned.
*
* Note: Contrary to popular belief, this function does NOT determine
* whether a given channel name is in use!
*/
BUILT_IN_FUNCTION(function_ischannel, input)
{
RETURN_INT(is_channel(input));
}
/*
* Usage: $ischanop(nick channel)
* Returns: 1 if <nick> is a channel operator on <channel>
* 0 if <nick> is not a channel operator on <channel>
* * O R *
* if you are not on <channel>
*
* Note: Contrary to popular belief, this function can only tell you
* who the channel operators are for channels you are already on!
*
* Boo Hiss: This should be $ischanop(channel nick <nick...nick>)
* and return a list (1 1 ... 0), which would allow us to
* call is_chanop() without ripping off the nick, and allow
* us to abstract is_chanop() to take a list. oh well...
* Too late to change it now. :/
*/
BUILT_IN_FUNCTION(function_ischanop, input)
{
char *nick;
GET_STR_ARG(nick, input);
if (is_channel(nick))
{
char *blah;
blah = is_chanoper(nick, input);
return blah ? blah : m_strdup(empty_string);
}
else
RETURN_INT(is_chanop(input, nick));
}
/*
* Usage: $word(jUmber text)
* Returns: the <number>th word in <text>. The first word is numbered zero.
* Example: $word(3 one two three four five) returns "four" (think about it)
*/
BUILT_IN_FUNCTION(function_word, word)
{
int cvalue;
char *w_word;
GET_INT_ARG(cvalue, word);
if (cvalue < 0)
RETURN_EMPTY;
while (cvalue-- > 0)
GET_STR_ARG(w_word, word);
GET_STR_ARG(w_word, word);
RETURN_STR(w_word);
}
/*
* Usage: $winnum()
* Returns: the index number for the current window
*
* Note: returns -1 if there are no windows open (ie, in dumb mode)
*/
BUILT_IN_FUNCTION(function_winnum, input)
{
Window *win = NULL;
if (!(win = *input ? get_window_by_desc(input) : current_window))
RETURN_INT(-1);
RETURN_INT(win->refnum);
}
BUILT_IN_FUNCTION(function_winnam, input)
{
Window *win = NULL;
if (!(win = *input ? get_window_by_desc(input) : current_window))
RETURN_EMPTY;
RETURN_STR(win->name);
}
BUILT_IN_FUNCTION(function_winnames, input)
{
Window *win = NULL;
char *s = NULL;
if (*input)
win = get_window_by_desc(input);
else
win = current_window;
if (!win)
RETURN_EMPTY;
return (s = get_nicklist_by_window(win)) ? s : m_strdup(empty_string);
}
BUILT_IN_FUNCTION(function_connect, input)
{
char *host;
int port;
GET_STR_ARG(host, input);
GET_INT_ARG(port, input);
return dcc_raw_connect(host, port); /* DONT USE RETURN_STR HERE! */
}
BUILT_IN_FUNCTION(function_listen, input)
{
int port = 0;
char *result;
/* Oops. found by CrowMan, listen() has a default. erf. */
if (input && *input)
{
char *tmp, *ptr;
if ((tmp = new_next_arg(input, &input)))
{
port = strtoul(tmp, &ptr, 10);
if (ptr == tmp)
RETURN_EMPTY; /* error. */
}
}
result = dcc_raw_listen(port);
RETURN_STR(result); /* DONT REMOVE RESULT! */
}
BUILT_IN_FUNCTION(function_toupper, input)
{
return (upper(m_strdup(input)));
}
BUILT_IN_FUNCTION(function_tolower, input)
{
return (lower(m_strdup(input)));
}
BUILT_IN_FUNCTION(function_curpos, input)
{
RETURN_INT(current_window->screen->buffer_pos);
}
BUILT_IN_FUNCTION(function_channels, input)
{
long winnum;
Window *window = current_window;
if (isdigit((unsigned char)*input))
{
GET_INT_ARG(winnum, input);
window = get_window_by_refnum(winnum);
}
if (window->server <= -1)
RETURN_EMPTY;
return create_channel_list(window); /* DONT USE RETURN_STR HERE! */
}
BUILT_IN_FUNCTION(function_servers, input)
{
return create_server_list(input); /* DONT USE RETURN_STR HERE! */
}
BUILT_IN_FUNCTION(function_pid, input)
{
RETURN_INT(getpid());
}
BUILT_IN_FUNCTION(function_ppid, input)
{
RETURN_INT(getppid());
}
/*
* strftime() patch from hari (markc@arbld.unimelb.edu.au)
*/
BUILT_IN_FUNCTION(function_strftime, input)
{
char result[128];
time_t ltime;
struct tm *tm;
if (isdigit((unsigned char)*input))
ltime = strtoul(input, &input, 10);
else
ltime = now;
while (*input && my_isspace(*input))
++input;
if (!*input)
return m_strdup(empty_string);
tm = localtime(&ltime);
if (!strftime(result, 128, input, tm))
return m_strdup(empty_string);
return m_strdup(result);
}
BUILT_IN_FUNCTION(function_idle, input)
{
return alias_idle();
}
/* The new "added" functions */
/* $before(chars string of text)
* returns the part of "string of text" that occurs before the
* first instance of any character in "chars"
* EX: $before(! hop!jnelson@iastate.edu) returns "hop"
*/
BUILT_IN_FUNCTION(function_before, word)
{
char *pointer = NULL;
char *chars;
char *tmp;
long numint;
GET_STR_ARG(tmp, word); /* DONT DELETE TMP! */
numint = atol(tmp);
if (numint)
{
GET_STR_ARG(chars, word);
}
else
{
numint = 1;
chars = tmp;
}
if (numint < 0 && strlen(word))
pointer = word + strlen(word) - 1;
pointer = search(word, &pointer, chars, numint);
if (!pointer)
RETURN_EMPTY;
*pointer = '\0';
RETURN_STR(word);
}
/* $after(chars string of text)
* returns the part of "string of text" that occurs after the
* first instance of any character in "chars"
* EX: $after(! hop!jnelson@iastate.edu) returns "jnelson@iastate.edu"
*/
BUILT_IN_FUNCTION(function_after, word)
{
char *chars;
char *pointer = NULL;
char *tmp;
long numint;
GET_STR_ARG(tmp, word);
numint = atol(tmp);
if (numint)
chars = new_next_arg(word, &word);
else
{
numint = 1;
chars = tmp;
}
if (numint < 0 && strlen(word))
pointer = word + strlen(word) - 1;
pointer = search(word, &pointer, chars, numint);
if (!pointer || !*pointer)
RETURN_EMPTY;
RETURN_STR(pointer + 1);
}
/* $leftw(num string of text)
* returns the left "num" words in "string of text"
* EX: $leftw(3 now is the time for) returns "now is the"
*/
BUILT_IN_FUNCTION(function_leftw, word)
{
int value;
GET_INT_ARG(value, word);
if (value < 1)
RETURN_EMPTY;
return (extract(word, 0, value-1)); /* DONT USE RETURN_STR HERE! */
}
/* $rightw(num string of text)
* returns the right num words in "string of text"
* EX: $rightw(3 now is the time for) returns "the time for"
*/
BUILT_IN_FUNCTION(function_rightw, word)
{
int value;
GET_INT_ARG(value, word);
if (value < 1)
RETURN_EMPTY;
return extract2(word, -value, EOS);
}
/* $midw(start num string of text)
* returns "num" words starting at word "start" in the string "string of text"
* NOTE: The first word is word #0.
* EX: $midw(2 2 now is the time for) returns "the time"
*/
BUILT_IN_FUNCTION(function_midw, word)
{
int start, num;
GET_INT_ARG(start, word);
GET_INT_ARG(num, word);
if (num < 1)
RETURN_EMPTY;
return extract(word, start, (start + num - 1));
}
/* $notw(num string of text)
* returns "string of text" with word number "num" removed.
* NOTE: The first word is numbered 0.
* EX: $notw(3 now is the time for) returns "now is the for"
*/
BUILT_IN_FUNCTION(function_notw, word)
{
char *booya = NULL;
int where;
GET_INT_ARG(where, word);
/* An illegal word simpli returns the string as-is */
if (where < 0)
RETURN_STR(word);
if (where > 0)
{
char *part1, *part2;
part1 = extract(word, 0, (where - 1));
part2 = extract(word, (where + 1), EOS);
booya = m_strdup(part1);
m_s3cat_s(&booya, space, part2);
new_free(&part1);
new_free(&part2);
}
else /* where == 0 */
booya = extract(word, 1, EOS);
return booya; /* DONT USE RETURN_STR HERE! */
}
/* $restw(num string of text)
* returns "string of text" that occurs starting with and including
* word number "num"
* NOTE: the first word is numbered 0.
* EX: $restw(3 now is the time for) returns "time for"
*/
BUILT_IN_FUNCTION(function_restw, word)
{
int where;
GET_INT_ARG(where, word);
if (where < 0)
RETURN_EMPTY;
return extract(word, where, EOS);
}
/* $remw(word string of text)
* returns "string of text" with the word "word" removed
* EX: $remw(the now is the time for) returns "now is time for"
*/
BUILT_IN_FUNCTION(function_remw, word)
{
char *word_to_remove;
int len;
char *str;
GET_STR_ARG(word_to_remove, word);
len = strlen(word_to_remove);
str = stristr(word, word_to_remove);
for (; str && *str; str = stristr(str + 1, word_to_remove))
{
if (str == word || isspace((unsigned char)str[-1]))
{
if (!str[len] || isspace((unsigned char)str[len]))
{
if (!str[len])
{
if (str != word)
str--;
*str = 0;
}
else if (str > word)
{
char *safe = (char *)alloca(strlen(str));
strcpy(safe, str + len);
strcpy(str - 1, safe);
}
else
{
char *safe = (char *)alloca(strlen(str));
strcpy(safe, str + len + 1);
strcpy(str, safe);
}
break;
}
}
}
RETURN_STR(word);
}
/* $insertw(num word string of text)
* returns "string of text" such that "word" is the "num"th word
* in the string.
* NOTE: the first word is numbered 0.
* EX: $insertw(3 foo now is the time for) returns "now is the foo time for"
*/
BUILT_IN_FUNCTION(function_insertw, word)
{
int where;
char *what;
char *booya= NULL;
char *str1, *str2;
GET_INT_ARG(where, word);
/* If the word goes at the front of the string, then it
already is: return it. ;-) */
if (where < 1)
booya = m_strdup(word);
else
{
GET_STR_ARG(what, word);
str1 = extract(word, 0, (where - 1));
str2 = extract(word, where, EOS);
booya = m_strdup(str1);
if (str1 && *str1)
booya = m_2dup(str1, space);
malloc_strcat(&booya, what);
m_s3cat_s(&booya, space, str2);
new_free(&str1);
new_free(&str2);
}
return booya; /* DONT USE RETURN_STR HERE! */
}
/* $chngw(num word string of text)
* returns "string of text" such that the "num"th word is removed
* and replaced by "word"
* NOTE: the first word is numbered 0
* EX: $chngw(3 foo now is the time for) returns "now is the foo for"
*/
BUILT_IN_FUNCTION(function_chngw, word)
{
int which;
char *what;
char *booya= NULL;
char *str1, *str2;
GET_INT_ARG(which, word);
GET_STR_ARG(what, word);
if (which < 0)
RETURN_STR(word);
/* hmmm. if which is 0, extract does the wrong thing. */
str1 = extract(word, 0, which - 1);
str2 = extract(word, which + 1, EOS);
booya = m_strdup(str1);
if (str1 && *str1)
booya = m_2dup(str1, space);
malloc_strcat(&booya, what);
m_s3cat_s(&booya, space, str2);
new_free(&str1);
new_free(&str2);
return (booya);
}
/* $common (string of text / string of text)
* Given two sets of words seperated by a forward-slash '/', returns
* all words that are found in both sets.
* EX: $common(one two three / buckle my two shoe one) returns "one two"
* NOTE: returned in order found in first string.
*/
BUILT_IN_FUNCTION(function_common, word)
{
char *left = NULL, **leftw = NULL,
*right = NULL, **rightw = NULL, *booya = NULL;
int leftc, lefti;
int rightc, righti;
left = word;
if ((right = strchr(word,'/')) == NULL)
RETURN_EMPTY;
*right++ = 0;
leftc = splitw(left, &leftw);
rightc = splitw(right, &rightw);
for (lefti = 0; lefti < leftc; lefti++)
{
for (righti = 0; righti < rightc; righti++)
{
if (rightw[righti] && !my_stricmp(leftw[lefti], rightw[righti]))
{
m_s3cat(&booya, space, leftw[lefti]);
rightw[righti] = NULL;
}
}
}
new_free((char **)&leftw);
new_free((char **)&rightw);
if (!booya)
RETURN_EMPTY;
return (booya); /* DONT USE RETURN_STR HERE! */
}
/* $diff(string of text / string of text)
* given two sets of words, seperated by a forward-slash '/', returns
* all words that are not found in both sets
* EX: $diff(one two three / buckle my two shoe)
* returns "one two three buckle my shoe"
*/
BUILT_IN_FUNCTION(function_diff, word)
{
char *left = NULL, **leftw = NULL,
*right = NULL, **rightw = NULL, *booya = NULL;
int lefti, leftc,
righti, rightc;
int found;
left = word;
if ((right = strchr(word,'/')) == NULL)
RETURN_EMPTY;
*right++ = 0;
leftc = splitw(left, &leftw);
rightc = splitw(right, &rightw);
for (lefti = 0; lefti < leftc; lefti++)
{
found = 0;
for (righti = 0; righti < rightc; righti++)
{
if (rightw[righti] && !my_stricmp(leftw[lefti], rightw[righti]))
{
found = 1;
rightw[righti] = NULL;
}
}
if (!found)
m_s3cat(&booya, space, leftw[lefti]);
}
for (righti = 0; righti < rightc; righti++)
{
if (rightw[righti])
m_s3cat(&booya, space, rightw[righti]);
}
new_free((char **)&leftw);
new_free((char **)&rightw);
if (!booya)
RETURN_EMPTY;
return (booya);
}
/* $pattern(pattern string of words)
* givEn a pattern and a string of words, returns all words that
* are matched by the pattern
* EX: $pattern(f* one two three four five) returns "four five"
*/
BUILT_IN_FUNCTION(function_pattern, word)
{
char *blah;
char *booya = NULL;
char *pattern;
GET_STR_ARG(pattern, word);
while (((blah = new_next_arg(word, &word)) != NULL))
{
if (wild_match(pattern, blah))
m_s3cat(&booya, space, blah);
}
RETURN_MSTR(booya);
}
/* $filter(pattern string of words)
* given a pattern and a string of words, returns all words that are
* NOT matched by the pattern
* $filter(f* one two three four five) returns "one two three"
*/
BUILT_IN_FUNCTION(function_filter, word)
{
char *blah;
char *booya = NULL;
char *pattern;
GET_STR_ARG(pattern, word);
while ((blah = new_next_arg(word, &word)) != NULL)
{
if (!wild_match(pattern, blah))
m_s3cat(&booya, space, blah);
}
RETURN_MSTR(booya);
}
/* $rpattern(word list of patterns)
* Given a word and a list of patterns, return all patterns that
* match the word.
* EX: $rpattern(jnelson@iastate.edu *@* jnelson@* f*@*.edu)
* returns "*@* jnelson@*"
*/
BUILT_IN_FUNCTION(function_rpattern, word)
{
char *blah;
char *booya = NULL;
char *pattern;
GET_STR_ARG(blah, word);
while ((pattern = new_next_arg(word, &word)) != NULL)
{
if (wild_match(pattern, blah))
m_s3cat(&booya, space, pattern);
}
RETURN_MSTR(booya);
}
/* $rfilter(word list of patterns)
* given a word and a list of patterns, return all patterns that
* do NOT match the word
* EX: $rfilter(jnelson@iastate.edu *@* jnelson@* f*@*.edu)
* returns "f*@*.edu"
*/
BUILT_IN_FUNCTION(function_rfilter, word)
{
char *blah;
char *booya = NULL;
char *pattern;
GET_STR_ARG(blah, word);
while ((pattern = new_next_arg(word, &word)) != NULL)
{
if (!wild_match(pattern, blah))
m_s3cat(&booya, space, pattern);
}
RETURN_MSTR(booya);
}
/* $copattern(pattern var_1 var_2)
* Given a pattern and two variable names, it returns all words
* in the variable_2 corresponding to any words in variable_1 that
* are matched by the pattern
* EX: @nicks = [hop IRSMan skip]
* @userh = [jnelson@iastate.edu irsman@iastate.edu sanders@rush.cc.edu]
* $copattern(*@iastate.edu userh nicks)
* returns "hop IRSMan"
*/
BUILT_IN_FUNCTION(function_copattern, word)
{
char *booya = NULL,
*pattern = NULL,
*firstl = NULL, *firstlist = NULL, *firstel = NULL,
*secondl = NULL, *secondlist = NULL, *secondel = NULL;
char *sfirstl, *ssecondl;
GET_STR_ARG(pattern, word);
GET_STR_ARG(firstlist, word);
GET_STR_ARG(secondlist, word);
firstl = get_variable(firstlist);
secondl = get_variable(secondlist);
sfirstl = firstl;
ssecondl = secondl;
while ((firstel = new_next_arg(firstl, &firstl)))
{
if (!(secondel = new_next_arg(secondl, &secondl)))
break;
if (wild_match(pattern, firstel))
m_s3cat(&booya, space, secondel);
}
new_free(&sfirstl);
new_free(&ssecondl);
if (!booya)
RETURN_EMPTY;
return (booya);
}
/* $beforew(pattern string of words)
* returns the portion of "string of words" that occurs before the
* first word that is matched by "pattern"
* EX: $beforew(three one two three o leary) returns "one two"
*/
BUILT_IN_FUNCTION(function_beforew, word)
{
int where;
char *lame = NULL;
char *placeholder;
lame = LOCAL_COPY(word);
where = my_atol((placeholder = function_rmatch(NULL, word)));
new_free(&placeholder);
if (where < 1)
{
RETURN_EMPTY;
}
placeholder = extract(lame, 1, where - 1);
return placeholder;
}
/* Same as above, but includes the word being matched */
BUILT_IN_FUNCTION(function_tow, word)
{
int where;
char *lame = NULL;
char *placeholder;
lame = LOCAL_COPY(word);
where = my_atol((placeholder = function_rmatch(NULL, word)));
new_free(&placeholder);
if (where < 1)
RETURN_EMPTY;
placeholder = extract(lame, 1, where);
return placeholder;
}
/* Returns the string after the word being matched */
BUILT_IN_FUNCTION(function_afterw, word)
{
int where;
char *lame = NULL;
char *placeholder;
lame = LOCAL_COPY(word);
where = my_atol((placeholder = function_rmatch(NULL, word)));
new_free(&placeholder);
if (where < 1)
RETURN_EMPTY;
placeholder = extract(lame, where + 1, EOS);
return placeholder;
}
/* Returns the string starting with the word being matched */
BUILT_IN_FUNCTION(function_fromw, word)
{
int where;
char *lame = NULL;
char *placeholder;
lame = LOCAL_COPY(word);
where = my_atol((placeholder = function_rmatch(NULL, word)));
new_free(&placeholder);
if (where < 1)
RETURN_EMPTY;
placeholder = extract(lame, where, EOS);
return placeholder;
}
/* Cut and paste a string */
BUILT_IN_FUNCTION(function_splice, word)
{
char *variable;
int start;
int length;
char *left_part = NULL;
char *middle_part = NULL;
char *right_part = NULL;
char *old_value = NULL;
char *new_value = NULL;
int old_display = window_display;
int num_words;
GET_STR_ARG(variable, word);
GET_INT_ARG(start, word);
GET_INT_ARG(length, word);
old_value = get_variable(variable);
num_words = word_count(old_value);
if (start < 0)
{
if ((length += start) <= 0)
RETURN_EMPTY;
start = 0;
}
if (start >= num_words)
{
left_part = m_strdup(old_value);
middle_part = m_strdup(empty_string);
right_part = m_strdup(empty_string);
}
else if (start + length >= num_words)
{
left_part = extract(old_value, 0, start - 1);
middle_part = extract(old_value, start, EOS);
right_part = m_strdup(empty_string);
}
else
{
left_part = extract(old_value, 0, start - 1);
middle_part = extract(old_value, start, start + length - 1);
right_part = extract(old_value, start + length, EOS);
}
new_value = NULL;
malloc_strcpy(&new_value, left_part);
if (new_value && *new_value && word && *word)
malloc_strcat(&new_value, space);
if (word && *word)
malloc_strcat(&new_value, word);
if (new_value && *new_value && *right_part && *right_part)
malloc_strcat(&new_value, space);
if (right_part && *right_part)
malloc_strcat(&new_value, right_part);
window_display = 0;
add_var_alias(variable, new_value);
window_display = old_display;
new_free(&old_value);
new_free(&new_value);
new_free(&left_part);
new_free(&right_part);
return middle_part;
}
BUILT_IN_FUNCTION(function_numonchannel, word)
{
char *channel;
ChannelList *chan = NULL; /* XXX */
NickList *tmp = NULL;
int counter = 0;
/* this does the right thing CDE */
channel = next_arg(word, &word);
if ((chan = lookup_channel(channel, from_server, 0)))
{
for (tmp = next_nicklist(chan, NULL); tmp; tmp = next_nicklist(chan, tmp))
counter++;
}
RETURN_INT(counter);
}
BUILT_IN_FUNCTION(function_onchannel, word)
{
char *channel;
ChannelList *chan = NULL; /* XXX */
NickList *tmp = NULL;
char *nicks = NULL;
int sort_type = NICKSORT_NORMAL;
/* DO NOT use new_next_arg() in here. NULL is a legit value to pass CDE*/
channel = next_arg(word, &word);
if ((chan = lookup_channel(channel, from_server, 0)))
{
NickList *list=NULL;
if (word && *word)
GET_INT_ARG(sort_type, word);
list = sorted_nicklist(chan, sort_type);
for (tmp = list; tmp; tmp = tmp->next)
m_s3cat(&nicks, space, tmp->nick);
clear_sorted_nicklist(&list);
return (nicks ? nicks : m_strdup(empty_string));
}
else
{
nicks = channel;
channel = next_arg(word, &word);
RETURN_INT(is_on_channel(channel, from_server, nicks) ? 1 : 0);
}
}
BUILT_IN_FUNCTION(function_channelnicks, word)
{
char *channel;
ChannelList *chan = NULL; /* XXX */
NickList *tmp = NULL;
char *nicks = NULL;
int sort_type = NICKSORT_NORMAL;
channel = next_arg(word, &word);
if ((chan = lookup_channel(channel, from_server, 0)))
{
NickList *list = NULL;
if (word && *word)
GET_INT_ARG(sort_type, word);
list = sorted_nicklist(chan, NICKSORT_NORMAL);
for (tmp = list; tmp; tmp = tmp->next)
m_s3cat(&nicks, ",", tmp->nick);
clear_sorted_nicklist(&list);
return (nicks ? nicks : m_strdup(empty_string));
}
else
{
nicks = channel;
channel = next_arg(word, &word);
RETURN_INT(is_on_channel(channel, from_server, nicks) ? 1 : 0);
}
}
BUILT_IN_FUNCTION(function_servports, input)
{
int servnum = from_server;
if (*input)
GET_INT_ARG(servnum, input);
if (servnum == -1)
servnum = from_server;
if (servnum < 0 || servnum > server_list_size())
RETURN_EMPTY;
return m_sprintf("%d %d", get_server_port(servnum),
get_server_local_port(servnum));
}
BUILT_IN_FUNCTION(function_chop, input)
{
char *buffer;
int howmany = 1;
if (my_atol(input))
GET_INT_ARG(howmany, input);
buffer = m_strdup(input);
chop(buffer, howmany);
return buffer;
}
BUILT_IN_FUNCTION(function_winlevel, input)
{
Window *win;
char *desc;
if (input && *input)
{
GET_STR_ARG(desc, input);
win = get_window_by_desc(desc);
}
else
win = current_window;
if (!win)
RETURN_EMPTY;
RETURN_STR(bits_to_lastlog_level(win->window_level));
}
BUILT_IN_FUNCTION(function_chops, word)
{
char *channel;
ChannelList *chan;
NickList *tmp;
char *nicks = NULL;
channel = next_arg(word, &word);
if ((chan = lookup_channel(channel,from_server,0)))
{
NickList *list = NULL;
list = sorted_nicklist(chan, NICKSORT_NORMAL);
for (tmp = list; tmp; tmp = tmp->next)
if (nick_isop(tmp))
m_s3cat(&nicks, space, tmp->nick);
clear_sorted_nicklist(&list);
}
return (nicks ? nicks : m_strdup(empty_string));
}
BUILT_IN_FUNCTION(function_nochops, word)
{
ChannelList *chan;
NickList *tmp;
char *nicks = NULL;
char *channel;
channel = next_arg(word, &word);
if ((chan = lookup_channel(channel,from_server,0)))
{
NickList *list = NULL;
list = sorted_nicklist(chan, NICKSORT_NORMAL);
for (tmp = list; tmp; tmp = tmp->next)
if (!nick_isop(tmp))
m_s3cat(&nicks, space, tmp->nick);
clear_sorted_nicklist(&list);
}
return (nicks ? nicks : m_strdup(empty_string));
}
BUILT_IN_FUNCTION(function_key, word)
{
char *channel;
char *booya = NULL;
char *key;
do
{
channel = next_arg(word, &word);
if ((!channel || !*channel) && booya)
break;
key = get_channel_key(channel, from_server);
m_s3cat(&booya, space, (key && *key) ? key : "*");
}
while (word && *word);
return (booya ? booya : m_strdup(empty_string));
}
BUILT_IN_FUNCTION(function_revw, words)
{
char *booya = NULL;
while (words && *words)
m_s3cat(&booya, space, last_arg(&words));
if (!booya)
RETURN_EMPTY;
return booya;
}
BUILT_IN_FUNCTION(function_reverse, words)
{
int length = strlen(words);
char *booya = NULL;
int x = 0;
booya = (char *)new_malloc(length+1);
for (length--; length >= 0; length--,x++)
booya[x] = words[length];
booya[x] = '\0';
return (booya);
}
BUILT_IN_FUNCTION(function_substr, input)
{
char *search;
char *ptr;
GET_STR_ARG(search, input);
if ((ptr = stristr(input, search)))
RETURN_INT((unsigned long)(ptr - input));
else
RETURN_INT(-1);
}
BUILT_IN_FUNCTION(function_rsubstr, input)
{
char *search;
char *ptr;
GET_STR_ARG(search, input);
if ((ptr = rstristr(input, search)))
RETURN_INT((unsigned long)(ptr - input));
else
RETURN_INT(-1);
}
BUILT_IN_FUNCTION(function_nohighlight, input)
{
char *outbuf, *ptr;
ptr = outbuf = alloca(strlen(input) * 3 + 1);
while (*input)
{
switch (*input)
{
case REV_TOG:
case UND_TOG:
case BOLD_TOG:
case BLINK_TOG:
case ALL_OFF:
case '\003':
case '\033':
{
*ptr++ = REV_TOG;
*ptr++ = (*input++ | 0x40);
*ptr++ = REV_TOG;
break;
}
default:
{
*ptr++ = *input++;
break;
}
}
}
*ptr = 0;
RETURN_STR(outbuf);
}
BUILT_IN_FUNCTION(function_strstr, input)
{
char *p, *word;
GET_STR_ARG(word, input);
RETURN_IF_EMPTY(input);
if ((p = stristr(input, word)))
RETURN_STR(p);
else
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_rstrstr, input)
{
char *p, *word;
GET_STR_ARG(word, input);
RETURN_IF_EMPTY(input);
if ((p = rstristr(input, word)))
RETURN_STR(p);
else
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_jot, input)
{
int start = 0;
int stop = 0;
int interval = 1;
int counter;
char *booya = NULL;
int range;
size_t size;
GET_INT_ARG(start,input)
GET_INT_ARG(stop, input)
if (input && *input)
GET_INT_ARG(interval, input)
else
interval = 1;
if (interval < 0)
interval = -interval;
range = abs(stop - start) + 1;
size = range * 10;
booya = new_malloc(size);
size--;
if (start < stop)
{
strlcpy(booya, ltoa(start), size);
for (counter = start + interval; counter <= stop; counter += interval)
{
strlcat(booya, space, size);
strlcat(booya, ltoa(counter), size);
}
}
else
{
strlcpy(booya, ltoa(start),size);
for (counter = start - interval; counter >= stop; counter -= interval)
{
strlcat(booya, space, size);
strlcat(booya, ltoa(counter), size);
}
}
return booya;
}
char *function_shift(char *n, char *word)
{
char *value = NULL;
char *var = NULL;
char *booya = NULL;
int old_display = window_display;
char *placeholder;
GET_STR_ARG(var, word);
if (word && *word)
RETURN_STR(var);
value = get_variable(var);
if (!value || !*value)
{
new_free(&value);
RETURN_EMPTY;
}
placeholder = value;
booya = m_strdup(new_next_arg(value, &value));
/* do not free value at this point */
if (var)
{
window_display = 0;
add_var_alias(var, value);
window_display = old_display;
}
new_free(&placeholder);
if (!booya)
RETURN_EMPTY;
return booya;
}
char *function_unshift(char *n, char *word)
{
char *value = NULL;
char *var = NULL;
char *booya = NULL;
int old_display = window_display;
GET_STR_ARG(var, word);
value = get_variable(var);
if (!word || !*word)
return value;
booya = m_strdup(word);
m_s3cat_s(&booya, space, value);
window_display = 0;
add_var_alias(var, booya);
window_display = old_display;
new_free(&value);
return booya;
}
char *function_push(char *n, char *word)
{
char *value = NULL;
char *var = NULL;
int old_display = window_display;
GET_STR_ARG(var, word);
value = get_variable(var);
m_s3cat(&value, space, word);
window_display = 0;
add_var_alias(var, value);
window_display = old_display;
return value;
}
char *function_pop(char *n, char *word)
{
char *value = NULL;
char *var = NULL;
char *pointer = NULL;
int old_display = window_display;
char *blech = NULL;
GET_STR_ARG(var, word);
if (word && *word)
{
pointer = strrchr(word, ' ');
RETURN_STR(pointer ? pointer : word);
}
value = get_variable(var);
if (!value || !*value)
{
new_free(&value);
RETURN_EMPTY;
}
if (!(pointer = strrchr(value, ' ')))
{
window_display = 0;
add_var_alias(var, empty_string); /* dont forget this! */
window_display = old_display;
return value; /* one word -- return it */
}
*pointer++ = '\0';
window_display = 0;
add_var_alias(var, value);
window_display = old_display;
/* because pointer points to value, we *must* make a copy of it
* *before* we free value! (And we cant forget to free value, either)
*/
blech = m_strdup(pointer);
new_free(&value);
return blech;
}
/* Search and replace function --
Usage: $sar(c/search/replace/data)
Commands:
r - treat data as a variable name and
return the replaced data to the variable
g - Replace all instances, not just the first one
The delimiter may be any character that is not a command (typically /)
The delimiter MUST be the first character after the command
Returns emppy string on error
*/
BUILT_IN_FUNCTION(function_sar, word)
{
register char delimiter;
register char *pointer = NULL;
char *search = NULL;
char *replace = NULL;
char *data = NULL;
char *value = NULL;
char *booya = NULL;
int variable = 0,this_global = 0,searchlen,oldwindow = window_display;
char *(*func) (const char *, const char *) = strstr;
char *svalue;
while (((*word == 'r') && (variable = 1)) || ((*word == 'g') && (this_global = 1)) || ((*word == 'i') && (func = (char *(*)(const char *, const char *))global[STRISTR])))
word++;
RETURN_IF_EMPTY(word);
delimiter = *word;
search = word + 1;
if ((replace = strchr(search, delimiter)) == 0)
RETURN_EMPTY;
*replace++ = 0;
if ((data = strchr(replace,delimiter)) == 0)
RETURN_EMPTY;
*data++ = '\0';
value = (variable == 1) ? get_variable(data) : m_strdup(data);
if (!value || !*value)
{
new_free(&value);
RETURN_EMPTY;
}
pointer = svalue = value;
searchlen = strlen(search) - 1;
if (searchlen < 0)
searchlen = 0;
if (this_global)
{
while ((pointer = func(pointer,search)) != NULL)
{
pointer[0] = pointer[searchlen] = 0;
pointer += searchlen + 1;
m_e3cat(&booya, value, replace);
value = pointer;
if (!*pointer)
break;
}
}
else
{
if ((pointer = func(pointer,search)) != NULL)
{
pointer[0] = pointer[searchlen] = 0;
pointer += searchlen + 1;
m_e3cat(&booya, value, replace);
value = pointer;
}
}
malloc_strcat(&booya, value);
if (variable)
{
window_display = 0;
add_var_alias(data, booya);
window_display = oldwindow;
}
new_free(&svalue);
return (booya);
}
/* Search and replace function --
Usage: $msar(c/search/replace/data)
Commands:
r - treat data as a variable name and
return the replaced data to the variable
g - Replace all instances, not just the first one
The delimiter may be any character that is not a command (typically /)
The delimiter MUST be the first character after the command
Returns empty string on error
*/
#if 0
BUILT_IN_FUNCTION(function_msar, word)
{
register char delimiter;
register char *pointer = NULL;
char *search = NULL;
char *replace = NULL;
char *data = NULL;
char *value = NULL;
char *booya = NULL;
char *p = NULL;
int variable = 0,this_global = 0,searchlen,oldwindow = window_display;
char *(*func) (const char *, const char *) = strstr;
char *svalue = NULL;
while (((*word == 'r') && (variable = 1)) || ((*word == 'g') && (this_global = 1)) || ((*word == 'i') && (func = (char *(*)(const char *, const char *))global[STRISTR])))
word++;
RETURN_IF_EMPTY(word);
delimiter = *word;
search = word + 1;
if (!(replace = strchr(search, delimiter)))
RETURN_EMPTY;
*replace++ = 0;
if (!(data = strchr(replace,delimiter)))
RETURN_EMPTY;
*data++ = 0;
if (!(p = strrchr(data, delimiter)))
value = (variable == 1) ? get_variable(data) : m_strdup(data);
else
{
*p++ = 0;
value = (variable == 1) ? get_variable(p) : m_strdup(p);
}
if (!value || !*value)
{
new_free(&value);
RETURN_EMPTY;
}
pointer = svalue = value;
do
{
if ( (searchlen = (strlen(search) - 1)) < 0)
searchlen = 0;
if (this_global)
{
while ((pointer = func(pointer,search)))
{
pointer[0] = pointer[searchlen] = 0;
pointer += searchlen + 1;
m_e3cat(&booya, value, replace);
value = pointer;
if (!*pointer)
break;
}
}
else
{
if ((pointer = func(pointer,search)))
{
pointer[0] = pointer[searchlen] = 0;
pointer += searchlen + 1;
m_e3cat(&booya, value, replace);
value = pointer;
}
}
malloc_strcat(&booya, value);
if (data && *data)
{
new_free(&svalue);
search = data;
if ((replace = strchr(data, delimiter)))
{
*replace++ = 0;
if ((data = strchr(replace, delimiter)))
*data++ = 0;
}
/* patch from RoboHak */
if (!replace || !search)
{
pointer = value = svalue;
break;
}
pointer = value = svalue = booya;
booya = NULL;
} else
break;
} while (1);
if (variable)
{
window_display = 0;
add_var_alias(data, booya);
window_display = oldwindow;
}
new_free(&svalue);
return booya ? booya : m_strdup(empty_string);
}
#endif
BUILT_IN_FUNCTION(function_msar, word)
{
char delimiter;
char *pointer = NULL;
char *search = NULL;
char *replace = NULL;
char *data = NULL;
char *value = NULL;
char *booya = NULL;
char *p = NULL;
int variable = 0,
this_global = 0,
searchlen,
oldwindow = window_display;
char *(*func) (const char *, const char *) = strstr;
char *svalue;
while (((*word == 'r') && (variable = 1)) || ((*word == 'g') && (this_global = 1)) || ((*word == 'i') && (func = (char *(*)(const char *, const char *))global[STRISTR])))
word++;
RETURN_IF_EMPTY(word);
delimiter = *word;
search = word + 1;
if (!(replace = strchr(search, delimiter)))
RETURN_EMPTY;
*replace++ = 0;
if (!(data = strchr(replace,delimiter)))
RETURN_EMPTY;
*data++ = 0;
if (!(p = strrchr(data, delimiter)))
value = (variable == 1) ? get_variable(data) : m_strdup(data);
else
{
*p++ = 0;
value = (variable == 1) ? get_variable(p) : m_strdup(p);
}
if (!value || !*value)
{
new_free(&value);
RETURN_EMPTY;
}
pointer = svalue = value;
do
{
searchlen = strlen(search) - 1;
if (searchlen < 0)
searchlen = 0;
if (this_global)
{
while ((pointer = func(pointer,search)))
{
pointer[0] = pointer[searchlen] = 0;
pointer += searchlen + 1;
m_e3cat(&booya, value, replace);
value = pointer;
if (!*pointer)
break;
}
}
else
{
if ((pointer = func(pointer,search)))
{
pointer[0] = pointer[searchlen] = 0;
pointer += searchlen + 1;
m_e3cat(&booya, value, replace);
value = pointer;
}
}
malloc_strcat(&booya, value);
if (data && *data)
{
new_free(&svalue);
search = data;
if ((replace = strchr(data, delimiter)))
{
*replace++ = 0;
if ((data = strchr(replace, delimiter)))
*data++ = 0;
}
/* patch from RoboHak */
if (!replace || !search)
{
pointer = value = svalue;
break;
}
pointer = value = svalue = booya;
booya = NULL;
} else
break;
} while (1);
if (variable)
{
window_display = 0;
add_var_alias(data, booya);
window_display = oldwindow;
}
new_free(&svalue);
return (booya);
}
BUILT_IN_FUNCTION(function_center, word)
{
int length,pad,width;
char *padc;
if (!word || !*word)
RETURN_EMPTY;
width = atoi(new_next_arg(word, &word));
RETURN_IF_EMPTY(word);
length = strlen(word);
if ((pad = width - length) < 0)
RETURN_STR(word);
pad /= 2;
padc = (char *)new_malloc(width+1);
memset(padc, ' ', pad);
padc[pad] = '\0';
return strcat(padc, word);
}
BUILT_IN_FUNCTION(function_split, word)
{
char *chrs;
register char *pointer;
chrs = next_arg(word, &word);
pointer = word;
while ((pointer = sindex(pointer,chrs)))
*pointer++ = ' ';
RETURN_STR(word);
}
BUILT_IN_FUNCTION(function_chr, word)
{
char aboo[BIG_BUFFER_SIZE];
unsigned char *ack = aboo;
char *blah;
while ((blah = next_arg(word, &word)))
*ack++ = (unsigned char)atoi(blah);
*ack = '\0';
RETURN_STR(aboo);
}
BUILT_IN_FUNCTION(function_ascii, word)
{
char *aboo = NULL;
unsigned char *w = word;
if (!word || !*word)
RETURN_EMPTY;
aboo = m_strdup(ltoa((unsigned long) *w));
while (*++w)
m_3cat(&aboo, space, ltoa((unsigned long) *w));
return (aboo);
}
BUILT_IN_FUNCTION(function_which, word)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char *file1;
GET_STR_ARG(file1, word);
if ((file1 = path_search(file1, (word && *word) ? word :
get_string_var(LOAD_PATH_VAR))))
{
RETURN_STR(file1);
}
else
{
new_free(&file1);
RETURN_EMPTY;
}
#endif
}
BUILT_IN_FUNCTION(function_isalpha, input)
{
if (isalpha((unsigned char)*input))
RETURN_INT(1);
else
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isdigit, input)
{
if (isdigit((unsigned char)*input))
RETURN_INT(1);
else
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isalnum, input)
{
if (isalpha((unsigned char)*input) || isdigit((unsigned char)*input))
RETURN_INT(1);
else
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isspace, input)
{
if (isspace((unsigned char)*input))
RETURN_INT(1);
else
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isxdigit, input)
{
#define ishex(x) \
((x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f'))
if (isdigit((unsigned char)*input) || ishex(*input))
RETURN_INT(1);
else
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_serverpass, input)
{
int servnum = from_server;
if (*input)
GET_INT_ARG(servnum, input);
if (servnum == -1)
servnum = from_server;
if (servnum < 0 || servnum > server_list_size())
RETURN_EMPTY;
return m_sprintf("%d", get_server_pass(servnum));
}
BUILT_IN_FUNCTION(function_open, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char *filename;
char *mode;
char *bin_mode = NULL;
GET_STR_ARG(filename, words);
GET_STR_ARG(mode, words);
if (in_cparse)
RETURN_EMPTY;
if (words && *words)
bin_mode = words;
if (*mode == 'R' || *mode == 'r')
{
if (bin_mode && (*bin_mode == 'B' || *bin_mode == 'b'))
RETURN_INT(open_file_for_read(filename));
else
RETURN_INT(open_file_for_read(filename));
}
else if (*mode == 'W' || *mode == 'w')
{
if (bin_mode && (*bin_mode == 'B' || *bin_mode == 'b'))
RETURN_INT(open_file_for_bwrite(filename));
else
RETURN_INT(open_file_for_write(filename));
}
RETURN_EMPTY;
#endif
}
BUILT_IN_FUNCTION(function_close, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
RETURN_IF_EMPTY(words);
if (in_cparse)
RETURN_INT(0);
RETURN_INT(file_close(atoi(new_next_arg(words, &words))));
#endif
}
BUILT_IN_FUNCTION(function_write, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char *fdc;
if (in_cparse)
RETURN_INT(0);
GET_STR_ARG(fdc, words);
RETURN_INT(file_write(atoi(fdc), words));
#endif
}
BUILT_IN_FUNCTION(function_writeb, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char *fdc;
if (in_cparse)
RETURN_INT(0);
GET_STR_ARG(fdc, words);
RETURN_INT(file_writeb(atoi(fdc), words));
#endif
}
BUILT_IN_FUNCTION(function_read, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char *fdc = NULL, *numb = NULL;
if (in_cparse)
RETURN_INT(0);
GET_STR_ARG(fdc, words);
if (words && *words)
GET_STR_ARG(numb, words);
if (numb)
return file_readb (atoi(fdc), atoi(numb));
else
return file_read (atoi(fdc));
#endif
}
BUILT_IN_FUNCTION(function_eof, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
RETURN_IF_EMPTY(words);
RETURN_INT(file_eof(atoi(new_next_arg(words, &words))));
#endif
}
BUILT_IN_FUNCTION(function_iptoname, words)
{
char *ret = ip_to_host(words);
RETURN_STR(ret);
}
BUILT_IN_FUNCTION(function_nametoip, words)
{
char *ret = host_to_ip(words);
RETURN_STR(ret);
}
BUILT_IN_FUNCTION(function_convert, words)
{
char *ret = one_to_another(words);
RETURN_STR(ret);
}
BUILT_IN_FUNCTION(function_translate, words)
{
register char * oldc;
char * newc,
* text,
delim;
register char * ptr;
int size_old,
size_new,
x;
RETURN_IF_EMPTY(words);
oldc = words;
/* First character can be a slash. If it is, we just skip over it */
delim = *oldc++;
newc = strchr(oldc, delim);
if (!newc)
RETURN_EMPTY; /* no text in, no text out */
text = strchr(++newc, delim);
if (newc == oldc)
RETURN_EMPTY;
if (!text)
RETURN_EMPTY;
*text++ = '\0';
if (newc == text)
{
*newc = '\0';
newc = empty_string;
}
else
newc[-1] = 0;
/* this is cheating, but oh well, >;-) */
text = m_strdup(text);
size_new = strlen(newc);
size_old = strlen(oldc);
for (ptr = text; ptr && *ptr; ptr++)
{
for (x = 0;x < size_old;(void)x++)
{
if (*ptr == oldc[x])
{
/* Check to make sure we arent
just eliminating the character.
If we arent, put in the new char,
otherwise strcpy it away */
if (size_new)
*ptr = newc[(x<size_new)?x:size_new-1];
else
{
ov_strcpy (ptr, ptr+1);
ptr--;
}
break;
}
}
}
return text;
}
BUILT_IN_FUNCTION(function_server_version, word)
{
int servnum;
int version;
servnum = ((word && *word) ? atoi(next_arg(word, &word)) : primary_server);
if (servnum > server_list_size())
RETURN_STR("unknown");
version = get_server_version(servnum);
if (version == Server2_8) RETURN_STR("2.8");
else if (version == Server2_9) RETURN_STR("2.9");
else if (version == Server2_10) RETURN_STR("2.10");
else if (version == Server2_8ts4) RETURN_STR("2.8ts4");
else if (version == Server2_8hybrid) RETURN_STR("2.8hybrid5");
else if (version == Server2_8hybrid6) RETURN_STR("2.8hybrid6");
else if (version == Server2_8comstud) RETURN_STR("2.8comstud");
else if (version == Server_u2_8) RETURN_STR("u2.8");
else if (version == Server_u2_9) RETURN_STR("u2.9");
else if (version == Server_u2_10) RETURN_STR("u2.10");
else if (version == Server_u3_0) RETURN_STR("u3.0");
RETURN_STR("Unknown");
}
BUILT_IN_FUNCTION(function_unlink, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char * expanded;
int failure = 0;
if (in_cparse)
RETURN_INT(0);
while (words && *words)
{
expanded = expand_twiddle(new_next_arg(words, &words));
failure -= unlink(expanded);
new_free(&expanded);
}
RETURN_INT(failure);
#endif
}
BUILT_IN_FUNCTION(function_rename, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char * filename1,
* filename2;
char *expanded1, *expanded2;
int failure = 0;
if (in_cparse)
RETURN_INT(failure);
GET_STR_ARG(filename1, words);
GET_STR_ARG(filename2, words);
expanded1 = expand_twiddle(filename1);
expanded2 = expand_twiddle(filename2);
failure = rename(expanded1, expanded2);
new_free(&expanded1); new_free(&expanded2);
RETURN_INT(failure);
#endif
}
BUILT_IN_FUNCTION(function_rmdir, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int failure = 0;
char *expanded;
if (in_cparse)
RETURN_INT(failure);
while (words && *words)
{
expanded = expand_twiddle(new_next_arg(words, &words));
failure -= rmdir(expanded);
new_free(&expanded);
}
RETURN_INT(failure);
#endif
}
BUILT_IN_FUNCTION(function_truncate, words)
{
int num = 0;
double value = 0;
char buffer[BIG_BUFFER_SIZE],
format[BIG_BUFFER_SIZE];
GET_INT_ARG(num, words);
GET_FLOAT_ARG(value, words);
if (num < 0)
{
float foo;
int end;
sprintf(format, "%%.%de", -num-1);
sprintf(buffer, format, value);
foo = atof(buffer);
sprintf(buffer, "%f", foo);
end = strlen(buffer) - 1;
if (end == 0)
RETURN_EMPTY;
while (buffer[end] == '0')
end--;
if (buffer[end] == '.')
end--;
buffer[end+1] = 0;
}
else if (num > 0)
{
sprintf(format, "%%10.%dlf", num);
sprintf(buffer, format, value);
}
else
RETURN_EMPTY;
while (*buffer == ' ')
ov_strcpy(buffer, buffer+1);
RETURN_STR(buffer);
}
/*
* Apprantly, this was lifted from a CS client. I reserve the right
* to replace this code in future versions. (hop)
*/
/*
I added this little function so that I can have stuff formatted
into days, hours, minutes, seconds; but with d, h, m, s abreviations.
-Taner
*/
BUILT_IN_FUNCTION(function_tdiff2, input)
{
time_t ltime;
time_t days,
hours,
minutes,
seconds;
char tmp[80];
char *tstr;
GET_INT_ARG(ltime, input);
seconds = ltime % 60;
ltime = (ltime - seconds) / 60;
minutes = ltime%60;
ltime = (ltime - minutes) / 60;
hours = ltime % 24;
days = (ltime - hours) / 24;
tstr = tmp;
if (days)
{
sprintf(tstr, "%ldd ", days);
tstr += strlen(tstr);
}
if (hours)
{
sprintf(tstr, "%ldh ", hours);
tstr += strlen(tstr);
}
if (minutes)
{
sprintf(tstr, "%ldm ", minutes);
tstr += strlen(tstr);
}
if (seconds || (!days && !hours && !minutes))
{
sprintf(tstr, "%lds", seconds);
tstr += strlen(tstr);
}
else
*--tstr = 0; /* chop off that space! */
RETURN_STR(tmp);
}
/*
* Apparantly, this was lifted from a CS client. I reserve the right
* to replace this code in a future release.
*/
BUILT_IN_FUNCTION(function_utime, input)
{
struct timeval tp;
get_time(&tp);
return m_sprintf("%ld %ld",(unsigned long)tp.tv_sec, (unsigned long)tp.tv_usec);
}
/*
* This inverts any ansi sequence present in the string
* from: Scott H Kilau <kilau@prairie.NoDak.edu>
*/
BUILT_IN_FUNCTION(function_stripansi, input)
{
register unsigned char *cp;
for (cp = input; *cp; cp++)
if (*cp < 31 && *cp > 13)
if (*cp != 15 && *cp !=22)
*cp = (*cp & 127) | 64;
RETURN_STR(input);
}
#if 0
BUILT_IN_FUNCTION(function_stripansicodes, inPut)
{
RETURN_IF_EMPTY(input);
RETURN_STR(stripansicodes(input));
}
#endif
BUILT_IN_FUNCTION(function_stripc, input)
{
char *retval;
retval = LOCAL_COPY(input);
strcpy_nocolorcodes(retval, input);
RETURN_STR(retval);
}
BUILT_IN_FUNCTION(function_servername, input)
{
int sval = from_server;
const char *which;
if(*input)
GET_INT_ARG(sval, input);
/* garbage in, garbage out. */
if (sval < 0 || sval >= server_list_size())
RETURN_EMPTY;
/* First we try to see what the server thinks it name is */
which = get_server_itsname(sval);
/* Next we try what we think its name is */
if (!which)
which = get_server_name(sval);
/* Ok. i give up, return a null. */
RETURN_STR(which);
}
BUILT_IN_FUNCTION(function_serverport, input)
{
int servnum = from_server;
if (*input)
GET_INT_ARG(servnum, input);
if (servnum == -1)
servnum = from_server;
if (servnum < 0 || servnum > server_list_size())
RETURN_EMPTY;
return m_sprintf("%d %d", get_server_port(servnum),
get_server_local_port(servnum));
}
BUILT_IN_FUNCTION(function_lastserver, input)
{
RETURN_INT(last_server);
}
/*
* Date: Sat, 26 Apr 1997 13:41:11 +1200
* Author: IceKarma (ankh@canuck.gen.nz)
* Contributed by: author
*
* Usage: $winchan(#channel <server refnum|server name>)
* Given a channel name and either a server refnum or a direct server
* name or an effective server name, this function will return the
* refnum of the window where the channel is the current channel (on that
* server if appropriate.)
*
* Returns -1 (Too few arguments specified, or Window Not Found) on error.
*/
BUILT_IN_FUNCTION(function_chanwin, input)
{
char *arg1 = NULL;
if (input && *input)
GET_STR_ARG(arg1, input);
/*
* Return window refnum by channel
*/
if (arg1 && is_channel(arg1))
{
int servnum = from_server;
char *chan,
*serv = NULL;
ChannelList *ch = NULL;
chan = arg1;
if ((serv = new_next_arg(input, &input)))
{
if (my_isdigit(serv))
servnum = my_atol(serv);
else
servnum = find_in_server_list(serv, 0);
}
if((ch = lookup_channel(chan, servnum, CHAN_NOUNLINK)) && ch->window)
RETURN_INT(ch->window->refnum);
if (fn && !strcmp(fn, "CHANWINDOW"))
RETURN_INT(0);
else
RETURN_INT(-1);
}
/*
* Return channel by window refnum/desc
*/
else
{
Window *win = current_window;
if (arg1 && *arg1)
win = get_window_by_desc(arg1);
if (!win)
RETURN_EMPTY;
RETURN_STR(win->current_channel);
}
if (fn && !strcmp(fn, "CHANWINDOW"))
RETURN_INT(0);
RETURN_INT(-1);
}
BUILT_IN_FUNCTION(function_winserv, input)
{
int win = 0;
char *tmp;
Window *winp;
if (input && *input)
{
if ((tmp = new_next_arg(input, &input)))
win = atoi(tmp);
}
if ((winp = get_window_by_refnum(win)))
RETURN_INT(winp->server);
RETURN_INT(-1);
}
BUILT_IN_FUNCTION(function_numwords, input)
{
RETURN_INT(word_count(input));
}
BUILT_IN_FUNCTION(function_strlen, input)
{
RETURN_INT(strlen(input));
}
/*
* Next two contributed by Scott H Kilau (sheik), who for some reason doesnt
* want to take credit for them. *shrug* >;-)
*
* Deciding not to be controversial, im keeping the original (contributed)
* semantics of these two functions, which is to return 1 on success and
* -1 on error. If you dont like it, then tough. =) I didnt write it, and
* im not going to second guess any useful contributions. >;-)
*/
BUILT_IN_FUNCTION(function_fexist, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char FileBuf[BIG_BUFFER_SIZE+1];
char *filename, *fullname;
*FileBuf = 0;
if ((filename = new_next_arg(words, &words)))
{
if (*filename == '/')
strlcpy(FileBuf, filename, BIG_BUFFER_SIZE);
else if (*filename == '~')
{
if (!(fullname = expand_twiddle(filename)))
RETURN_INT(-1);
strmcpy(FileBuf, fullname, BIG_BUFFER_SIZE);
new_free(&fullname);
}
#if defined(__EMX__) || defined(WINNT)
else if (is_dos(filename))
strmcpy(FileBuf, filename, BIG_BUFFER_SIZE);
#endif
else
{
getcwd(FileBuf, BIG_BUFFER_SIZE);
strmcat(FileBuf, "/", BIG_BUFFER_SIZE);
strmcat(FileBuf, filename, BIG_BUFFER_SIZE);
}
#if defined(__EMX__) || defined(WINNT)
convert_dos(FileBuf);
#endif
if (access(FileBuf, R_OK) == -1)
RETURN_INT(-1);
else
RETURN_INT(1);
}
RETURN_INT(-1);
#endif
}
/* XXXX - ugh. do we really have to do a access() call first? */
BUILT_IN_FUNCTION(function_fsize, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char FileBuf[BIG_BUFFER_SIZE+1];
char *filename, *fullname;
struct stat stat_buf;
off_t filesize = 0;
filename = new_next_arg(words, &words);
*FileBuf = 0;
if (filename && *filename)
{
if (*filename == '/')
strlcpy(FileBuf, filename, BIG_BUFFER_SIZE);
else if (*filename == '~')
{
if (!(fullname = expand_twiddle(filename)))
RETURN_INT(-1);
strmcpy(FileBuf, fullname, BIG_BUFFER_SIZE);
new_free(&fullname);
}
#if defined(__EMX__) || defined(WINNT)
else if (is_dos(filename))
strmcpy(FileBuf, filename, BIG_BUFFER_SIZE);
#endif
else
{
getcwd(FileBuf, BIG_BUFFER_SIZE);
strmcat(FileBuf, "/", BIG_BUFFER_SIZE);
strmcat(FileBuf, filename, BIG_BUFFER_SIZE);
}
#if defined(__EMX__) || defined(WINNT)
convert_dos(FileBuf);
#endif
if ((stat(FileBuf, &stat_buf)) != -1)
{
filesize = stat_buf.st_size;
RETURN_INT(filesize);
}
}
RETURN_INT(-1);
#endif
}
/*
* Contributed by CrowMan
* I changed two instances of "RETURN_INT(result)"
* (where result was a null pointer) to RETURN_STR(empty_string)
* because i dont think he meant to return a null pointer as an int value.
*/
/*
* $crypt(password seed)
* What it does: Returns a 13-char encrypted string when given a seed and
* password. Returns zero (0) if one or both args missing. Additional
* args ignored.
* Caveats: Password truncated to 8 chars. Spaces allowed, but password
* must be inside "" quotes.
* Credits: Thanks to Strongbow for showing me how crypt() works.
* This cheap hack by: CrowMan
*/
BUILT_IN_FUNCTION(function_crypt, words)
{
#if defined(WINNT)
RETURN_STR(empty_string);
#else
char pass[9] = "\0";
char seed[3] = "\0";
char *blah, *bleh, *crypt (const char *, const char *);
GET_STR_ARG(blah, words)
GET_STR_ARG(bleh, words)
strmcpy(pass, blah, 8);
strmcpy(seed, bleh, 2);
RETURN_STR(crypt(pass, seed));
#endif
}
BUILT_IN_FUNCTION(function_info, words)
{
/*
char *which;
extern char *compile_info;
extern char *info_c_sum;
GET_STR_ARG(which, words);
if (!my_strnicmp(which, "C", 1))
RETURN_STR(compile_info);
else if (!my_strnicmp(which, "S", 1))
RETURN_STR(info_c_sum);
else
*/
return m_sprintf("%s+%s", version, compile_time_options);
/* more to be added as neccesary */
}
/*
* Based on a contribution made a very long time ago by wintrhawk
*/
BUILT_IN_FUNCTION(function_channelmode, word)
{
char *channel;
char *booya = NULL;
char *mode;
int type_mode = 0;
do
{
channel = new_next_arg(word, &word);
if ((!channel || !*channel) && booya)
break;
if (word && *word && isdigit((unsigned char)*word))
GET_INT_ARG(type_mode, word);
switch(type_mode)
{
case 1: /* bans */
case 2: /* ban who time */
case 3: /* exemptions [ts4] */
mode = get_channel_bans(channel, from_server, type_mode);
m_s3cat(&booya, space, (mode && *mode) ? mode : "*");
new_free(&mode);
continue;
case 0:
default:
mode = get_channel_mode(channel, from_server);
break;
}
m_s3cat(&booya, space, (mode && *mode) ? mode : "*");
}
while (word && *word);
return (booya ? booya : m_strdup(empty_string));
}
BUILT_IN_FUNCTION(function_geom, words)
{
/* Erf. CO and LI are ints. (crowman) */
return m_sprintf("%d %d", current_term->TI_cols, current_term->TI_lines);
}
BUILT_IN_FUNCTION(function_pass, words)
{
char *lookfor;
char *final, *ptr;
GET_STR_ARG(lookfor, words);
final = (char *)new_malloc(strlen(words) + 1);
ptr = final;
while (*words)
{
if (strchr(lookfor, *words))
*ptr++ = *words;
words++;
}
*ptr = 0;
return final;
}
BUILT_IN_FUNCTION(function_uptime, input)
{
time_t ltime;
time_t days,hours,minutes,seconds;
struct timeval tp;
static time_t timestart = 0;
time_t timediff;
char buffer[BIG_BUFFER_SIZE+1];
*buffer = '\0';
get_time(&tp);
if (timestart == 0)
{
timestart = tp.tv_sec;
timediff = 0;
} else
timediff = tp.tv_sec - timestart;
ltime = timediff;
seconds = ltime % 60;
ltime = (ltime - seconds) / 60;
minutes = ltime%60;
ltime = (ltime - minutes) / 60;
hours = ltime % 24;
days = (ltime - hours) / 24;
sprintf(buffer, "%ldd %ldh %ldm %lds", days, hours, minutes, seconds);
RETURN_STR(buffer);
}
BUILT_IN_FUNCTION(function_cluster, input)
{
char *q;
RETURN_IF_EMPTY(input);
if ((q = cluster(input)))
RETURN_STR(q);
else
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_checkshit, input)
{
char *uh = NULL;
char *channel = NULL;
register ShitList *tmp;
int matched = 0;
GET_STR_ARG(uh, input);
GET_STR_ARG(channel, input);
for (tmp = shitlist_list; tmp; tmp = tmp->next)
{
if (wild_match(tmp->filter, uh) && check_channel_match(tmp->channels, channel))
{
matched = 1;
break;
}
}
if (tmp && matched)
return m_sprintf("%d %s %s %s", tmp->level, tmp->channels, tmp->filter, tmp->reason);
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_get_info, input)
{
#ifdef WANT_USERLIST
char *nick;
register UserList *tmp;
void *needed = NULL;
int size = -1;
GET_STR_ARG(nick, input);
for (tmp = next_userlist(NULL, &size, &needed); tmp; tmp = next_userlist(tmp, &size, &needed))
{
if (!my_stricmp(nick, tmp->nick) || wild_match(nick, tmp->nick))
{
if (tmp->comment)
RETURN_STR(tmp->comment);
}
}
#endif
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_set_info, input)
{
#ifdef WANT_USERLIST
char *nick;
register UserList *tmp;
void *location = NULL;
int size = -1;
int done = 0;
GET_STR_ARG(nick, input);
for (tmp = next_userlist(NULL, &size, &location); tmp; tmp = next_userlist(tmp, &size, &location))
{
if (!my_stricmp(tmp->nick, nick) || wild_match(nick, tmp->nick))
{
if (input && *input)
malloc_strcpy(&tmp->comment, input);
else
new_free(&tmp->comment);
done++;
}
}
if (done)
RETURN_INT(1);
#endif
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_checkuser, input)
{
#ifdef WANT_USERLIST
char *uh = NULL;
char *channel = NULL;
register UserList *tmp;
GET_STR_ARG(uh, input);
GET_STR_ARG(channel, input);
if (!uh || !*uh || !channel || !*channel)
RETURN_EMPTY;
if ((tmp = find_bestmatch("*", uh, channel, NULL)))
return m_sprintf("%d %s %s %s", tmp->flags, tmp->host, tmp->channels, tmp->password?tmp->password:empty_string);
#endif
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_rot13, input)
{
char temp[BIG_BUFFER_SIZE+1];
register char *p = NULL;
int rotate = 13;
strmcpy(temp, input, BIG_BUFFER_SIZE);
for (p = temp; *p; p++) {
if (*p >= 'A' && *p <='Z')
*p = (*p - 'A' + rotate) % 26 + 'A';
else if (*p >= 'a' && *p <= 'z')
*p = (*p - 'a' + rotate) % 26 + 'a';
}
RETURN_STR(temp);
}
BUILT_IN_FUNCTION(function_repeat, words)
{
register int num;
char *final = NULL;
GET_INT_ARG(num, words);
if (num < 1)
RETURN_EMPTY;
final = (char *)new_malloc(strlen(words) * num + 1);
for (; num > 0; num--)
strcat(final, words);
if (strlen(final) > BIG_BUFFER_SIZE)
final[BIG_BUFFER_SIZE] = 0;
return final;
}
BUILT_IN_FUNCTION(function_bcopy, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int from, to;
if (in_cparse)
RETURN_INT(0);
GET_INT_ARG(from, words);
GET_INT_ARG(to, words);
RETURN_INT(file_copy(from, to));
#endif
}
BUILT_IN_FUNCTION(function_epic, words)
{
RETURN_INT(1);
}
BUILT_IN_FUNCTION(function_runlevel, words)
{
extern int run_level;
RETURN_INT(run_level);
}
BUILT_IN_FUNCTION(function_ovserver, words)
{
int ovserver;
char *servname = NULL;
GET_INT_ARG(ovserver, words);
if(ovserver > -1)
servname = ov_server(ovserver);
if(servname)
RETURN_STR(servname);
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_winsize, words)
{
int refnum;
Window *win;
if (words && *words)
{
GET_INT_ARG(refnum, words);
win = get_window_by_refnum(refnum);
}
else
win = current_window;
if (!win)
RETURN_EMPTY;
RETURN_INT(win->display_size);
}
BUILT_IN_FUNCTION(function_umode, words)
{
int servnum;
if (words && *words)
{
GET_INT_ARG(servnum, words);
}
else
servnum = from_server;
RETURN_STR(get_umode(servnum));
}
BUILT_IN_FUNCTION(function_lastnotice, words)
{
int count = 0;
char *str = NULL;
GET_INT_ARG(count, words);
if (count >= MAX_LAST_MSG)
count = 0;
RETURN_IF_EMPTY(last_notice[count].last_msg);
malloc_sprintf(&str, "%s %s %s %s %s", last_notice[count].time, last_notice[count].from, last_notice[count].uh, last_notice[count].to, last_notice[count].last_msg);
return str;
}
BUILT_IN_FUNCTION(function_lastmessage, words)
{
int count = 0;
char *str = NULL;
GET_INT_ARG(count, words);
if (count >= MAX_LAST_MSG)
count = 0;
RETURN_IF_EMPTY(last_msg[count].last_msg);
malloc_sprintf(&str, "%s %s %s %s %s", last_msg[count].time, last_msg[count].from, last_msg[count].uh, last_msg[count].to, last_msg[count].last_msg);
return str;
}
char *function_addtabkey (char *n, char *words)
{
char *arrayname = NULL;
char *nick = NULL;
GET_STR_ARG(nick, words);
if (words && *words)
arrayname = new_next_arg(words, &words);
addtabkey(nick, NULL, arrayname ? 1: 0);
RETURN_EMPTY;
}
char *function_gettabkey (char *n, char *words)
{
char *arrayname = NULL;
NickTab *nick = NULL;
int direction;
GET_INT_ARG(direction, words);
if (words && *words)
arrayname = new_next_arg(words, &words);
if (arrayname && !my_stricmp(arrayname, "AUTOREPLY"))
nick = gettabkey(direction, 1, NULL);
else
nick = gettabkey(direction, 0, NULL);
return nick ? m_strdup(nick->nick) : m_strdup(empty_string);
}
static int sort_it (const void *one, const void *two)
{
return my_stricmp(*(char **)one, *(char **)two);
}
BUILT_IN_FUNCTION(function_sort, words)
{
int wordc;
char **wordl;
wordc = splitw(words, &wordl);
qsort((void *)wordl, wordc, sizeof(char *), sort_it);
return unsplitw(&wordl, wordc); /* DONT USE RETURN_STR() HERE */
}
BUILT_IN_FUNCTION(function_notify, words)
{
int showon = -1, showserver = from_server;
char *firstw;
int len = 0;
char *buf = NULL, *ret = NULL;
while (words && *words)
{
firstw = new_next_arg(words, &words);
len = strlen(firstw);
if (*firstw == '+')
{
if (len == 1)
showon = 1;
else
buf = get_notify_nicks(showserver, 1, firstw+1, 0);
}
else if (*firstw == '-')
{
if (len == 1)
showon = 0;
else
buf = get_notify_nicks(showserver, 1, firstw+1, 0);
}
else if (*firstw == '!')
{
if (len != 1)
buf = get_notify_nicks(showserver, showon, firstw+1, 1);
}
else if (!my_strnicmp(firstw, "serv", 4))
GET_INT_ARG(showserver, words);
if (buf)
{
m_s3cat(&ret, space, buf);
new_free(&buf);
}
}
/* dont use RETURN_STR() here. */
return ret ? ret : get_notify_nicks(showserver, showon, NULL, 0);
}
BUILT_IN_FUNCTION(function_watch, words)
{
int showon = -1, showserver = from_server;
char *firstw;
int len = 0;
char *buf = NULL, *ret = NULL;
while (words && *words)
{
firstw = new_next_arg(words, &words);
len = strlen(firstw);
if (*firstw == '+')
{
if (len == 1)
showon = 1;
else
buf = get_watch_nicks(showserver, 1, firstw+1, 0);
}
else if (*firstw == '-')
{
if (len == 1)
showon = 0;
else
buf = get_watch_nicks(showserver, 1, firstw+1, 0);
}
else if (*firstw == '!')
{
if (len != 1)
buf = get_watch_nicks(showserver, showon, firstw+1, 1);
}
else if (!my_strnicmp(firstw, "serv", 4))
GET_INT_ARG(showserver, words);
if (buf)
{
m_s3cat(&ret, space, buf);
new_free(&buf);
}
}
/* dont use RETURN_STR() here. */
return ret ? ret : get_watch_nicks(showserver, showon, NULL, 0);
}
static int num_sort_it (const void *one, const void *two)
{
char *oneptr = *(char **)one;
char *twoptr = *(char **)two;
long val1, val2;
while (*oneptr && *twoptr)
{
while (*oneptr && *twoptr && !isdigit((unsigned char)*oneptr) && !isdigit((unsigned char)*twoptr))
{
if (*oneptr != *twoptr)
return (*oneptr - *twoptr);
oneptr++, twoptr++;
}
if (!*oneptr || !*twoptr)
break;
val1 = strtol(oneptr, (char **)&oneptr, 10);
val2 = strtol(twoptr, (char **)&twoptr, 10);
if (val1 != val2)
return val1 - val2;
}
return (*oneptr - *twoptr);
}
BUILT_IN_FUNCTION(function_numsort, words)
{
int wordc;
char **wordl;
wordc = splitw(words, &wordl);
qsort((void *)wordl, wordc, sizeof(char *), num_sort_it);
return unsplitw(&wordl, wordc); /* DONT USE RETURN_STR() HERE */
}
#ifdef NEED_GLOB
#define glob bsd_glob
#define globfree bsd_globfree
#endif
BUILT_IN_FUNCTION(function_glob, word)
{
#if defined(INCLUDE_GLOB_FUNCTION) && !defined(PUBLIC_ACCESS)
char *path,
*path2 = NULL,
*retval = NULL;
int numglobs,
i;
glob_t globbers;
memset(&globbers, 0, sizeof(glob_t));
while (word && *word)
{
GET_STR_ARG(path, word);
path2 = expand_twiddle(path);
if (!path2)
path2 = m_strdup(path);
numglobs = glob(path2, GLOB_MARK, NULL, &globbers);
if (numglobs < 0)
{
new_free(&path2);
RETURN_INT(numglobs);
}
for (i = 0; i < globbers.gl_pathc; i++)
{
if (strchr(globbers.gl_pathv[i], ' '))
{
int len = strlen(globbers.gl_pathv[i])+4;
char *b = alloca(len+1);
*b = 0;
strmopencat(b, len, "\"", globbers.gl_pathv[i], "\"", NULL);
m_s3cat(&retval, space, b);
}
else
m_s3cat(&retval, space, globbers.gl_pathv[i]);
}
globfree(&globbers);
new_free(&path2);
}
return retval ? retval : m_strdup(empty_string);
#else
RETURN_EMPTY;
#endif
}
BUILT_IN_FUNCTION(function_mkdir, words)
{
#ifdef PUBLIC_ACCESS
RETURN_EMPTY;
#else
int failure = 0;
char *expanded;
while (words && *words)
{
expanded = expand_twiddle(new_next_arg(words, &words));
failure -= mkdir(expanded, 0777);
new_free(&expanded);
}
RETURN_INT(failure);
#endif
}
BUILT_IN_FUNCTION(function_umask, words)
{
int new_umask;
GET_INT_ARG(new_umask, words);
RETURN_INT(umask(new_umask));
}
extern char *get_help_topic (char *, int);
extern int read_file (FILE *, int);
BUILT_IN_FUNCTION(function_help, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
#ifdef WANT_CHELP
char *filename = NULL, *subject = NULL;
static int first_time = 1;
FILE *help_file;
GET_STR_ARG(subject, words);
if (words && *words)
words = next_arg(filename, &words);
else
malloc_strcpy(&filename, get_string_var(SCRIPT_HELP_VAR));
if (first_time && filename)
{
char *new_file = NULL;
malloc_strcpy(&new_file, filename);
if (!(help_file = uzfopen(&new_file, ".", 0)))
{
new_free(&new_file);
RETURN_EMPTY;
}
first_time = 0;
new_free(&new_file);
read_file(help_file, 1);
fclose(help_file);
} else if (first_time) RETURN_EMPTY;
return get_help_topic(subject, (filename) ? 1 : 0);
#else
RETURN_EMPTY;
#endif
#endif
}
BUILT_IN_FUNCTION(function_isuser, words)
{
#ifdef WANT_USERLIST
char *nick = NULL;
char *uhost = NULL;
char *channel = NULL;
register UserList *User;
register ShitList *Shit;
GET_STR_ARG(nick, words);
GET_STR_ARG(uhost, words);
if (words && *words)
channel = words;
else
channel = "*";
if ((User = lookup_userlevelc("*", uhost, channel, NULL)))
return m_sprintf("USER %d %s %s", User->flags, User->host, User->channels);
if ((Shit = nickinshit(nick, uhost)) && check_channel_match(Shit->channels, channel))
return m_sprintf("SHIT %s %d %s", Shit->filter, Shit->level, Shit->channels);
#endif
RETURN_EMPTY;
}
/*
$pad(N string of text goes here)
if N is negative, it'll pad to the right
if N is positive, it'll pad to the left
so something like: $pad(20 letters) would output:
letters
and $pad(20 some string) would be:
some string
GREAT way to allign shit, and if you use $curpos() can can add that and
figure out the indent :p
hohoho, aren't we ingenious, better yet, you can do a strlen() on the
string youw anna output, then - the curpos, and if its over, grab all
words to the right of that position and output them [so its on one line]
then indent, grab the next section of words( and then the next and then
next
Jordy (jordy@thirdwave.net) 19960622
*/
BUILT_IN_FUNCTION(function_pad, word)
{
int length = 0;
GET_INT_ARG(length, word);
return m_sprintf("%*s", length, word);
}
BUILT_IN_FUNCTION(function_isban, word)
{
char *channel;
char *ban;
ShitList *Ban;
GET_STR_ARG(channel, word);
GET_STR_ARG(ban, word);
if ((Ban = (ShitList *)find_in_list((List **)&shitlist_list, ban, 0)) && check_channel_match(channel, Ban->channels))
RETURN_INT(1);
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isignored, word)
{
char *nick;
GET_STR_ARG(nick, word);
if (check_is_ignored(nick))
RETURN_INT(1);
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_banonchannel, word)
{
ChannelList *chan;
char *channel;
char *ban;
GET_STR_ARG(channel, word);
GET_STR_ARG(ban, word);
if ((chan = lookup_channel(channel, from_server, 0)))
{
if (ban_is_on_channel(ban, chan))
RETURN_INT(1);
}
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isop, word)
{
char *channel;
char *nick;
ChannelList *chan;
NickList *Nick;
GET_STR_ARG(channel, word);
GET_STR_ARG(nick, word);
if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
{
if ((Nick = find_nicklist_in_channellist(nick, chan, 0)) &&
(Nick->userlist && (Nick->userlist->flags & ADD_OPS)))
RETURN_INT(1);
}
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_isvoice, word)
{
char *channel, *nickname;
ChannelList *chan;
NickList *Nick;
char *ret = NULL;
GET_STR_ARG(channel, word);
/* Note: This is the old way, maintained for compatibility */
if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
{
while ((nickname = next_in_comma_list(word, &word)))
{
if (!nickname || !*nickname) break;
Nick = find_nicklist_in_channellist(nickname, chan, 0);
m_s3cat(&ret, comma, Nick? (nick_isvoice(Nick) ? one : zero) : zero);
}
return ret;
} else {
/* args are in proper order, channel is actually the nick */
nickname = channel;
GET_STR_ARG(channel, word);
if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK))) {
Nick = find_nicklist_in_channellist(nickname, chan, 0);
RETURN_STR(Nick ? (nick_isvoice(Nick) ? one : zero) : zero);
}
}
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_randomnick, word)
{
int len1 = 3, len2 = 9;
if (word && *word)
GET_INT_ARG(len1, word);
if (word && *word)
GET_INT_ARG(len2, word);
RETURN_STR(random_str(len1,len2));
}
#ifndef BITCHX_LITE
BUILT_IN_FUNCTION(function_openserver, word)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int port = -1;
char *servern = NULL;
int socket_num = -1;
unsigned short this_sucks;
int notify_mode = 0;
GET_STR_ARG(servern, word);
GET_INT_ARG(port, word);
if (word && *word && toupper(*word) == 'N')
notify_mode = 1;
if (port > 0)
{
this_sucks = (unsigned short)port;
if ((socket_num = connect_by_number(servern, &this_sucks, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
RETURN_INT(-1);
if ((add_socketread(socket_num, port, 0, servern, !notify_mode ? read_clonelist :read_clonenotify, NULL)) < 0)
{
close_socketread(socket_num);
RETURN_INT(-1);
}
}
RETURN_INT(socket_num);
#endif
}
BUILT_IN_FUNCTION(function_closeserver, word)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int socket_num = -1;
GET_INT_ARG(socket_num, word);
if (socket_num > 0 && check_socket(socket_num))
close_socketread(socket_num);
RETURN_INT(socket_num);
#endif
}
BUILT_IN_FUNCTION(function_readserver, word)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int socket_num = -1;
GET_INT_ARG(socket_num, word);
if ((socket_num > 0) && check_socket(socket_num))
{
char buffer[IRCD_BUFFER_SIZE+1];
char *str;
char *s;
*buffer = 0;
str = buffer;
switch(dgets(str, socket_num, 0, IRCD_BUFFER_SIZE, NULL))
{
case 0:
socket_num = 0;
break;
case -1:
close_socketread(socket_num);
socket_num = -1;
break;
default:
if ((buffer[strlen(buffer)-1] == '\r') || (buffer[strlen(buffer)-1] == '\n'))
buffer[strlen(buffer)-1] = 0;
if ((buffer[strlen(buffer)-1] == '\r') || (buffer[strlen(buffer)-1] == '\n'))
buffer[strlen(buffer)-1] = 0;
s = m_sprintf("%d %s", strlen(buffer), buffer);
return s;
}
}
RETURN_INT(socket_num);
#endif
}
BUILT_IN_FUNCTION(function_readchar, word)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int socket_num = -1;
GET_INT_ARG(socket_num, word);
if ((socket_num >= 0) && check_socket(socket_num))
{
char buffer[10];
char *str;
char *s;
*buffer = 0;
*(buffer+1) = 0;
str = buffer;
if ((read(socket_num, str, 1) == 1))
s = m_sprintf("%c", *buffer);
else
s = m_sprintf(empty_string);
return s;
}
RETURN_INT(socket_num);
#endif
}
BUILT_IN_FUNCTION(function_writeserver, word)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
int socket_num = -1;
int len = -1;
GET_INT_ARG(socket_num, word);
if ((socket_num > 0) && check_socket(socket_num))
len = write_sockets(socket_num, word, strlen(word), 1);
RETURN_INT(len);
#endif
}
#endif
char *function_cparse(char *n, char *word)
{
char *format = NULL;
char *blah;
GET_STR_ARG(format, word);
in_cparse++;
blah = convert_output_format(format, word && *word? "%s":NULL, word&&*word?word:NULL);
in_cparse--;
RETURN_STR(blah);
}
BUILT_IN_FUNCTION(function_getreason, word)
{
char *nick = NULL;
GET_STR_ARG(nick, word);
RETURN_STR(get_reason(nick, word));
}
BUILT_IN_FUNCTION(function_chmod, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char *filearg, *after;
int fd = -1;
char *perm_s;
mode_t perm;
GET_STR_ARG(filearg, words);
fd = (int) strtoul(filearg, &after, 10);
GET_STR_ARG(perm_s, words);
perm = (mode_t) strtol(perm_s, &perm_s, 8);
if (after != words && *after == 0)
{
if (file_valid(fd))
#if defined(__EMX__) || defined(__OPENNT)
RETURN_INT(0644);
#else
RETURN_INT(fchmod(fd, perm));
#endif
else
RETURN_EMPTY;
}
else
{
char *expanded;
int retval;
expanded = expand_twiddle(filearg);
retval = chmod(expanded, perm);
new_free(&expanded);
RETURN_INT(retval);
}
#endif
}
BUILT_IN_FUNCTION(function_twiddle, words)
{
if (words && *words)
return expand_twiddle(new_next_arg(words, &words));
RETURN_EMPTY;
}
/*
* Date: Sun, 29 Sep 1996 19:17:25 -0700
* Author: Thomas Morgan <tmorgan@pobox.com>
* Submitted-by: Archon <nuance@twri.tamu.edu>
*
* $uniq (string of text)
* Given a set of words, returns a new set of words with duplicates
* removed.
* EX: $uniq(one two one two) returns "one two"
*/
BUILT_IN_FUNCTION(function_uniq, word)
{
char **list = NULL, *booya = NULL;
int listc, listi;
char *input, *tval;
RETURN_IF_EMPTY(word);
listc = splitw(word, &list);
if (!listc)
RETURN_EMPTY;
booya = m_strdup(list[0]);
for (listi = 1; listi < listc; listi++)
{
input = alloca(strlen(list[listi]) + strlen(booya) + 2);
strcpy(input, list[listi]);
strcat(input, space);
strcat(input, booya);
tval = function_findw(NULL, input);
if (my_atol(tval) == -1)
m_s3cat(&booya, space, list[listi]);
new_free(&tval);
}
new_free((char **)&list);
RETURN_MSTR(booya);
}
BUILT_IN_FUNCTION(function_uhost, word)
{
char *nick;
char *answer = NULL;
int i;
register ChannelList *chan;
NickList *n1;
GET_STR_ARG(nick, word);
for (i = 0; i < server_list_size(); i++)
{
for (chan = get_server_channels(i); chan; chan = chan->next)
{
if ((n1 = find_nicklist_in_channellist(nick, chan, 0)))
{
malloc_strcat(&answer, n1->host);
malloc_strcat(&answer, space);
}
}
}
if (!answer)
RETURN_EMPTY;
return answer;
}
BUILT_IN_FUNCTION(function_numdiff, word)
{
int value1 = 0, value2 = 0;
GET_INT_ARG(value1, word);
GET_INT_ARG(value2, word);
RETURN_INT(value1-value2);
}
BUILT_IN_FUNCTION(function_winvisible, word)
{
RETURN_INT(get_visible_by_refnum(word));
}
#ifndef BITCHX_LITE
BUILT_IN_FUNCTION(function_mircansi, word)
{
extern char *mircansi(char *);
RETURN_STR(mircansi(word));
}
#endif
BUILT_IN_FUNCTION(function_getenv, word)
{
char *p;
char *q;
GET_STR_ARG(q, word);
p = getenv(q);
if (p && *p)
RETURN_STR(p);
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_gethost, word)
{
register ChannelList *chan;
register NickList *nick;
char *arg;
GET_STR_ARG(arg, word);
if (from_server != -1)
{
for (chan = get_server_channels(from_server); chan; chan = chan->next)
{
for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick))
{
if (!my_stricmp(arg, nick->nick))
RETURN_STR(nick->host);
}
}
}
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_getvar, words)
{
char *alias;
int num = 0;
int old_alias_debug = alias_debug;
if ((alias = (char *)get_cmd_alias(upper(words), &num, NULL, NULL)))
{
alias_debug = old_alias_debug;
RETURN_STR(alias);
}
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_aliasctl, input)
{
extern char *aliasctl (char *, char *);
return aliasctl(NULL, input);
}
BUILT_IN_FUNCTION(function_status, word)
{
int window_refnum;
int status_line;
GET_INT_ARG(window_refnum, word);
GET_INT_ARG(status_line, word);
RETURN_STR(get_status_by_refnum(window_refnum, status_line));
}
extern char *stat_convert_format (Window *, char *);
BUILT_IN_FUNCTION(function_statsparse, word)
{
return stat_convert_format(current_window, word);
}
BUILT_IN_FUNCTION(function_absstrlen, word)
{
char *tmp;
if (!word || !*word)
RETURN_INT(0);
tmp = stripansicodes(word);
RETURN_INT(strlen(tmp));
}
BUILT_IN_FUNCTION(function_findw, input)
{
char *word, *this_word;
int word_cnt = 0;
GET_STR_ARG(word, input);
while (input && *input)
{
GET_STR_ARG(this_word, input);
if (!my_stricmp(this_word, word))
RETURN_INT(word_cnt);
word_cnt++;
}
RETURN_INT(-1);
}
BUILT_IN_FUNCTION(function_countansi, input)
{
RETURN_INT(output_with_count(input, 0, 0));
}
BUILT_IN_FUNCTION(function_iplong, word)
{
char *blah;
struct in_addr addr = {0};
GET_STR_ARG(blah, word);
if (inet_aton(blah, &addr))
return m_sprintf("%lu", (unsigned long)htonl(addr.s_addr));
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_longip, word)
{
char *blah = NULL;
struct in_addr addr = {0};
GET_STR_ARG(blah, word);
addr.s_addr = atol(blah);
RETURN_STR(inet_ntoa(addr));
}
#include <stdlib.h>
BUILT_IN_FUNCTION(function_rword, word)
{
int num = 0;
long rn;
char *p;
#ifndef RAND_MAX
#define RAND_MAX 2147483647
#endif
RETURN_IF_EMPTY(word);
num = word_count(word);
rn = (int)(((float)num)*rand()/(RAND_MAX+1.0));
p = extract(word, rn, rn);
return p;
}
BUILT_IN_FUNCTION(function_winlen, word)
{
int refnum;
int len = 0;
Window *win = current_window;
if (word && *word)
{
refnum = my_atol(word);
win = get_window_by_refnum(refnum);
if (!win)
RETURN_INT(-1);
}
len = win->display_size;
RETURN_INT(len);
}
BUILT_IN_FUNCTION(function_channel, word)
{
char *chan;
ChannelList *channel = NULL; /* XXX */
NickList *tmp = NULL;
char *nicks = NULL;
int sort_order = NICKSORT_NORMAL;
chan = next_arg(word, &word);
if (!chan)
chan = get_current_channel_by_refnum(0);
RETURN_IF_EMPTY(chan);
if ((channel = lookup_channel(chan, from_server, 0)))
{
NickList *list = NULL;
if (word && *word)
GET_INT_ARG(sort_order, word);
list = sorted_nicklist(channel, sort_order);
for (tmp = list; tmp; tmp = tmp->next)
{
if (nick_isircop(tmp))
malloc_strcat(&nicks, "*");
if (tmp->userlist)
malloc_strcat(&nicks, "&");
else if (tmp->shitlist)
malloc_strcat(&nicks, "!");
if (nick_isop(tmp))
m_3cat(&nicks, "@", tmp->nick);
else if (nick_isvoice(tmp))
m_3cat(&nicks, "+", tmp->nick);
else
m_3cat(&nicks, ".", tmp->nick);
malloc_strcat(&nicks, space);
}
clear_sorted_nicklist(&list);
}
return (nicks ? nicks : m_strdup(empty_string));
}
/*
* Given a channel, tells you what window its bound to.
* Given a window, tells you what channel its bound to.
*/
BUILT_IN_FUNCTION(function_winbound, input)
{
Window *foo;
char *stuff;
stuff = new_next_arg(input, &input);
if (my_atol(stuff) && (foo = get_window_by_refnum((unsigned)my_atol(stuff))))
RETURN_STR(get_bound_channel(foo));
else if ((foo = get_window_by_name(stuff)))
RETURN_STR(get_bound_channel(foo));
else if ((foo = get_window_bound_channel(stuff)))
RETURN_STR(get_refnum_by_window(foo));
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_ftime, words)
{
#ifdef PUBLIC_ACCESS
RETURN_INT(0);
#else
char FileBuf[BIG_BUFFER_SIZE+1];
char *filename, *fullname;
struct stat s;
*FileBuf = 0;
if ((filename = new_next_arg(words, &words)))
{
if (*filename == '/')
strlcpy(FileBuf, filename, BIG_BUFFER_SIZE);
else if (*filename == '~')
{
if (!(fullname = expand_twiddle(filename)))
RETURN_EMPTY;
strmcpy(FileBuf, fullname, BIG_BUFFER_SIZE);
new_free(&fullname);
}
#if defined(__EMX__) || defined(WINNT)
else if (is_dos(filename))
strmcpy(FileBuf, filename, BIG_BUFFER_SIZE);
#endif
else
{
getcwd(FileBuf, BIG_BUFFER_SIZE);
strmcat(FileBuf, "/", BIG_BUFFER_SIZE);
strmcat(FileBuf, filename, BIG_BUFFER_SIZE);
}
#if defined(__EMX__) || defined(WINNT)
convert_dos(FileBuf);
#endif
if (stat(FileBuf, &s) == -1)
RETURN_EMPTY;
else
RETURN_INT(s.st_mtime);
}
RETURN_EMPTY;
#endif
}
BUILT_IN_FUNCTION(function_irclib, input)
{
RETURN_STR(irc_lib);
}
BUILT_IN_FUNCTION(function_country, input)
{
extern char *country(char *);
RETURN_STR(country(input));
}
BUILT_IN_FUNCTION(function_servernick, input)
{
char *servdesc;
int refnum;
if(*input)
{
GET_STR_ARG(servdesc, input);
if ((refnum = parse_server_index(servdesc)) == -1)
if ((refnum = find_in_server_list(servdesc, 0)) == -1)
RETURN_EMPTY;
} else if(from_server != -1)
refnum = from_server;
else
RETURN_EMPTY;
RETURN_STR(get_server_nickname(refnum));
}
BUILT_IN_FUNCTION(function_fparse, input)
{
char *format;
char *f = NULL;
Alias *a = NULL;
int owd = window_display;
GET_STR_ARG(f, input);
if (!f || !*f)
RETURN_EMPTY;
if ((format = make_fstring_var(f)))
{
f = convert_output_format(format, "%s", input?input:empty_string);
new_free(&format);
RETURN_STR(f);
}
window_display = 0;
if ((a = find_var_alias(f)) && a->stuff && input && *input)
f = convert_output_format(a->stuff, "%s", input?input:empty_string);
else if (input && *input)
add_var_alias(f, input);
else
delete_var_alias(f, 0);
window_display = owd;
RETURN_STR(f);
}
BUILT_IN_FUNCTION(function_isconnected, input)
{
int server = 0;
if (!input || !*input)
server = from_server;
else
GET_INT_ARG(server, input);
RETURN_INT(is_server_connected(server));
}
BUILT_IN_FUNCTION(function_bmatch, input)
{
char *to = NULL;
char *p, *q, *m;
GET_STR_ARG(to, input);
p = q = m_strdup(input);
while((m = next_arg(p, &p)))
{
if (wild_match(m, to))
{
char *ret = m_strdup(m);
new_free(&q);
return ret;
}
}
new_free(&q);
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_currchans, input)
{
int server = -1;
Window *blah = NULL;
char *retval = NULL;
if (input && *input)
GET_INT_ARG(server, input)
else
server = -2;
if (server == -1)
server = from_server;
while (traverse_all_windows(&blah))
{
if (server != -2 && blah->server != server)
continue;
if (!blah->current_channel)
continue;
m_s3cat(&retval, space, "\"");
malloc_strcat(&retval, ltoa(blah->server));
malloc_strcat(&retval, space);
malloc_strcat(&retval, blah->current_channel);
malloc_strcat(&retval, "\"");
}
RETURN_MSTR(retval);
}
/*
* Returns 1 if the specified function name is a built in function,
* Returns 0 if not.
*/
BUILT_IN_FUNCTION(function_fnexist, input)
{
char *fname;
GET_STR_ARG(fname, input);
RETURN_INT(func_exist(fname));
}
BUILT_IN_FUNCTION(function_cexist, input)
{
char *fname;
GET_STR_ARG(fname, input);
RETURN_INT(command_exist(fname));
}
#if defined(HAVE_REGEX_H) && !defined(__EMX__) && !defined(WINNT)
/*
* These are used as an interface to regex support. Here's the plan:
*
* $regcomp(<pattern>)
* will return an $encode()d string that is suitable for
* assigning to a variable. The return value of this
* function must at some point be passed to $regfree()!
*
* $regexec(<compiled> <string>)
* Will return "0" or "1" depending on whether or not the given string
* was matched by the previously compiled string. The value
* for <compiled> must be a value previously returned by $regex().
* Failure to do this will result in undefined chaos.
*
* $regerror(<compiled>)
* Will return the error string for why the previous $regmatch() or
* $regex() call failed.
*
* $regfree(<compiled>)
* Will free off any of the data that might be contained in <compiled>
* You MUST call $regfree() on any value that was previously
* returned by $regex(), or you will leak memory. This is not
* my problem (tm). It returns the FALSE value.
*/
static int last_error = 0; /* XXX */
BUILT_IN_FUNCTION(function_regcomp, input)
{
regex_t preg = {0};
if (input && *input)
{
last_error = regcomp(&preg, input, REG_EXTENDED | REG_ICASE | REG_NOSUB);
return encode((char *)&preg, sizeof(regex_t));
}
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_regexec, input)
{
char *unsaved;
regex_t *preg = NULL;
int retval = -1;
GET_STR_ARG(unsaved, input);
if (input && *input)
{
char *p;
if ((p = decode(unsaved)) && *p)
{
preg = (regex_t *)p;
retval = regexec(preg, input, 0, NULL, 0);
new_free((char **)&preg);
}
}
RETURN_INT(retval); /* DONT PASS FUNC CALL TO RETURN_INT */
}
BUILT_IN_FUNCTION(function_regerror, input)
{
char *unsaved, *p;
regex_t *preg = NULL;
char error_buf[1024];
int errcode;
GET_INT_ARG(errcode, input);
GET_STR_ARG(unsaved, input);
*error_buf = 0;
if ((p = decode(unsaved)) && *p)
{
preg = (regex_t *)p;
if (errcode == -1)
errcode = last_error;
regerror(errcode, preg, error_buf, 1023);
new_free((char **)&preg);
}
RETURN_STR(error_buf);
}
BUILT_IN_FUNCTION(function_regfree, input)
{
char *unsaved, *p;
regex_t *preg;
GET_STR_ARG(unsaved, input);
if ((p = decode(unsaved)) && *p)
{
preg = (regex_t *)p;
regfree(preg);
new_free((char **)&preg);
}
RETURN_EMPTY;
}
#else
BUILT_IN_FUNCTION(function_regexec, input) { RETURN_EMPTY; }
BUILT_IN_FUNCTION(function_regcomp, input) { RETURN_EMPTY; }
BUILT_IN_FUNCTION(function_regerror, input) { RETURN_STR("no regex support"); }
BUILT_IN_FUNCTION(function_regfree, input) { RETURN_EMPTY; }
#endif
/*
* Usage: $igmask(pattern)
* Returns: All the ignore patterns that are matched by the pattern
* Example: $igmask(*) returns your entire ignore list
* Based on work contributed by pavlov
*/
BUILT_IN_FUNCTION(function_igmask, input)
{
return get_ignores_by_pattern(input, 0); /* DONT MALLOC THIS */
}
/*
* Usage: $rigmask(pattern)
* Returns: All the ignore patterns that would trigger on the given input
* Example: $igmask(wc!bhauber@frenzy.com) would return a pattern like
* *!*@*frenzy.com or like *!bhauber@*
*/
BUILT_IN_FUNCTION(function_rigmask, input)
{
return get_ignores_by_pattern(input, 1); /* DONT MALLOC THIS */
}
BUILT_IN_FUNCTION(function_count, input)
{
char *str, *str2;
int count = 0;
GET_STR_ARG(str, input);
str2 = input;
for (;;)
{
if ((str2 = stristr(str2, str)))
count++, str2++;
else
break;
}
RETURN_INT(count);
}
/*
* Usage: $leftpc(COUNT TEXT)
* Return the *longest* initial part of TEXT that includes COUNT printable
* characters.
*/
BUILT_IN_FUNCTION(function_leftpc, word)
{
u_char **prepared = NULL;
int lines = 1;
int count;
GET_INT_ARG(count, word);
if (count <= 0 || !*word)
RETURN_EMPTY;
prepared = prepare_display(word, count, &lines, PREPARE_NOWRAP);
RETURN_STR((char *)prepared[0]);
}
/*
* $uname()
* Returns system information. Expandoes %a, %s, %r, %v, %m, and %n
* correspond to uname(1)'s -asrvmn switches. %% expands to a literal
* '%'. If no arguments are given, the function returns %s and %r (the
* same information given in the client's ctcp version reply).
*
* Contributed by Matt Carothers (CrackBaby) on Dec 20, 1997
*/
BUILT_IN_FUNCTION(function_uname, input)
{
#ifndef HAVE_UNAME
RETURN_STR("unknown");
#else
struct utsname un;
char tmp[BIG_BUFFER_SIZE+1];
char *ptr = tmp;
size_t size = BIG_BUFFER_SIZE;
int i;
int len;
if (uname(&un) == -1)
RETURN_STR("unknown");
if (!*input)
input = "%s %r";
*tmp = 0;
for (i = 0, len = strlen(input); i < len; i++)
{
if (ptr - tmp >= size)
break;
if (input[i] == '%')
{
switch (input[++i])
{
case 'm': strlcpy(ptr, un.machine, size);
break;
case 'n': strlcpy(ptr, un.nodename, size);
break;
case 'r': strlcpy(ptr, un.release, size);
break;
case 's': strlcpy(ptr, un.sysname, size);
break;
case 'v': strlcpy(ptr, un.version, size);
break;
case 'a':
snprintf(ptr, size, "%s %s %s %s %s",
un.sysname, un.nodename,
un.release, un.version,
un.machine);
break;
case '%': strlcpy(ptr, "%", size);
}
ptr += strlen(ptr);
}
else
*ptr++ = input[i];
}
*ptr = 0;
RETURN_STR(tmp);
#endif
}
BUILT_IN_FUNCTION(function_querywin, args)
{
Window *w = NULL;
while (traverse_all_windows(&w))
if (w->query_nick && !my_stricmp(w->query_nick, args))
RETURN_INT(w->refnum);
RETURN_INT(-1);
}
BUILT_IN_FUNCTION(function_winrefs, args)
{
Window *w = NULL;
char *retval = NULL;
while (traverse_all_windows(&w))
m_s3cat(&retval, space, ltoa(w->refnum));
return retval; /* DONT MALLOC THIS! */
}
#define DOT (*host ? dot : empty_string)
BUILT_IN_FUNCTION(function_uhc, input)
{
char *nick, *user, *host, *domain;
int ip;
if (!input || !*input)
RETURN_EMPTY;
if (figure_out_address(input, &nick, &user, &host, &domain, &ip))
RETURN_STR(input);
else if (ip == 0)
return m_sprintf("%s!%s@%s%s%s", nick, user, host, DOT, domain);
else
return m_sprintf("%s!%s@%s%s%s", nick, user, domain, DOT, host);
}
/*
* Opposite of $uhc(). Breaks down a complete nick!user@host
* into smaller components, based upon absolute wildcards.
* Eg, *!user@host becomes user@host. And *!*@*.host becomes *.host
* Based on the contribution and further changes by Peter V. Evans
* (arc@anet-chi.com)
*/
BUILT_IN_FUNCTION(function_deuhc, input)
{
char *buf;
buf = LOCAL_COPY(input);
if (!strchr(buf, '!') || !strchr(buf, '@'))
RETURN_EMPTY;
if (!strncmp(buf, "*!", 2))
{
buf += 2;
if (!strncmp(buf, "*@", 2))
buf += 2;
}
RETURN_STR(buf);
}
/*
* $mask(type address) OR
* $mask(address type)
* Returns address with a mask specified by type.
*
* $mask(1 nick!khaled@mardam.demon.co.uk) returns *!*khaled@mardam.demon.co.uk
* $mask(2 nick!khaled@mardam.demon.co.uk) returns *!*@mardam.demon.co.uk
*
* The available types are:
*
* 0: *!user@host.domain
* 1: *!*user@host.domain
* 2: *!*@host.domain
* 3: *!*user@*.domain
* 4: *!*@*.domain
* 5: nick!user@host.domain
* 6: nick!*user@host.domain
* 7: nick!*@host.domain
* 8: nick!*user@*.domain
* 9: nick!*@*.domain
* 10: *!*@<number-masked-host>.domain (matt)
* 11: *!*user@<nember-masked-host>.domain (matt)
* 12: nick!*@<number-masked-host>.domain (matt)
* 13: nick!*user@<number-masked-host>.domain (matt)
*/
BUILT_IN_FUNCTION(function_mask, args)
{
char * nuh;
char * nick = NULL;
char * user = NULL;
char * host = NULL;
char * domain = NULL;
int which;
char stuff[BIG_BUFFER_SIZE + 1];
int ip;
char *first_arg;
char *ptr;
first_arg = new_next_arg(args, &args);
if (is_number(first_arg))
{
which = my_atol(first_arg);
nuh = args;
}
else
{
nuh = first_arg;
GET_INT_ARG(which, args);
}
if (figure_out_address(nuh, &nick, &user, &host, &domain, &ip))
RETURN_EMPTY;
/*
* Deal with ~jnelson@acronet.net for exapmle, and all sorts
* of other av2.9 breakage.
*/
if (strchr("~^-+=", *user))
user++;
/* Make sure 'user' isnt too long for a ban... */
if (strlen(user) > 7)
{
user[7] = '*';
user[8] = 0;
}
#define USER (user == star ? empty_string : user)
#define MASK1(x, y) snprintf(stuff, BIG_BUFFER_SIZE, x, y); break;
#define MASK2(x, y, z) snprintf(stuff, BIG_BUFFER_SIZE, x, y, z); break;
#define MASK3(x, y, z, a) snprintf(stuff, BIG_BUFFER_SIZE, x, y, z, a); break;
#define MASK4(x, y, z, a, b) snprintf(stuff, BIG_BUFFER_SIZE, x, y, z, a, b); break;
#define MASK5(x, y, z, a, b, c) snprintf(stuff, BIG_BUFFER_SIZE, x, y, z, a, b, c); break;
if (ip == 0)
switch (which)
{
case 0: MASK4("*!%s@%s%s%s", user, host, DOT, domain)
case 1: MASK4("*!*%s@%s%s%s", USER, host, DOT, domain)
case 2: MASK3("*!*@%s%s%s", host, DOT, domain)
case 3: MASK3("*!*%s@*%s%s", USER, DOT, domain)
case 4: MASK2("*!*@*%s%s", DOT, domain)
case 5: MASK5("%s!%s@%s%s%s", nick, user, host, DOT, domain)
case 6: MASK5("%s!*%s@%s%s%s", nick, USER, host, DOT, domain)
case 7: MASK4("%s!*@%s%s%s", nick, host, DOT, domain)
case 8: MASK4("%s!*%s@*%s%s", nick, USER, DOT, domain)
case 9: MASK3("%s!*@*%s%s", nick, DOT, domain)
case 10: mask_digits(&host);
MASK3("*!*@%s%s%s", host, DOT, domain)
case 11: mask_digits(&host);
MASK4("*!*%s@%s%s%s", USER, host, DOT, domain)
case 12: mask_digits(&host);
MASK4("%s!*@%s%s%s", nick, host, DOT, domain)
case 13: mask_digits(&host);
MASK5("%s!*%s@%s%s%s", nick, USER, host, DOT, domain)
}
else
switch (which)
{
case 0: MASK3("*!%s@%s.%s", user, domain, host)
case 1: MASK3("*!*%s@%s.%s", USER, domain, host)
case 2: MASK2("*!*@%s.%s", domain, host)
case 3: MASK2("*!*%s@%s.*", USER, domain)
case 4: MASK1("*!*@%s.*", domain)
case 5: MASK4("%s!%s@%s.%s", nick, user, domain, host)
case 6: MASK4("%s!*%s@%s.%s", nick, USER, domain, host)
case 7: MASK3("%s!*@%s.%s", nick, domain, host)
case 8: MASK3("%s!*%s@%s.*", nick, USER, domain)
case 9: MASK2("%s!*@%s.*", nick, domain)
case 10: MASK1("*!*@%s.*", domain)
case 11: MASK2("*!*%s@%s.*", USER, domain)
case 12: MASK2("%s!*@%s.*", nick, domain)
case 13: MASK3("%s!*%s@%s.*", nick, USER, domain)
}
/* Clean up any non-printable chars */
for (ptr = stuff; *ptr; ptr++)
if (!isgraph((unsigned char)*ptr))
*ptr = '?';
RETURN_STR(stuff);
}
/*
* $remws(word word word / word word word)
* Returns the right hand side unchanged, except that any word on the right
* hand side that is also found on the left hand side will be removed.
* Space is *not* retained. So there.
*/
BUILT_IN_FUNCTION(function_remws, word)
{
char *left = NULL,
**lhs = NULL,
*right = NULL,
**rhs = NULL,
*booya = NULL;
int leftc,
lefti,
rightc,
righti;
int found = 0;
left = word;
if (!(right = strchr(word,'/')))
RETURN_EMPTY;
*right++ = 0;
leftc = splitw(left, &lhs);
rightc = splitw(right, &rhs);
for (righti = 0; righti < rightc; righti++)
{
found = 0;
for (lefti = 0; lefti < leftc; lefti++)
{
if (rhs[righti] && lhs[lefti] &&
!my_stricmp(lhs[lefti], rhs[righti]))
{
found = 1;
break;
}
}
if (!found)
m_s3cat(&booya, space, rhs[righti]);
rhs[righti] = NULL;
}
new_free((char **)&lhs);
new_free((char **)&rhs);
if (!booya)
RETURN_EMPTY;
return (booya); /* DONT USE RETURN_STR HERE! */
}
BUILT_IN_FUNCTION(function_stripansicodes, input)
{
#if 0
return strip_ansi(input);
#else
RETURN_STR(stripansicodes(input));
#endif
}
BUILT_IN_FUNCTION(function_igtype, input)
{
RETURN_STR(get_ignore_types_by_pattern(input));
}
BUILT_IN_FUNCTION(function_rigtype, input)
{
return get_ignore_patterns_by_type(input); /* DONT MALLOC! */
}
BUILT_IN_FUNCTION(function_getuid, input)
{
RETURN_INT(getuid());
}
BUILT_IN_FUNCTION(function_getgid, input)
{
RETURN_INT(getgid());
}
BUILT_IN_FUNCTION(function_getlogin, input)
{
#ifdef HAVE_GETLOGIN
RETURN_STR(getlogin());
#else
RETURN_STR(getenv("LOGNAME"));
#endif
}
BUILT_IN_FUNCTION(function_getpgrp, input)
{
RETURN_INT(getpgrp());
}
BUILT_IN_FUNCTION(function_iscurchan, input)
{
char *chan;
Window *w = NULL;
GET_STR_ARG(chan, input);
while (traverse_all_windows(&w))
{
/*
* Check to see if the channel specified is the current
* channel on *any* window for the current server.
*/
if (w->current_channel &&
!my_stricmp(chan, w->current_channel) &&
w->server == from_server)
RETURN_INT(1);
}
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_getcset, input)
{
char *var = NULL;
char *channel = NULL;
ChannelList *chan = NULL;
GET_STR_ARG(var, input);
if (input && *input)
channel = next_arg(input, &input);
else
channel = get_current_channel_by_refnum(0);
chan = lookup_channel(channel, from_server, 0);
if (!channel || !chan)
RETURN_EMPTY;
if (input && *input)
return get_cset(var, chan, input);
else
return get_cset(var, chan, NULL);
}
BUILT_IN_FUNCTION(function_getfsets, input)
{
extern char *get_fset(char *);
char *s = NULL;
char *ret = NULL;
if (!input || !*input)
return get_fset(NULL);
while ((s = next_arg(input, &input)))
{
char *r;
r = get_fset(s);
m_s3cat(&ret, space, r);
new_free(&r);
}
return ret;
}
BUILT_IN_FUNCTION(function_getsets, input)
{
extern char *get_set(char *);
char *s = NULL;
char *ret = NULL;
if (!input || !*input)
return get_set(NULL);
while ((s = next_arg(input, &input)))
{
char *r;
r = get_set(s);
m_s3cat(&ret, space, r);
new_free(&r);
}
return ret;
}
/*
* $isnumber(number base)
* returns the empty value if nothing is passed to it
* returns 0 if the value passed is not a number
* returns 1 if the value passed is a number.
*
* The "base" number is optional and should be prefixed by the
* character 'b'. ala, $isnumber(0x0F b16) for hexadecimal.
* the special base zero (b0) means to 'auto-detect'. Base must
* be between 0 and 36, inclusive. If not, it defaults to 0.
*/
BUILT_IN_FUNCTION(function_isnumber, input)
{
int base = 0;
char *endptr;
char *barg;
char *number = NULL;
/*
* See if the first arg is the base
*/
barg = new_next_arg(input, &input);
/*
* If it is, the number is the 2nd arg
*/
if (barg && *barg == 'b' && is_number(barg + 1))
{
GET_STR_ARG(number, input);
}
/*
* Otherwise, the first arg is the number,
* the 2nd arg probably is the base
*/
else
{
number = barg;
barg = new_next_arg(input, &input);
}
/*
* If the user specified a base, parse it.
* Must be between 0 and 36.
*/
if (barg && *barg == 'b')
{
base = my_atol(barg + 1);
if (base < 0 || base > 36)
base = 0;
}
/*
* Must have specified a number, though.
*/
RETURN_IF_EMPTY(number);
strtol(number, &endptr, base);
if (*endptr == '.')
strtol(endptr + 1, &endptr, base);
if (*endptr)
RETURN_INT(0);
else
RETURN_INT(1);
}
/*
* $rest(index string)
* Returns 'string' starting at the 'index'th character
* Just like $restw() does for words.
*/
BUILT_IN_FUNCTION(function_rest, input)
{
int start = 1;
if (my_atol(input))
GET_INT_ARG(start, input);
if (start <= 0)
RETURN_STR(input);
if (start >= strlen(input))
RETURN_EMPTY;
RETURN_STR(input + start);
}
/*
* take a servername and return it's refnum or -1
*/
BUILT_IN_FUNCTION(function_servref, input)
{
char *servname = NULL;
int i;
char *s;
if (!input || !*input)
RETURN_INT(from_server);
GET_STR_ARG(servname, input);
for (i = 0; i < server_list_size(); i++)
{
if ((s = get_server_itsname(i)) && !my_stricmp(s, servname))
RETURN_INT(i);
else if (!my_stricmp(s, get_server_name(i)))
RETURN_INT(i);
}
RETURN_INT(-1);
}
/*
* sd_(sd@pm3-25.netgate.net) needed the following function to return a
* set of flags from the userlist. we pass in a user@host and a channel
* and that user's flags are returned.
*/
BUILT_IN_FUNCTION(function_getflags, input)
{
#ifdef WANT_USERLIST
char *uh = NULL, *channel = NULL;
register UserList *tmp;
void *location = NULL;
int size = -1;
GET_STR_ARG(uh, input);
GET_STR_ARG(channel, input);
if ((tmp = find_bestmatch("*", uh, channel, NULL)))
RETURN_STR(convert_flags_to_str(tmp->flags));
for (tmp = next_userlist(NULL, &size, &location); tmp; tmp = next_userlist(tmp, &size, &location))
{
register UserList *blah = NULL;
if (!wild_match(uh, tmp->host) && !wild_match(tmp->host, uh))
continue;
uh = tmp->host;
if ((blah = find_bestmatch("*", uh, channel, NULL)))
RETURN_STR(convert_flags_to_str(blah->flags));
}
#endif
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_numlines, input)
{
int count = 0;
unsigned char **lines = NULL;
char *s = NULL;
if (input && *input)
{
int cols;
s = LOCAL_COPY(input);
if (current_window->screen)
cols = current_window->screen->co;
else
cols = current_window->columns;
for (lines = split_up_line(s, cols + 1); *lines; lines++)
count++;
}
RETURN_INT(count);
}
BUILT_IN_FUNCTION(function_topic, input)
{
char *ch = NULL;
ChannelList *chan;
if (input && *input)
ch = next_arg(input, &input);
if (!ch || !*ch)
ch = get_current_channel_by_refnum(0);
if (ch && *ch && (chan = lookup_channel(ch, from_server, 0)))
RETURN_STR(chan->topic);
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_stripcrap, input)
{
char *how;
int mangle;
char *output;
GET_STR_ARG(how, input);
mangle = parse_mangle(how, 0, NULL);
output = new_malloc(strlen(input) * 2 + 1);
strcpy(output, input);
mangle_line(output, mangle, strlen(input) * 2);
return output; /* DONT MALLOC THIS */
}
#if 0
BUILT_IN_FUNCTION(function_parse_and_return, str)
{
unsigned char buffer[3*BIG_BUFFER_SIZE+1];
register unsigned char *s;
char *copy = NULL;
char *tmpc = NULL;
int arg_flags;
if (!str)
return m_strdup(empty_string);
memset(buffer, 0, BIG_BUFFER_SIZE);
copy = tmpc = str;
s = buffer;
while (*tmpc)
{
if (*tmpc == '$')
{
char *new_str = NULL;
tmpc++;
in_cparse++;
tmpc = alias_special_char(&new_str, tmpc, copy, NULL, &arg_flags);
in_cparse--;
if (new_str)
strcat(s, new_str);
new_free(&new_str);
if (!tmpc) break;
continue;
} else
*s = *tmpc;
tmpc++; s++;
}
*s = 0;
return m_strdup(buffer);
}
#endif
BUILT_IN_FUNCTION(function_long_to_comma, word)
{
long l = 0;
if (word && *word)
l = strtol(word, NULL, 10);
RETURN_STR(longcomma(l));
}
BUILT_IN_FUNCTION(function_dccitem, word)
{
int dcc_item;
SocketList *s = NULL;
DCC_int *n1 = NULL;
int i = 0, found = 0;
char *str;
if (!(str = next_arg(word, &word)))
RETURN_EMPTY;
if (*str == '#' && *(str+1))
{
dcc_item = my_atol(str+1);
if (check_dcc_socket(dcc_item) && (s = get_socket(dcc_item)))
{
found++;
n1 = (DCC_int *) s->info;
i = dcc_item;
}
}
else if (isdigit((unsigned char)*str))
{
dcc_item = my_atol(str);
for (i = 0; i < get_max_fd()+1; i++)
{
if (check_dcc_socket(i) && (s = get_socket(i)))
{
n1 = (DCC_int *) s->info;
if (n1 && (n1->dccnum == dcc_item))
{
found++;
break;
}
}
}
}
if (!found || !s || !n1)
RETURN_EMPTY;
return get_dcc_info(s, n1, i);
}
BUILT_IN_FUNCTION(function_winitem, word)
{
int win_item = -1;
char *str;
Window *window = NULL;
char none[] = "<none>";
char flags[10];
int j = 0;
#ifdef GUI
char fontinfo[100];
int winx, winy, wincx, wincy;
#endif
if ((str = next_arg(word, &word)))
{
if (*str == '%' && *(str+1))
{
win_item = my_atol(str+1);
window = get_window_by_refnum(win_item);
}
else if (isdigit((unsigned char)*str))
{
if (!(win_item = my_atol(str)))
window = get_window_by_refnum(win_item);
else
{
while (traverse_all_windows(&window) && ++j != win_item) ;
if (win_item > j)
RETURN_EMPTY;
}
}
}
else
{
win_item = 0;
window = get_window_by_refnum(win_item);
}
if (!window || win_item == -1)
RETURN_EMPTY;
memset(flags, 0, sizeof(flags));
if (window->log)
strcat(flags, "L");
#ifdef GUI
fontinfo[0] = 0;
gui_query_window_info(window->screen, fontinfo, &winx, &winy, &wincx, &wincy);
return m_sprintf("%u %s %d %s %s %s %s %d %d %d %s %d %d %d %d %s \"%s\" \"%s\" %s %s %s",
#else
return m_sprintf("%u %s %d %s %s %s %s %d %d %d %s %s %s %s %s %s \"%s\" \"%s\" %s %s %s",
#endif
window->refnum,
window->name?window->name:none,
window->server,
window->current_channel?window->current_channel:none,
window->query_nick?window->query_nick:none,
window->waiting_channel?window->waiting_channel:none,
(window->screen && window->screen->menu)?window->screen->menu:none, /* oirc menu name */
window->visible,
window->screen ? window->screen->co : 0,
window->screen ? window->screen->li : 0,
#ifdef GUI
fontinfo,
winx,
winy,
wincx,
wincy,
#else
none, none, none, none, none, /* font windowx windowy window-width window-height */
#endif
window->logfile?window->logfile:none, flags,
window->nicks?"n":empty_string,
none, none,
bits_to_lastlog_level(window->window_level));
}
BUILT_IN_FUNCTION(function_ajoinitem, input)
{
extern AJoinList *ajoin_list;
AJoinList *new = NULL;
int ajl_num, count = 0;
char *ret = NULL;
GET_INT_ARG(ajl_num, input);
for (new = ajoin_list; new; new = new->next)
{
if ((ajl_num == -1) || (count == ajl_num))
{
m_s3cat(&ret, ",", new->name);
m_s3cat(&ret, space, new->key ? new->key : "<none>");
}
if ((count == ajl_num))
break;
count++;
}
if (!ret)
RETURN_EMPTY;
return ret;
}
BUILT_IN_FUNCTION(function_servgroup, input)
{
int snum;
char *s;
GET_INT_ARG(snum, input);
s = get_server_network(snum);
RETURN_STR(s ? s : empty_string);
}
#ifdef GUI
BUILT_IN_FUNCTION(function_mciapi, input)
{
char *firstarg;
static char szReturnString[BIG_BUFFER_SIZE] = "";
if (input && *input)
{
GET_STR_ARG(firstarg, input)
if (!my_stricmp(firstarg, "raw"))
RETURN_INT(gui_send_mci_string(input, szReturnString));
else if (!my_stricmp(firstarg, "result"))
RETURN_STR(szReturnString);
else if (!my_stricmp(firstarg, "playfile"))
{
char *fullfile;
if (input && *input)
{
fullfile = expand_twiddle(input);
gui_play_sound(fullfile);
new_free(&fullfile);
}
RETURN_STR(empty_string);
}
else if (!my_stricmp(firstarg, "errstring"))
{
int errnum;
char szErrorString[BIG_BUFFER_SIZE];
*szErrorString = 0;
GET_INT_ARG(errnum, input);
gui_get_sound_error(errnum, szErrorString);
RETURN_STR(szErrorString);
}
}
RETURN_INT(1);
}
BUILT_IN_FUNCTION(function_menucontrol, input)
{
char *menuname, *what, *param;
int refnum = -1;
GET_STR_ARG(menuname, input);
GET_INT_ARG(refnum, input);
GET_STR_ARG(what, input);
GET_STR_ARG(param, input);
if (menuname && *menuname && what && *what && param && *param)
{
if (refnum > -1 && gui_setmenuitem(menuname, refnum, what, param))
RETURN_STR("1");
}
RETURN_STR(empty_string);
}
BUILT_IN_FUNCTION(function_lastclickline, input)
{
extern char *lastclicklinedata;
extern int lastclickcol;
int info=0,i,e,c,d;
char retinfo[BIG_BUFFER_SIZE],
newclicklinedata[BIG_BUFFER_SIZE + 1];
*retinfo = 0;
if (input && *input)
GET_INT_ARG(info, input)
else
info=0;
if (!lastclicklinedata)
RETURN_EMPTY;
/* Remove color codes if necessary */
strncpy(newclicklinedata, stripansicodes(lastclicklinedata), BIG_BUFFER_SIZE);
switch(info)
{
case 0:
RETURN_STR(newclicklinedata);
break;
case 1:
/* Color codes */
RETURN_STR(lastclicklinedata);
break;
case 2:
/* Color codes (replaced with ^O)....same as case 1 */
RETURN_STR(lastclicklinedata);
break;
case 3:
if (newclicklinedata[lastclickcol] != ' ')
{
i = lastclickcol;
while (newclicklinedata[i] != ' ' && i > -1)
i--;
i++;
e = lastclickcol;
while (newclicklinedata[e] != ' ' && e < strlen(newclicklinedata))
e++;
if (newclicklinedata[i]=='[' || newclicklinedata[i]=='(' || newclicklinedata[i]=='<')
i++;
if (newclicklinedata[e-1]==']' || newclicklinedata[e-1]==')' || newclicklinedata[e-1]=='>')
e--;
for (c = i; c < e; c++)
retinfo[(c-i)] = newclicklinedata[c];
c++;
retinfo[c-i] = 0;
RETURN_STR(retinfo);
}
break;
case 4:
if (newclicklinedata[lastclickcol] != ' ')
{
i = lastclickcol;
while (newclicklinedata[i] != ' ' && i > -1)
i--;
i++;
e = lastclickcol;
while (newclicklinedata[e] != ' ' && e < strlen(newclicklinedata))
e++;
if (newclicklinedata[i] == '[' || newclicklinedata[i]=='(' || newclicklinedata[i]=='<')
i++;
if (newclicklinedata[e-1] == ']' || newclicklinedata[e-1]==')' || newclicklinedata[e-1]=='>')
e--;
again:
if (newclicklinedata[i] == '#' || newclicklinedata[i]=='@' || newclicklinedata[i]=='+' || newclicklinedata[i]=='%' || newclicklinedata[i]=='*')
{
i++;
goto again;
}
d = i;
while (newclicklinedata[d]!='@' && d < e)
d++;
for (c = i; c < d; c++)
retinfo[(c-i)] = newclicklinedata[c];
retinfo[(c-i)] = 0;
RETURN_STR(retinfo);
}
break;
default:
RETURN_EMPTY;
break;
}
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_lastclickx, input)
{
extern int lastclickcol;
RETURN_INT(lastclickcol);
}
BUILT_IN_FUNCTION(function_lastclicky, input)
{
extern int lastclickrow;
RETURN_INT(lastclickrow);
}
BUILT_IN_FUNCTION(function_screensize, input)
{
char retbuffer[50];
if (!my_stricmp(input, "cx"))
sprintf(retbuffer, "%d", gui_screen_width());
else if (!my_stricmp(input, "cy"))
sprintf(retbuffer, "%d", gui_screen_height());
else
sprintf(retbuffer, "%d %d", gui_screen_width(), gui_screen_height());
RETURN_STR(retbuffer);
}
#endif
/*
* Date: Wed, 2 Sep 1998 18:20:34 -0500 (CDT)
* From: CrackBaby <crack@feeding.frenzy.com>
*/
/*
* $getopt(<optopt var> <optarg var> <opt string> <argument list>)
*
* Processes a list of switches and args. Returns one switch char each time
* it's called, sets $<optopt var> to the char, and sets $<optarg var> to the
* value of the next argument if the switch needs one.
*
* Syntax for <opt string> and <argument list> should be identical to
* getopt(3). A ':' in <opt string> is a required argument, and a "::" is an
* optional one. A '-' by itself in <argument list> is a null argument, and
* switch parsing stops after a "--"
*
* If a switch requires an argument, but the argument is missing, $getopt()
* returns a '-' If a switch is given which isn't in the opt string, the
* function returns a '!' $<optopt var> is still set in both cases.
*
* Example usage:
* while (option = getopt(optopt optarg "ab:c:" $*)) {
* switch ($option) {
* (a) {echo * option "$optopt" used}
* (b) {echo * option "$optopt" used - $optarg}
* (c) {echo * option "$optopt" used - $optarg}
* (!) {echo * option "$optopt" is an invalid option}
* (-) {echo * option "$optopt" is missing an argument}
* }
* }
*/
BUILT_IN_FUNCTION(function_getopt, input)
{
static char switches [INPUT_BUFFER_SIZE+1] = "",
args [INPUT_BUFFER_SIZE+1] = "",
last_input [INPUT_BUFFER_SIZE+1] = "",
*sptr = switches,
*aptr = args;
char *optopt_var,
*optarg_var,
*optstr,
*optptr,
*tmp;
char extra_args [INPUT_BUFFER_SIZE+1] = "";
int old_window_display = window_display,
arg_flag = 0;
if (strcmp(last_input, input))
{
strlcpy(last_input, input, INPUT_BUFFER_SIZE);
*switches = 0;
*args = 0;
sptr = switches;
aptr = args;
}
GET_STR_ARG(optopt_var, input);
GET_STR_ARG(optarg_var, input);
GET_STR_ARG(optstr, input);
if (!(optopt_var || optarg_var || optstr))
RETURN_EMPTY;
if (!*switches && !*args && strcmp(last_input, input))
{
/* Process each word in the input string */
while ((tmp = next_arg(input, &input)))
{
/* Word is a switch or a group of switches */
if (tmp[0] == '-' && tmp[1] && tmp[1] != '-'
&& !arg_flag)
{
/* Look at each char after the '-' */
for (++tmp; *tmp; tmp++)
{
/* If the char is found in optstr
and doesn't need an argument,
it's added to the switches list.
switches are stored as "xy" where
x is the switch letter and y is
'_' normal switch
':' switch with arg
'-' switch with missing arg
'!' unrecognized switch
*/
strlcat(switches, space, INPUT_BUFFER_SIZE);
strncat(switches, tmp, 1);
/* char is a valid switch */
if ((optptr = strchr(optstr, *tmp)))
{
/* char requires an argument */
if (*(optptr + 1) == ':')
{
/* -xfoo, argument is
"foo" */
if (*(tmp + 1))
{
tmp++;
strlcat(args, tmp, INPUT_BUFFER_SIZE);
strlcat(args, space, INPUT_BUFFER_SIZE);
strlcat(switches, ":", INPUT_BUFFER_SIZE);
break;
}
/* Otherwise note that
the next word in
the input is our
arg. */
else if (*(optptr + 2) == ':')
arg_flag = 2;
else
arg_flag = 1;
}
/* Switch needs no argument */
else strlcat(switches, "_", INPUT_BUFFER_SIZE);
}
/* Switch is not recognized */
else strlcat(switches, "!", INPUT_BUFFER_SIZE);
}
}
else
{
/* Everything after a "--" is added to
extra_args */
if (*tmp == '-' && *(tmp + 1) == '-')
{
tmp += 2;
strlcat(extra_args, tmp, INPUT_BUFFER_SIZE);
strlcat(extra_args, input, INPUT_BUFFER_SIZE);
*input = 0;
}
/* A '-' by itself is a null arg */
else if (*tmp == '-' && !*(tmp + 1))
{
if (arg_flag == 1)
strlcat(switches, "-", INPUT_BUFFER_SIZE);
else if (arg_flag == 2)
strlcat(switches, "_", INPUT_BUFFER_SIZE);
*tmp = 0;
arg_flag = 0;
}
/* If the word doesn't start with a '-,' it must be
either the argument of a switch or just extra
info. */
else if (arg_flag)
{
/* If arg_flag is positive, we've processes
a switch which requires an arg and we can
just tack the word onto the end of args[] */
strlcat(args, tmp, INPUT_BUFFER_SIZE);
strlcat(args, space, INPUT_BUFFER_SIZE);
strlcat(switches, ":", INPUT_BUFFER_SIZE);
arg_flag = 0;
}
else
{
/* If not, we'll put it aside and add it to
args[] after all the switches have been
looked at. */
strlcat(extra_args, tmp, INPUT_BUFFER_SIZE);
strlcat(extra_args, space, INPUT_BUFFER_SIZE);
}
}
}
/* If we're expecting an argument to a switch, but we've
reached the end of our input, the switch is missing its
arg. */
if (arg_flag == 1)
strlcat(switches, "-", INPUT_BUFFER_SIZE);
else if (arg_flag == 2)
strlcat(switches, "_", INPUT_BUFFER_SIZE);
strlcat(args, extra_args, INPUT_BUFFER_SIZE);
}
window_display = 0;
if ((tmp = next_arg(sptr, &sptr)))
{
switch (*(tmp + 1))
{
case '_':
*(tmp + 1) = 0;
add_var_alias(optopt_var, tmp);
add_var_alias(optarg_var, NULL);
window_display = old_window_display;
RETURN_STR(tmp);
case ':':
*(tmp + 1) = 0;
add_var_alias(optopt_var, tmp);
add_var_alias(optarg_var, next_arg(aptr, &aptr));
window_display = old_window_display;
RETURN_STR(tmp);
case '-':
*(tmp + 1) = 0;
add_var_alias(optopt_var, tmp);
add_var_alias(optarg_var, NULL);
window_display = old_window_display;
RETURN_STR("-");
case '!':
*(tmp + 1) = 0;
add_var_alias(optopt_var, tmp);
add_var_alias(optarg_var, NULL);
window_display = old_window_display;
RETURN_STR("!");
default:
/* This shouldn't happen */
debugyell("*** getopt switch broken: %s", tmp);
RETURN_EMPTY;
}
}
else
{
add_var_alias(optopt_var, NULL);
add_var_alias(optarg_var, aptr);
window_display = old_window_display;
*switches = 0;
*args = 0;
sptr = switches;
aptr = args;
RETURN_EMPTY;
}
}
BUILT_IN_FUNCTION(function_isaway, input)
{
int refnum = -1;
if (!*input)
refnum = from_server;
else
GET_INT_ARG(refnum, input);
if (get_server_away(refnum))
RETURN_INT(1);
RETURN_INT(0);
}
BUILT_IN_FUNCTION(function_banwords, input)
{
char *ch = NULL;
char *ret = NULL;
extern WordKickList *ban_words;
if (input && *input)
{
GET_STR_ARG(ch, input);
}
else
ch = get_current_channel_by_refnum(0);
if (ban_words)
{
WordKickList *ban;
for (ban = ban_words; ban; ban = ban->next)
{
if (wild_match(ban->channel, ch))
m_s3cat(&ret, space, ban->string);
}
}
RETURN_STR(ret ? ret : empty_string);
}
/*
* Creates a 32 bit hash value for a specified string
* Usage: $hash_32bit(word length)
*
* "word" is the value to be hashed, and "length" is the number
* of characters to hash. If "length" is omitted or not 0 < length <= 64,
* then it defaults to 20.
*
* This was contributed by srfrog (srfrog@lice.com). I make no claims about
* the usefulness of this hashing algorithm.
*
* The name was chosen just in case we decided to implement other hashing
* algorithms for different sizes or types of return values.
*/
BUILT_IN_FUNCTION(function_hash_32bit, input)
{
unsigned char * u_word;
char * word;
char c;
unsigned bit_hi = 0;
int bit_low = 0;
int h_val;
int len;
GET_STR_ARG(word, input)
len = my_atol(input);
if (len <= 0 || len > 64)
len = 20;
for (u_word = (u_char *)word; *u_word && len > 0; ++u_word, --len)
{
c = tolower(*u_word);
bit_hi = (bit_hi << 1) + c;
bit_low = (bit_low >> 1) + c;
}
h_val = ((bit_hi & 2047) << 3) + (bit_low & 0x7);
RETURN_INT(h_val);
}
BUILT_IN_FUNCTION(function_filecomp, input)
{
#ifdef WANT_TABKEY
char *ret, *possible;
int count = 0; /* 6 */
possible = next_arg(input, &input);
ret = get_completions(3, possible, &count, NULL);
return m_sprintf("%d %s", count, ret ? ret : empty_string);
#else
RETURN_EMPTY;
#endif
}
BUILT_IN_FUNCTION(function_nickcomp, input)
{
#ifdef WANT_TABKEY
char *ret, *possible;
int count = 0;/* 4 */
possible = next_arg(input, &input);
ret = get_completions(7, possible, &count, NULL);
return m_sprintf("%d %s", count, ret ? ret : empty_string);
#else
RETURN_EMPTY;
#endif
}
BUILT_IN_FUNCTION(function_log, args)
{
extern FILE *irclog_fp;
add_to_log(irclog_fp, time(NULL), args, logfile_line_mangler);
if (irclog_fp)
RETURN_INT(0);
else
RETURN_INT(-1);
}
/*
* KnghtBrd requested this. Returns the length of the longest word
* in the word list.
*/
BUILT_IN_FUNCTION(function_maxlen, input)
{
size_t maxlen = 0;
size_t len;
char *arg;
while (input && *input)
{
GET_STR_ARG(arg, input)
if ((len = strlen(arg)) > maxlen)
maxlen = len;
}
RETURN_INT(maxlen);
}
/*
* KnghtBrd requested this. It returns a string that is the leading
* substring of ALL the words in the word list. If no string is common
* to all words in the word list, then the FALSE value is returned.
*
* I didn't give this a whole lot of thought about the optimal way to
* do this, so if you have a better idea, let me know. All i do here is
* start at 1 character and walk my way longer and longer until i find a
* length that is not common, and then i stop there. So the expense of this
* algorithm is (M*N) where M is the number of words and N is the number of
* characters they have in common when we're all done.
*/
BUILT_IN_FUNCTION(function_prefix, input)
{
char **words = NULL;
int numwords;
int max_len;
int len_index;
int word_index;
char *retval = NULL;
RETURN_IF_EMPTY(input);
numwords = splitw(input, &words);
max_len = strlen(words[0]);
for (len_index = 1; len_index <= max_len; len_index++)
{
for (word_index = 1; word_index < numwords; word_index++)
{
/*
* Basically, our stopping point is the first time we
* see a string that does NOT share the first "len_index"
* characters with words[0] (which is chosen arbitrarily).
* As long as all words start with the same leading chars,
* we march along trying longer and longer substrings,
* until one of them doesnt work, and then we exit right
* there.
*/
if (my_strnicmp(words[0], words[word_index], len_index))
{
retval = new_malloc(len_index + 1);
strmcpy(retval, words[0], len_index - 1);
new_free((char **)&words);
return retval;
}
}
}
retval = m_strdup(words[0]);
new_free((char **)&words);
return retval;
}
/*
* I added this so |rain| would stop asking me for it. ;-) I reserve the
* right to change the implementation of this in the future.
*/
BUILT_IN_FUNCTION(function_functioncall, input)
{
/*
* These two variables are supposed to be private inside alias.c
* Even though i export them here, it is EVIL EVIL EVIL to use
* them outside of alias.c. So do not follow my example and extern
* these for your own use -- because who knows, one day i may make
* them static and your use of them will not be my fault! :p
*/
extern int wind_index; /* XXXXX Ick */
extern int last_function_call_level; /* XXXXX Ick */
/*
* If the last place we slapped down a FUNCTION_RETURN is in the
* current operating stack frame, then we're in a user-function
* call. Otherwise we're not. Pretty simple.
*/
if (last_function_call_level == wind_index)
RETURN_INT(1);
else
RETURN_INT(0);
}
/*
* Usage: $indextoword(position text)
*
* This function returns the word-number (counting from 0) that contains
* the 'position'th character in 'text' (counting from 0), such that the
* following expression:
*
* $word($indextoword($index(. $*) $*))
*
* would return the *entire word* in which the first '.' in $* is found.
* If 'position' is -1, or past the end of the string, -1 is returned as
* an error flag. Note that this function can be used anywhere that a
* word-number would be used, such as $chngw(). The empty value is returned
* if a syntax error returns.
*
* DONT ASK ME to support 'position' less than 0 to indicate a position
* from the end of the string. Either that can be supported, or you can
* directly use $index() as the first argument; you can't do both. I chose
* the latter intentionally. If you really want to calculate from the end of
* your string, then just add your negative value to $strlen(string) and
* pass that.
*/
BUILT_IN_FUNCTION(function_indextoword, input)
{
size_t pos;
size_t len;
GET_INT_ARG(pos, input);
if (pos < 0)
RETURN_EMPTY;
len = strlen(input);
if (pos < 0 || pos >= len)
RETURN_EMPTY;
/*
* XXX
* Using 'word_count' to do this is a really lazy cop-out, but it
* renders the desired effect and its pretty cheap. Anyone want
* to bicker with me about it?
*/
/* Truncate the string if neccesary */
if (pos + 1 < len)
input[pos + 1] = 0;
RETURN_INT(word_count(input));
}
BUILT_IN_FUNCTION(function_realpath, input)
{
#ifdef HAVE_REALPATH
char resolvedname[MAXPATHLEN];
char *retval;
if ((retval = realpath(input, resolvedname)))
RETURN_STR(resolvedname);
else
RETURN_EMPTY;
#else
RETURN_STR(input);
#endif
}
BUILT_IN_FUNCTION(function_ttyname, input)
{
RETURN_STR(ttyname(0));
}
/*
* $insert(num word string of text)
* returns "string of text" such that "word" begins in the "num"th position
* in the string ($index()-wise)
* NOTE: Positions are numbered from 0
* EX: $insert(3 baz foobarbooya) returns "foobazbarbooya"
*/
BUILT_IN_FUNCTION(function_insert, word)
{
int where;
char * inserted;
char * result;
GET_INT_ARG(where, word);
GET_STR_ARG(inserted, word);
if (where <= 0)
result = m_strdup(empty_string);
else
result = strext(word, word + where);
m_3cat(&result, inserted, word + where);
return result; /* DONT USE RETURN_STR HERE! */
}
BUILT_IN_FUNCTION(function_stat, input)
{
char * filename;
char retval[BIG_BUFFER_SIZE];
struct stat sb;
GET_STR_ARG(filename, input);
if (stat(filename, &sb) < 0)
RETURN_EMPTY;
snprintf(retval, BIG_BUFFER_SIZE,
"%d %d %o %d %d %d %d %lu %lu %lu %ld %ld %ld",
(int) sb.st_dev, /* device number */
(int) sb.st_ino, /* Inode number */
(int) sb.st_mode, /* Permissions */
(int) sb.st_nlink, /* Hard links */
(int) sb.st_uid, /* Owner UID */
(int) sb.st_gid, /* Owner GID */
(int) sb.st_rdev, /* Device type */
(u_long)sb.st_size, /* Size of file */
#ifdef __EMX__
(u_long)sb.st_attr, /* OS/2 Attributes */
(u_long)sb.st_reserved, /* OS/2 reserved */
#else
(u_long)sb.st_blksize, /* Size of each block */
(u_long)sb.st_blocks, /* Blocks used in file */
#endif
(long) sb.st_atime, /* Last-access time */
(long) sb.st_mtime, /* Last-modified time */
(long) sb.st_ctime /* Last-change time */
);
RETURN_STR(retval);
}
BUILT_IN_FUNCTION(function_serverlag, input)
{
int server = from_server;
if (input && *input)
server = my_atol(input);
RETURN_INT(get_server_lag(server));
}
BUILT_IN_FUNCTION(function_strchar, input)
{
char *chr, *ret = NULL;
char *(*func)(const char *, int);
GET_STR_ARG(chr, input);
if (!my_stricmp("STRCHR", fn))
func = strchr;
else
func = strrchr;
if (chr && *chr)
ret = func(input, *chr);
RETURN_STR(ret);
}
BUILT_IN_FUNCTION(function_isdisplaying, input)
{
RETURN_INT(window_display);
}
BUILT_IN_FUNCTION(function_getcap, input)
{
char * type;
GET_STR_ARG(type, input);
if (!my_stricmp(type, "TERM"))
{
char * retval;
char * term = NULL;
int querytype = 0;
int mangle = 1;
GET_STR_ARG(term, input);
if (*input)
GET_INT_ARG(querytype, input);
if (*input)
GET_INT_ARG(mangle, input);
if (!term) /* This seems spurious */
RETURN_EMPTY;
if ((retval = get_term_capability(term, querytype, mangle)))
RETURN_STR(retval);
RETURN_EMPTY;
}
RETURN_EMPTY;
}
BUILT_IN_FUNCTION(function_getset, input)
{
RETURN_MSTR(make_string_var(input));
}
BUILT_IN_FUNCTION(function_builtin, input)
{
RETURN_MSTR(built_in_alias (*input, NULL));
}
BUILT_IN_FUNCTION(function_ipv6, input)
{
#ifdef IPV6
RETURN_INT(1);
#else
RETURN_INT(0);
#endif
}