diff --git a/Makefile b/Makefile index 7920886..11c82cd 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -MISCFILES = CREDITS LICENSE README README.TCL TODO VERSIONS VERSIONS-1 Makefile configure \ +MISCFILES = CREDITS FEATURES LICENSE README README.TCL TODO VERSIONS VERSIONS-2.x Makefile configure \ checkmech sample.conf sample.py sample.tcl sample.userfile default.bigchars public/README trivia/README ASCIIFILES = ascii/README ascii/bbw ascii/camel ascii/goatse ascii/mech ascii/phooler @@ -58,8 +58,8 @@ TRIVFILES = trivia/mkindex.c SRCFILES = src/alias.c src/auth.c src/bounce.c src/chanban.c src/channel.c src/core.c src/ctcp.c src/debug.c src/dns.c \ src/function.c src/gencmd.c src/greet.c src/help.c src/hostinfo.c src/irc.c src/kicksay.c src/main.c src/mega.c \ src/net.c src/net_chan.c src/note.c src/notify.c src/ons.c src/parse.c src/partyline.c src/perl.c src/prot.c \ - src/python.c src/redirect.c src/reset.c src/seen.c src/shit.c src/socket.c src/spy.c src/stats.c src/tcl.c \ - src/toybox.c src/trivia.c src/uptime.c src/urlcap.c src/user.c src/vars.c src/web.c \ + src/python.c src/reset.c src/seen.c src/shit.c src/socket.c src/spy.c src/tcl.c \ + src/toybox.c src/trivia.c src/uptime.c src/user.c src/vars.c src/web.c \ src/lib/md5.c src/lib/md5.h src/lib/string.c HDRFILES = src/defines.h src/global.h src/h.h src/settings.h src/structs.h src/text.h src/usage.h diff --git a/VERSIONS b/VERSIONS index 979798d..bac9962 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,5 +1,6 @@ 3.0.99p4 -- WORK IN PROGRESS (~March, 2018) + * Added: RAND command (toybox). Usage: RAND [[min[-| ]]max|"nick"|"luser"] * Added: Energymech can now link with libmusl (--with-libmusl[=/PATH/TO/musl-gcc]) * Added: (ALPHA) Perl scripting support (PERL, PERLSCRIPT) * Changed: Trivia question file must be placed in ./trivia/* diff --git a/config/sendfile.c b/config/sendfile.c new file mode 100644 index 0000000..fb11fba --- /dev/null +++ b/config/sendfile.c @@ -0,0 +1,6 @@ +#include + +void test(int to, int from, off_t offset, size_t ct) +{ + sendfile(to, from, &offset, ct); +} diff --git a/configure b/configure index 2f2dde3..7520118 100755 --- a/configure +++ b/configure @@ -43,6 +43,7 @@ set_feature_defaults() { ft_hostinfo=$ft_default ft_ircd_ext=$ft_default ft_md5=$ft_default + ft_netcfg=$ft_default ft_newbie=$ft_default ft_note=$ft_default ft_notify=$ft_default @@ -106,6 +107,7 @@ do ircd_ext ) ft_ircd_ext=$yesno ;; libmusl ) try_libmusl=$yesno ;; md5 ) ft_md5=$yesno ;; + netcfg ) ft_netcfg=$yesno ;; newbie ) ft_newbie=$yesno ;; note ) ft_note=$yesno ;; notify ) ft_notify=$yesno ;; @@ -153,8 +155,8 @@ do case "$feature" in alias | botnet | bounce | chanban | ctcp | dccfile | debug | dynamode | dyncmd | greet | hostinfo | idwrap | ircd_ext | libmusl | md5 \ - | newbie | note | notify | perl | profiling | python | rawdns | redirect | seen | session | sha | stats | suppress | tcl | telnet | toybox \ - | trivia | uptime | urlcapture | web | wingate ) + | netcfg | newbie | note | notify | perl | profiling | python | rawdns | redirect | seen | session | sha | stats | suppress | tcl \ + | telnet | toybox | trivia | uptime | urlcapture | web | wingate ) case _"$optarg"_ in _yes_ | _no_ | __ ) ;; @@ -212,6 +214,8 @@ do libmusl_no ) try_libmusl=no ;; md5_yes | md5_ ) ft_md5=yes ;; md5_no ) ft_md5=no ;; + netcfg_yes | netcfg_ ) ft_netcfg=yes ;; + netcfg_no ) ft_netcfg=no ;; newbie_yes | newbie_ ) ft_newbie=yes ;; newbie_no ) ft_newbie=no ;; note_yes | note_ ) ft_note=yes ;; @@ -273,6 +277,7 @@ do ircd_ext ) ft_ircd_ext=no ;; libmusl ) try_libmusl=no ;; md5 ) ft_md5=no ;; + netcfg ) ft_netcfg=no ;; newbie ) ft_newbie=no ;; note ) ft_note=no ;; notify ) ft_notify=no ;; @@ -348,6 +353,7 @@ Features and packages: --with-libmusl[=/PATH/TO/musl-gcc] Try to use libmusl instead of system default --with-md5 Support for hashing passwords with the MD5 hashing algorithm + --with-netcfg Support for loading config blocks from the internet/other bots --with-newbie Newbie support for extra sanity checks and error messages --with-note --with-notify @@ -737,6 +743,25 @@ echo $ac_t "$has_unaligned" rm -f $TESTP +# +# is there a sendfile() system call? +# + +has_sendfile=no +DEF_SENDFILE='#undef HAS_SENDFILE' +TESTC=config/sendfile.c + +echo $ac_n "checking if system has sendfile() ... "$ac_c + +$CC -c $TESTC -o $TESTO 1> /dev/null 2> /dev/null +if [ -r $TESTO ]; then + has_sendfile=yes + DEF_SENDFILE='#define HAS_SENDFILE' +fi +echo $ac_t "$has_sendfile" + +rm -f $TESTO + # # where is inet_addr() ? # @@ -1204,6 +1229,13 @@ test "$ft_ircd_ext" && $out "$ft_ircd_ext" && ans=$ft_ircd_ext test -z "$ft_ircd_ext" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_ircd_ext='#define IRCD_EXTENSIONS' +def_netcfg='#undef NETCFG' +unset ans +$out $ac_n "[ ALPHA] Netcfg support? ............................ [Y/n] "$ac_c +test "$ft_netcfg" && $out "$ft_netcfg" && ans=$ft_netcfg +test -z "$ft_netcfg" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_netcfg='#define NETCFG' + def_newbie='#undef NEWBIE' unset ans $out $ac_n "[STABLE] Newbie support? ............................ [Y/n] "$ac_c @@ -1416,6 +1448,7 @@ s|@DEF_HOSTINFO@|$def_hostinfo|; s|@DEF_IRCD_EXT@|$def_ircd_ext|; s|@DEF_MD5@|$def_md5|; s|@DEF_SHA@|$def_sha|; + s|@DEF_NETCFG@|$def_netcfg|; s|@DEF_NEWBIE@|$def_newbie|; s|@DEF_NOTE@|$def_note|; s|@DEF_NOTIFY@|$def_notify|; diff --git a/help/RAND b/help/RAND new file mode 100644 index 0000000..4ca563b --- /dev/null +++ b/help/RAND @@ -0,0 +1,19 @@ + +Tell the user a random number. + +Valid forms: + +RAND Number between 1 and 100 (incl. 1 and 100) +RAND 10 Number between 1 and 10 (incl. 1 and 10) +RAND 0 10 Number between 0 and 10 (incl. 0 and 10) +RAND 0-10 Same +RAND nick Random channel non-bot user +RAND luser Random channel user with no bot access + +By default, the bot picks a number between 1 and 100 (incl. 1 and 100) + +If the command ``RAND nick'' is issued in a channel, the bot picks a random channel +user (after eliminating all known bots) and says the nick in the channel. + +If the command ``RAND luser'' is issued in a channel, the bot picks a random channel +user that has no access in the bots userlist and says the nick in the channel. diff --git a/netcfg/README b/netcfg/README new file mode 100644 index 0000000..a158546 --- /dev/null +++ b/netcfg/README @@ -0,0 +1 @@ +Storage for netcfg accessible files diff --git a/sample.conf b/sample.conf index 118f65b..3392794 100644 --- a/sample.conf +++ b/sample.conf @@ -1,13 +1,11 @@ ; ; server connection timeout limit = 60 seconds ; - set ctimeout 60 ; ; add some servers to the serverlist ; - servergroup undernet server amsterdam.nl.eu.undernet.org 6663 server amsterdam2.nl.eu.undernet.org 6663 @@ -41,7 +39,6 @@ server sterling.va.us.undernet.org 6669 ; ; this is sorta how a botnet configuration would look like... ; - set linkport 5000 set linkpass your_lame_password set autolink 1 @@ -56,14 +53,12 @@ set autolink 1 ; host internet host to connect to when linking the other bot ; port tcp port to connect to on remote host ; - link 2 janes_password janes.host.com 5000 ; Jane Does EnergyMech link 3 johns_password johns.host.com 5000 ; John Does EnergyMech ; ; we cant connect -to- bot 4, but we can accept connections from it! ; - link 4 ongabonga_pass ; @@ -76,14 +71,13 @@ link 4 ongabonga_pass ; 1 the globally uniqe ID (guid), used for botnet linking ; emech3 the bots nick ; - nick 1 emech3 set altnick myemech3 monkey3 dummy3 fuzzy3 ; ; set connection variables for this bot ; - +set servergroup undernet set userfile mech.passwd set ident robot set ircname EnergyMech 3: The Next Generation @@ -95,7 +89,6 @@ set cc 1 ; ; join a channel ; - join #anychannel set pub 1 set aop 1 @@ -105,11 +98,9 @@ set prot 4 ; ; this is how you'd load a tcl on startup... ; - tclscript does-not-exist.tcl ; ; Can you guess? ; - die You did not edit your configuation file! diff --git a/sample.netcfg b/sample.netcfg new file mode 100644 index 0000000..deea1a6 --- /dev/null +++ b/sample.netcfg @@ -0,0 +1,73 @@ +; +; server connection timeout limit = 60 seconds +; +set ctimeout 60 + +; +; in this example, servers are loaded by netcfg +; + +; +; this is sorta how a botnet configuration would look like... +; +set linkport 5000 +set linkpass your_lame_password +set autolink 1 + +; +; thats all the botnet stuff for now, in this example, the rest is loaded by netcfg +; + +; +; create a new bot +; +; 1 the globally uniqe ID (guid), used for botnet linking +; emech3 the bots nick +; +nick 1 emech3 +set altnick myemech3 monkey3 dummy3 fuzzy3 + +; +; set connection variables for this bot +; +set servergroup freenet +set userfile mech.passwd +set ident robot +set ircname EnergyMech 3: The Next Generation +set umodes +w +set cmdchar . +set modes 4 +set cc 1 + +; +; join a channel +; +join #anychannel +set pub 1 +set aop 1 +set avoice 1 +set prot 4 + +; +; setup command restrictions for commands loaded with netcfg +; all netcfg access restriction commands are optional, by default everything is unrestricted +; + +; run netcfg commands as a level 90 user with global access +netcfg access * 90 + +; disallow all commands +netcfg disallow * + +; allow listed commands again (access permissions still apply) +netcfg allow servergroup server link + +; +; load 'groupsetup.set' from 192.168.1.99, port 5000, using password 'gronkadonk' +; +netcfg groupsetup.set 192.168.1.99:5000 gronkadonk + +; +; Can you guess? +; +die You did not edit your configuation file! diff --git a/src/Makefile.in b/src/Makefile.in index ee61390..8a90ddb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -49,13 +49,13 @@ TESTFILES = aliastest safepathtest OFILES = alias.o auth.o bounce.o chanban.o channel.o core.o ctcp.o debug.o dns.o function.o greet.o \ help.o hostinfo.o irc.o kicksay.o main.o net.o net_chan.o note.o notify.o ons.o parse.o partyline.o \ - perl.o prot.o python.o redirect.o reset.o seen.o shit.o socket.o spy.o stats.o tcl.o toybox.o \ - trivia.o uptime.o urlcap.o user.o vars.o web.o lib/string.o @MD5_O@ @SHA_O@ + perl.o prot.o python.o reset.o seen.o shit.o socket.o spy.o tcl.o toybox.o \ + trivia.o uptime.o user.o vars.o web.o lib/string.o @MD5_O@ @SHA_O@ SRCFILES = alias.c auth.c bounce.c chanban.c channel.c core.c ctcp.c debug.c dns.c function.c greet.c \ help.c hostinfo.c irc.c kicksay.c main.c net.c net_chan.c note.c notify.c ons.c parse.c partyline.c \ - perl.c prot.c python.c redirect.c reset.c seen.c shit.c socket.c spy.c stats.c tcl.c toybox.c \ - trivia.c uptime.c urlcap.c user.c vars.c web.c lib/string.c @MD5_C@ @SHA_C@ + perl.c prot.c python.c reset.c seen.c shit.c socket.c spy.c tcl.c toybox.c \ + trivia.c uptime.c user.c vars.c web.c lib/string.c @MD5_C@ @SHA_C@ .PHONY: all clean mega-install mega mega-static test commands @@ -221,9 +221,6 @@ prot.o: prot.c $(INCS) python.o: python.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) $(PYINCLUDE) -redirect.o: redirect.c $(INCS) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) - reset.o: reset.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) @@ -239,9 +236,6 @@ socket.o: socket.c $(INCS) spy.o: spy.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) -stats.o: stats.c $(INCS) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) - tcl.o: tcl.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) $(TCLINCLUDE) @@ -254,9 +248,6 @@ trivia.o: trivia.c $(INCS) uptime.o: uptime.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) -urlcap.o: urlcap.c $(INCS) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) - user.o: user.c $(INCS) usercombo.h $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) diff --git a/src/channel.c b/src/channel.c index f05d3e6..2c17b36 100644 --- a/src/channel.c +++ b/src/channel.c @@ -650,7 +650,7 @@ void purge_chanusers(Chan *chan) remove_chanuser(chan,chan->users->nick); } -char *get_nuh(ChanUser *user) +char *get_nuh(const ChanUser *user) { sprintf(nuh_buf,"%s!%s",user->nick,user->userhost); return(nuh_buf); diff --git a/src/config.h.in b/src/config.h.in index 4f5087a..058f470 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -22,9 +22,10 @@ #define CONFIG_H /* - * DEBUG: extreme amounts of debug code, needed if you want to use the -d commandline switch + * ALIAS: create aliases for commands */ -@DEF_DEBUG@ +@DEF_ALIAS@ +#define MAXALIASRECURSE 20 /* * BOTNET: support for connecting bots to eachother in a botnet @@ -32,27 +33,27 @@ @DEF_BOTNET@ /* - * TELNET: connecting to the partyline via telnet + * BOUNCE: support for `standalone' irc proxy */ -@DEF_TELNET@ -#define TELNET_TIMEOUT 60 /* 60 seconds to enter password */ +@DEF_BOUNCE@ /* - * ALIAS: create aliases for commands + * Standard CTCP replies (PING, FINGER, VERSION), and commands (CTCP, PING). + * DCC CHAT and the CHAT command still works even if this is undefined. */ -@DEF_ALIAS@ -#define MAXALIASRECURSE 20 +@DEF_CTCP@ +#define CTCP_SLOTS 6 /* how many slots we have to send out CTCP replies */ +#define CTCP_TIMEOUT 60 /* how long before a used slot expires and can be used again */ /* - * Support for SEEN command, undefined by default - * because it consumes a lardass amount of memory + * DEBUG: extreme amounts of debug code, needed if you want to use the -d commandline switch */ -@DEF_SEEN@ +@DEF_DEBUG@ /* - * sessions support (mech.session) + * DYNAMODE: dynamic updating of the +l channel user limit */ -@DEF_SESSION@ +@DEF_DYNAMODE@ /* * Support to alter commandlevels on the fly. undefine @@ -61,14 +62,30 @@ @DEF_DYNCMD@ /* - * NEWBIE: support for some newbie spanking routines + * GREET: greet known users when they join a channel */ -@DEF_NEWBIE@ +@DEF_GREET@ /* - * WINGATE: support for proxy connections through wingates + * HOSTINFO: share information about the host that the bot is running on */ -@DEF_WINGATE@ +@DEF_HOSTINFO@ + +/* + * IDWRAP: support for idwrap ident spoofing + */ +@DEF_IDWRAP@ +#define IDWRAP_PATH @IDWRAP_PATH@ + +/* + * IRCD_EXTENSIONS: support some special features of new ircds + */ +@DEF_IRCD_EXT@ +#ifdef IRCD_EXTENSIONS +@DEF_CHANBAN@ +#else +#undef CHANBAN +#endif /* IRCD_EXTENSIONS */ /* * SHACRYPT: support use of SHA to hash passwords @@ -80,14 +97,6 @@ */ @DEF_MD5@ -/* - * Standard CTCP replies (PING, FINGER, VERSION), and commands (CTCP, PING). - * DCC CHAT and the CHAT command still works even if this is undefined. - */ -@DEF_CTCP@ -#define CTCP_SLOTS 6 /* how many slots we have to send out CTCP replies */ -#define CTCP_TIMEOUT 60 /* how long before a used slot expires and can be used again */ - /* * */ @@ -96,21 +105,11 @@ #define DCC_PUBLICINCOMING DCC_PUBLICFILES "incoming/" #define DCC_FILETIMEOUT 90 -/* - * UPTIME: send uptime packets to uptime.energymech.net - */ -@DEF_UPTIME@ - /* * REDIRECT: send command output from certain commands to a different target */ @DEF_REDIRECT@ -/* - * GREET: greet known users when they join a channel - */ -@DEF_GREET@ - /* * PERL: scripting using the perl language (may not be supported on all hosts) */ @@ -127,14 +126,14 @@ @DEF_PYTHON@ /* - * DYNAMODE: dynamic updating of the +l channel user limit + * NETCFG: support for loading config blocks from the internet/other bots */ -@DEF_DYNAMODE@ +@DEF_NETCFG@ /* - * WEB: serving documents via HTTP + * NEWBIE: support for some newbie spanking routines */ -@DEF_WEB@ +@DEF_NEWBIE@ /* * NOTE: enable commands to leave notes for users to read at a later time @@ -147,10 +146,26 @@ @DEF_NOTIFY@ /* - * IDWRAP: support for idwrap ident spoofing + * Support for SEEN command, undefined by default + * because it consumes a lardass amount of memory */ -@DEF_IDWRAP@ -#define IDWRAP_PATH @IDWRAP_PATH@ +@DEF_SEEN@ + +/* + * sessions support (mech.session) + */ +@DEF_SESSION@ + +/* + * SUPPRESS: suppress duplication of certain commands + */ +@DEF_SUPPRESS@ + +/* + * TELNET: connecting to the partyline via telnet + */ +@DEF_TELNET@ +#define TELNET_TIMEOUT 60 /* 60 seconds to enter password */ /* * TRIVIA: support for playing trivia game @@ -162,11 +177,6 @@ */ @DEF_TOYBOX@ -/* - * BOUNCE: support for `standalone' irc proxy - */ -@DEF_BOUNCE@ - /* * STATS: channel statistics */ @@ -178,19 +188,9 @@ @DEF_RAWDNS@ /* - * IRCD_EXTENSIONS: support some special features of new ircds + * UPTIME: send uptime packets to uptime.energymech.net */ -@DEF_IRCD_EXT@ -#ifdef IRCD_EXTENSIONS -@DEF_CHANBAN@ -#else -#undef CHANBAN -#endif /* IRCD_EXTENSIONS */ - -/* - * HOSTINFO: share information about the host that the bot is running on - */ -@DEF_HOSTINFO@ +@DEF_UPTIME@ /* * URLCAPTURE: capture url's mentioned @@ -198,9 +198,14 @@ @DEF_URLCAPTURE@ /* - * SUPPRESS: suppress duplication of certain commands + * WEB: serving documents via HTTP */ -@DEF_SUPPRESS@ +@DEF_WEB@ + +/* + * WINGATE: support for proxy connections through wingates + */ +@DEF_WINGATE@ /* * FASTNICK: faster nick regain if the nick is seen when released @@ -497,6 +502,13 @@ const char __mx_opts[] = "" #undef OPT_COREONLY #endif /* BOTNET */ +#ifdef NETCFG + OPT_COMMA "netcfg" +#undef OPT_COMMA +#define OPT_COMMA ", " +#undef OPT_COREONLY +#endif /* NETCFG */ + #ifdef NEWBIE OPT_COMMA "newbie" #undef OPT_COMMA diff --git a/src/gencmd.c b/src/gencmd.c index 1d7933d..3f5a67d 100644 --- a/src/gencmd.c +++ b/src/gencmd.c @@ -67,6 +67,7 @@ struct { 0, "VERIFY", "do_auth", 0 | NOPUB | CBANG }, // catch login attempts #ifdef TOYBOX { 0, "8BALL", "do_8ball", 0 | CBANG | SUPRES }, + { 0, "RAND", "do_rand", 0 | CBANG | SUPRES }, #endif /* TOYBOX */ /* diff --git a/src/global.h b/src/global.h index dfa45d7..064f7e7 100644 --- a/src/global.h +++ b/src/global.h @@ -105,6 +105,7 @@ BEG User *CurrentUser MDEF(NULL); BEG Shit *CurrentShit MDEF(NULL); BEG const OnMsg *CurrentCmd MDEF(NULL); BEG User *cfgUser MDEF(NULL); +BEG const char *global_from MDEF(NULL); BEG User __internal_users[2]; #define CoreUser (__internal_users[0]) diff --git a/src/h.h b/src/h.h index d0b17c0..51aba4c 100644 --- a/src/h.h +++ b/src/h.h @@ -164,7 +164,7 @@ ChanUser *find_chanuser(Chan *, const char *); void remove_chanuser(Chan *, const char *); void make_chanuser(char *, char *); void purge_chanusers(Chan *); -char *get_nuh(ChanUser *); +char *get_nuh(const ChanUser *); void do_join(COMMAND_ARGS) __page(CMD1_SEG); void do_part(COMMAND_ARGS) __page(CMD1_SEG); void do_cycle(COMMAND_ARGS) __page(CMD1_SEG); @@ -586,7 +586,6 @@ void send_redirect(char *); void end_redirect(void); /* reset.c */ -// ; char *recover_client(char *env); char *recover_debug(char *env); @@ -641,47 +640,48 @@ void send_spy(const char *src, const char *format, ...); void send_global(const char *src, const char *format, ...); void spy_typecount(Mech *bot); int spy_source(char *from, int *t_src, const char **src); -void do_spy(COMMAND_ARGS) __page(CMD1_SEG); -void do_rspy(COMMAND_ARGS) __page(CMD1_SEG); - -/* stats.c */ - +char *urlhost(const char *); +LS void urlcapture(const char *) __page(CORE_SEG); void stats_loghour(Chan *chan, char *filename, int hour); void stats_plusminususer(Chan *chan, int plusminus); +void do_spy(COMMAND_ARGS) __page(CMD1_SEG); +void do_rspy(COMMAND_ARGS) __page(CMD1_SEG); void do_info(COMMAND_ARGS) __page(CMD1_SEG); +LS void do_urlhist(COMMAND_ARGS) __page(CMD1_SEG); /* tcl.c */ #ifdef TCL -char *tcl_var_read(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int flags); -char *tcl_var_write(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int flags); -int tcl_timer_jump(Hook *hook); -int tcl_parse_jump(char *from, char *rest, Hook *hook); -void tcl_dcc_complete(Client *client, int cps); -int tcl_hook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_unhook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_userlevel(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_debug(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_to_server(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_to_file(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_dcc_sendfile(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -int tcl_dns_jump(char *host, char *resolved, Hook *hook); -int tcl_dns(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); -void init_tcl(void); -void do_tcl(COMMAND_ARGS) __page(CMD1_SEG); +LS char *tcl_var_read(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int flags); +LS char *tcl_var_write(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int flags); +LS int tcl_timer_jump(Hook *hook); +LS int tcl_parse_jump(char *from, char *rest, Hook *hook); +LS void tcl_dcc_complete(Client *client, int cps); +LS int tcl_hook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_unhook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_userlevel(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_debug(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_to_server(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_to_file(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_dcc_sendfile(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS int tcl_dns_jump(char *host, char *resolved, Hook *hook); +LS int tcl_dns(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +LS void init_tcl(void); +LS void do_tcl(COMMAND_ARGS) __page(CMD1_SEG); #endif /* TCL */ /* toybox.c */ -int read_bigcharset_callback(char *rest); -int read_bigcharset(char *fname); -int read_ascii(char *rest); -void do_bigsay(COMMAND_ARGS) __page(CMD1_SEG); -void do_random_msg(COMMAND_ARGS) __page(CMD1_SEG); -void do_randtopic(COMMAND_ARGS) __page(CMD1_SEG); -void do_8ball(COMMAND_ARGS) __page(CMD1_SEG); +LS int read_bigcharset_callback(char *rest); +LS int read_bigcharset(char *fname); +LS int read_ascii(char *rest); +LS void do_bigsay(COMMAND_ARGS) __page(CMD1_SEG); +LS void do_random_msg(COMMAND_ARGS) __page(CMD1_SEG); +LS void do_randtopic(COMMAND_ARGS) __page(CMD1_SEG); +LS void do_8ball(COMMAND_ARGS) __page(CMD1_SEG); LS void do_ascii(COMMAND_ARGS) __page(CMD1_SEG); +LS void do_rand(COMMAND_ARGS) __page(CMD1_SEG); /* trivia.c */ @@ -708,15 +708,8 @@ void uptime_death(int type); void process_uptime(void); void do_upsend(COMMAND_ARGS) __page(CMD1_SEG); -/* urlcap.c */ - -char *urlhost(const char *); -LS void urlcapture(const char *) __page(CORE_SEG); -LS void do_urlhist(COMMAND_ARGS) __page(CMD1_SEG); - /* user.c */ - LS void cfg_user(char *) __page(CFG1_SEG); void cfg_modcount(char *); LS void cfg_pass(char *) __page(CFG1_SEG); diff --git a/src/hostinfo.c b/src/hostinfo.c index 6d3b12d..18ef225 100644 --- a/src/hostinfo.c +++ b/src/hostinfo.c @@ -96,7 +96,6 @@ int parse_proc_status(char *line) return(FALSE); } -char *cpufrom; int sentmodel; int physid,cpus,cores,addsiblings; @@ -146,7 +145,7 @@ int parse_proc_cpuinfo(char *line) #ifdef DEBUG debug("(parse_proc_cpuinfo) model name = %s\n",omni); #endif - to_user_q(cpufrom,"Cpu: %s\n",omni); + to_user_q(global_from,"Cpu: %s\n",omni); sentmodel++; } else @@ -237,8 +236,7 @@ void do_cpuinfo(COMMAND_ARGS) return; #endif - debug("%s\n",from); - cpufrom = from; + global_from = from; sentmodel = 0; physid = -1; cpus = cores = addsiblings = 0; diff --git a/src/main.c b/src/main.c index a34a487..f1162f1 100644 --- a/src/main.c +++ b/src/main.c @@ -952,6 +952,17 @@ int main(int argc, char **argv, char **envp) debug_on_exit = TRUE; break; #endif /* DEBUG */ + case 'e': // run a single command before exiting + startup = 3; + ++argv; + if (*argv) + { + //void on_msg(char *from, char *to, char *rest) + //on_msg(); + } + else + to_file(1,"error: Missing argument for -e \n"); + _exit(0); case 't': startup = 666; break; diff --git a/src/mega.c b/src/mega.c index d5a1c03..0e98865 100644 --- a/src/mega.c +++ b/src/mega.c @@ -38,18 +38,15 @@ #include "perl.c" #include "prot.c" #include "python.c" -#include "redirect.c" #include "reset.c" #include "seen.c" #include "shit.c" #include "socket.c" #include "spy.c" -#include "stats.c" #include "tcl.c" #include "toybox.c" #include "trivia.c" #include "uptime.c" -#include "urlcap.c" #include "user.c" #include "vars.c" #include "web.c" diff --git a/src/net.c b/src/net.c index 925367d..accd79a 100644 --- a/src/net.c +++ b/src/net.c @@ -1225,17 +1225,21 @@ void botnet_parse(BotNet *bn, char *rest) #ifdef TELNET if (bn->status == BN_UNKNOWN) { - if (!stringcmp(rest,telnetprompt)) + if (!stringcmp(rest,telnetprompt)) // another bot sent me its telnetprompt return; - if (*rest != 'B') +#ifdef NETCFG + if (strncmp(rest,"netcfg ",7) == 0) { - if (check_telnet(bn->sock,rest)) - { - bn->sock = -1; - bn->status = BN_DEAD; - deadlinks = TRUE; - return; - } + goto not_a_botnet_connection; + } +#endif /* NETCFG */ + if (check_telnet(bn->sock,rest)) + { +not_a_botnet_connection: + bn->sock = -1; + bn->status = BN_DEAD; + deadlinks = TRUE; + return; } } #endif /* TELNET */ diff --git a/src/notify.c b/src/notify.c index d368d68..57bd513 100644 --- a/src/notify.c +++ b/src/notify.c @@ -518,7 +518,6 @@ LS const char notify_opt[NF_OPTIONS][10] = #define NFF_FULL 8 #define NFF_SEEN 16 -LS char *nf_from; LS int nf_header; void nfshow_brief(Notify *nf) @@ -547,8 +546,8 @@ void nfshow_brief(Notify *nf) s = " never seen"; if (!nf_header) - to_user(nf_from,"\037nick\037 \037last seen\037 \037note\037"); - to_user(nf_from,(nf->info) ? "%-9s %-22s %s" : "%-9s %s", + to_user(global_from,"\037nick\037 \037last seen\037 \037note\037"); + to_user(global_from,(nf->info) ? "%-9s %-22s %s" : "%-9s %s", nf->nick,s,nf->info); nf_header++; } @@ -560,15 +559,15 @@ void nfshow_full(Notify *nf) char *s,*opt; if (nf_header) - to_user(nf_from," "); - to_user(nf_from,(nf->status == NF_MASKONLINE) ? "Nick: \037%s\037" : "Nick: %s",nf->nick); + to_user(global_from," "); + to_user(global_from,(nf->status == NF_MASKONLINE) ? "Nick: \037%s\037" : "Nick: %s",nf->nick); if (nf->info) - to_user(nf_from,"Note: %s",nf->info); + to_user(global_from,"Note: %s",nf->info); if (nf->mask) - to_user(nf_from,"Mask: %s",nf->mask); + to_user(global_from,"Mask: %s",nf->mask); if (nf->log) { - to_user(nf_from,"Online history:"); + to_user(global_from,"Online history:"); for(nlog=nf->log;nlog;nlog=nlog->next) { opt = mem; @@ -597,7 +596,7 @@ void nfshow_full(Notify *nf) *(opt++) = ' '; *opt = 0; s = (nlog->realname) ? "%s: %s (%s)" : "%s: %s"; - to_user(nf_from,s,mem,nlog->userhost,nlog->realname); + to_user(global_from,s,mem,nlog->userhost,nlog->realname); } } nf_header++; @@ -645,7 +644,7 @@ void do_notify(COMMAND_ARGS) char *opt; int n,flags; - nf_from = from; + global_from = from; flags = nf_header = 0; *message = 0; diff --git a/src/redirect.c b/src/redirect.c deleted file mode 100644 index 6670e18..0000000 --- a/src/redirect.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - - EnergyMech, IRC bot software - Copyright (c) 1997-2018 proton - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ -#define REDIRECT_C -#include "config.h" - -#ifdef REDIRECT - -#include "defines.h" -#include "structs.h" -#include "global.h" -#include "h.h" -#include "text.h" -#include "mcmd.h" - -int begin_redirect(char *from, char *args) -{ - char *pt,*nick; - - if (!args) - return(0); - pt = STRCHR(args,'>'); - if (pt) - { - *pt = 0; - nick = pt+1; - pt--; - while((pt > args) && (*pt == ' ')) - { - *pt = 0; - pt--; - } - while(*nick == ' ') - nick++; - if (*nick) - { -#ifdef DEBUG - debug("(begin_redirect) from %s --> %s\n",from,nick); -#endif /* DEBUG */ - if (ischannel(nick)) - { - if (find_channel_ac(nick)) - { - redirect.to = stringdup(nick); - redirect.method = R_PRIVMSG; - return(0); - } - else - { - to_user(from,ERR_CHAN,nick); - return(-1); - } - } - if (*nick == '>') - { - nick++; - while(*nick == ' ') - nick++; - if (!*nick) - { - to_user(from,"Missing name for redirect."); - return(-1); - } - if (is_safepath(nick,FILE_MAY_EXIST) != FILE_IS_SAFE) // redirect output is appended - { - to_user(from,"Bad filename."); - return(-1); - } - redirect.to = stringdup(nick); - redirect.method = R_FILE; - return(0); - } - if ((pt = find_nuh(nick))) - { - redirect.to = stringdup(nick); - redirect.method = R_NOTICE; - return(0); - } - else - { - to_user(from,TEXT_UNKNOWNUSER,nick); - return(-1); - } - } - else - { - to_user(from,"Bad redirect"); - return(-1); - } - } - return(0); -} - -void send_redirect(char *message) -{ - Strp *new,**pp; - char *fmt; - int fd; - - if (!redirect.to) - return; - - switch(redirect.method) - { - case R_FILE: - if ((fd = open(redirect.to,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) < 0) - return; - fmt = stringcat(message,"\n"); - write(fd,message,(fmt-message)); - close(fd); - return; -#ifdef BOTNET - case R_BOTNET: - { - char tempdata[MAXLEN]; - Mech *backup; - - /* PM */ - sprintf(tempdata,"%i %s %s %s",redirect.guid,redirect.to,current->nick,message); - backup = current; - partyMessage(NULL,tempdata); - current = backup; - } - return; -#endif /* BOTNET */ - case R_NOTICE: - fmt = "NOTICE %s :%s"; - break; - /* case R_PRIVMSG: */ - default: - fmt = "PRIVMSG %s :%s"; - break; - } - - pp = ¤t->sendq; - while(*pp) - pp = &(*pp)->next; - - *pp = new = (Strp*)Calloc(sizeof(Strp) + StrlenX(message,fmt,redirect.to,NULL)); - /* Calloc sets to zero new->next = NULL; */ - sprintf(new->p,fmt,redirect.to,message); -} - -void end_redirect(void) -{ - if (redirect.to) - Free((char**)&redirect.to); -} - -#endif /* REDIRECT */ diff --git a/src/spy.c b/src/spy.c index df02080..43143a7 100644 --- a/src/spy.c +++ b/src/spy.c @@ -28,6 +28,10 @@ #include "text.h" #include "mcmd.h" +#ifdef STATS +#include +#endif + #ifdef DEBUG LS const char SPY_DEFS[][12] = @@ -200,6 +204,278 @@ int spy_source(char *from, int *t_src, const char **src) return(get_useraccess(from,*src)); } +#ifdef REDIRECT + +int begin_redirect(char *from, char *args) +{ + char *pt,*nick; + + if (!args) + return(0); + pt = STRCHR(args,'>'); + if (pt) + { + *pt = 0; + nick = pt+1; + pt--; + while((pt > args) && (*pt == ' ')) + { + *pt = 0; + pt--; + } + while(*nick == ' ') + nick++; + if (*nick) + { +#ifdef DEBUG + debug("(begin_redirect) from %s --> %s\n",from,nick); +#endif /* DEBUG */ + if (ischannel(nick)) + { + if (find_channel_ac(nick)) + { + redirect.to = stringdup(nick); + redirect.method = R_PRIVMSG; + return(0); + } + else + { + to_user(from,ERR_CHAN,nick); + return(-1); + } + } + if (*nick == '>') + { + nick++; + while(*nick == ' ') + nick++; + if (!*nick) + { + to_user(from,"Missing name for redirect."); + return(-1); + } + if (is_safepath(nick,FILE_MAY_EXIST) != FILE_IS_SAFE) // redirect output is appended + { + to_user(from,"Bad filename."); + return(-1); + } + redirect.to = stringdup(nick); + redirect.method = R_FILE; + return(0); + } + if ((pt = find_nuh(nick))) + { + redirect.to = stringdup(nick); + redirect.method = R_NOTICE; + return(0); + } + else + { + to_user(from,TEXT_UNKNOWNUSER,nick); + return(-1); + } + } + else + { + to_user(from,"Bad redirect"); + return(-1); + } + } + return(0); +} + +void send_redirect(char *message) +{ + Strp *new,**pp; + char *fmt; + int fd; + + if (!redirect.to) + return; + + switch(redirect.method) + { + case R_FILE: + if ((fd = open(redirect.to,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) < 0) + return; + fmt = stringcat(message,"\n"); + write(fd,message,(fmt-message)); + close(fd); + return; +#ifdef BOTNET + case R_BOTNET: + { + char tempdata[MAXLEN]; + Mech *backup; + + /* PM */ + sprintf(tempdata,"%i %s %s %s",redirect.guid,redirect.to,current->nick,message); + backup = current; + partyMessage(NULL,tempdata); + current = backup; + } + return; +#endif /* BOTNET */ + case R_NOTICE: + fmt = "NOTICE %s :%s"; + break; + /* case R_PRIVMSG: */ + default: + fmt = "PRIVMSG %s :%s"; + break; + } + + pp = ¤t->sendq; + while(*pp) + pp = &(*pp)->next; + + *pp = new = (Strp*)Calloc(sizeof(Strp) + StrlenX(message,fmt,redirect.to,NULL)); + /* Calloc sets to zero new->next = NULL; */ + sprintf(new->p,fmt,redirect.to,message); +} + +void end_redirect(void) +{ + if (redirect.to) + Free((char**)&redirect.to); +} + +#endif /* REDIRECT */ + +#ifdef URLCAPTURE + +char *urlhost(const char *url) +{ + char copy[strlen(url)]; + const char *end,*beg,*dst; + int n = 0; + + beg = end = url; + while(*end) + { + if (*end == '@') + beg = end+1; + else + if (*end == '/') + { + if (n == 1) + beg = end+1; + else + if (n == 2) + break; + n++; + } + end++; + } + stringcpy_n(copy,beg,(end-beg)); +#ifdef DEBUG + debug("(urlhost) host = %s\n",copy); +#endif +} + +void urlcapture(const char *rest) +{ + Strp *sp,*nx; + char *dest,url[MSGLEN]; + int n; + + dest = url; + while(*rest && *rest != ' ' && dest < url+MSGLEN-1) + *(dest++) = *(rest++); + *dest = 0; + +#ifdef DEBUG + debug("(urlcapture) URL = \"%s\"\n",url); +#endif /* ifdef DEBUG */ + urlhost(url); + + send_spy(SPYSTR_URL,"%s",url); + + if ((n = urlhistmax) < 0) + return; + + prepend_strp(&urlhistory,url); + + for(sp=urlhistory;sp;sp=sp->next) + { + if (n <= 0) + { + purge_strplist(sp->next); + sp->next = NULL; + return; + } + n--; + } +} + +#endif /* ifdef URLCAPTURE */ + +#ifdef STATS + +void stats_loghour(Chan *chan, char *filename, int hour) +{ + ChanStats *stats; + time_t when; + int fd; + + if (!(stats = chan->stats)) + return; + + when = (now - (now % 3600)); + + if ((fd = open(filename,O_WRONLY|O_APPEND|O_CREAT,NEWFILEMODE)) >= 0) + { + stats->userseconds += stats->users * (when - stats->lastuser); + to_file(fd,"H %s %i %i %i %i\n",chan->name,hour, + (stats->flags & CSTAT_PARTIAL) ? -stats->userseconds : stats->userseconds, + stats->userpeak,stats->userlow); + close(fd); + } + stats->LHuserseconds = stats->userseconds; + stats->userseconds = 0; + stats->lastuser = when; + stats->flags = 0; +} + +void stats_plusminususer(Chan *chan, int plusminus) +{ + ChanStats *stats; + ChanUser *cu; + + if (!(stats = chan->stats)) + { + set_mallocdoer(stats_plusminususer); + chan->stats = stats = (ChanStats*)Calloc(sizeof(ChanStats)); /* Calloc sets memory to 0 */ + for(cu=chan->users;cu;cu=cu->next) + stats->users++; + stats->userpeak = stats->users; + stats->userlow = stats->users; + stats->lastuser = now; + stats->flags = CSTAT_PARTIAL; + } + + /* + * add (number of users until now * seconds since last user entered/left) + */ + stats->userseconds += stats->users * (now - stats->lastuser); + + stats->lastuser = now; + stats->users += plusminus; /* can be both negative (-1), zero (0) and positive (+1) */ + + if (stats->userpeak < stats->users) + stats->userpeak = stats->users; + if (stats->userlow > stats->users) + stats->userlow = stats->users; + +#ifdef DEBUG + debug("(stats_plusminususer) %s: %i users, %i userseconds, %i high, %i low; %s (%lu)\n", + chan->name,stats->users,stats->userseconds,stats->userpeak,stats->userlow, + atime(stats->lastuser),stats->lastuser); +#endif /* DEBUG */ +} + +#endif /* ifdef STATS */ + /* * * commands related to spy-pipes @@ -579,3 +855,99 @@ rspy_dest_ok: } spy_typecount(current); } + +#ifdef URLCAPTURE + +/* +help:URLHIST:[max] + +Display a list of URLs seen by the bot in order most recent to oldest. + + [max] Maximum number of URLs to display. +*/ +void do_urlhist(COMMAND_ARGS) +{ + Strp *sp; + char *thenum; + int n,maxnum; + + if (urlhistory == NULL) + { + to_user(from,"No URLs recorded."); + return; + } + + if (!rest || !*rest) + maxnum = urlhistmax; + else + { + thenum = chop(&rest); + maxnum = asc2int(thenum); + } + if ((maxnum < 1) || (maxnum > urlhistmax)) + usage(from); /* usage for CurrentCmd->name */ + + n = 1; + for(sp=urlhistory;sp;sp=sp->next) + { + if (n > maxnum) + break; + to_user(from,"[%i] %s",n,sp->p); + n++; + } +} + +#endif /* URLCAPTURE */ + +#ifdef STATS + +void do_info(COMMAND_ARGS) +{ + ChanStats *stats; + Chan *chan; + char *p; + char text[MSGLEN]; + uint32_t avg; + + if (current->chanlist == NULL) + { + to_user(from,ERR_NOCHANNELS); + return; + } + to_user(from,"\037channel\037 " + "\037average\037 \037peak\037 \037low\037"); + for(chan=current->chanlist;chan;chan=chan->next) + { + *(p = text) = 0; + p = stringcat(p,chan->name); + if (chan == current->activechan) + p = stringcat(p," (current)"); + if ((stats = chan->stats)) + { + if (stats && stats->flags == CSTAT_PARTIAL) + p = stringcat(p," (partial)"); + while(p < text+35) + *(p++) = ' '; + if (stats->LHuserseconds > 0) + { + avg = stats->LHuserseconds / (60*60); + } + else + { + avg = (stats->userpeak + stats->userlow) / 2; + } + sprintf(p,"%-7lu %-4i %i",avg,stats->userpeak,stats->userlow); + to_user(from,FMT_PLAIN,text); + sprintf(text,"Messages: %i Notices: %i Joins: %i Parts: %i Kicks: %i Quits: %i", + stats->privmsg,stats->notice,stats->joins,stats->parts,stats->kicks,stats->quits); + } + else + { + stringcpy(p," (no current data)"); + } + to_user(from,FMT_PLAIN,text); + } +} + +#endif /* STATS */ + diff --git a/src/stats.c b/src/stats.c deleted file mode 100644 index e186222..0000000 --- a/src/stats.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - - EnergyMech, IRC bot software - Copyright (c) 2001-2004 proton - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ -#define STATS_C -#include "config.h" - -#ifdef STATS -#include "defines.h" -#include "structs.h" -#include "global.h" -#include "h.h" -#include "text.h" -#include "mcmd.h" - -#include - -void stats_loghour(Chan *chan, char *filename, int hour) -{ - ChanStats *stats; - time_t when; - int fd; - - if (!(stats = chan->stats)) - return; - - when = (now - (now % 3600)); - - if ((fd = open(filename,O_WRONLY|O_APPEND|O_CREAT,NEWFILEMODE)) >= 0) - { - stats->userseconds += stats->users * (when - stats->lastuser); - to_file(fd,"H %s %i %i %i %i\n",chan->name,hour, - (stats->flags & CSTAT_PARTIAL) ? -stats->userseconds : stats->userseconds, - stats->userpeak,stats->userlow); - close(fd); - } - stats->LHuserseconds = stats->userseconds; - stats->userseconds = 0; - stats->lastuser = when; - stats->flags = 0; -} - -void stats_plusminususer(Chan *chan, int plusminus) -{ - ChanStats *stats; - ChanUser *cu; - - if (!(stats = chan->stats)) - { - set_mallocdoer(stats_plusminususer); - chan->stats = stats = (ChanStats*)Calloc(sizeof(ChanStats)); /* Calloc sets memory to 0 */ - for(cu=chan->users;cu;cu=cu->next) - stats->users++; - stats->userpeak = stats->users; - stats->userlow = stats->users; - stats->lastuser = now; - stats->flags = CSTAT_PARTIAL; - } - - /* - * add (number of users until now * seconds since last user entered/left) - */ - stats->userseconds += stats->users * (now - stats->lastuser); - - stats->lastuser = now; - stats->users += plusminus; /* can be both negative (-1), zero (0) and positive (+1) */ - - if (stats->userpeak < stats->users) - stats->userpeak = stats->users; - if (stats->userlow > stats->users) - stats->userlow = stats->users; - -#ifdef DEBUG - debug("(stats_plusminususer) %s: %i users, %i userseconds, %i high, %i low; %s (%lu)\n", - chan->name,stats->users,stats->userseconds,stats->userpeak,stats->userlow, - atime(stats->lastuser),stats->lastuser); -#endif /* DEBUG */ -} - -void do_info(COMMAND_ARGS) -{ - ChanStats *stats; - Chan *chan; - char *p; - char text[MSGLEN]; - uint32_t avg; - - if (current->chanlist == NULL) - { - to_user(from,ERR_NOCHANNELS); - return; - } - to_user(from,"\037channel\037 " - "\037average\037 \037peak\037 \037low\037"); - for(chan=current->chanlist;chan;chan=chan->next) - { - *(p = text) = 0; - p = stringcat(p,chan->name); - if (chan == current->activechan) - p = stringcat(p," (current)"); - if ((stats = chan->stats)) - { - if (stats && stats->flags == CSTAT_PARTIAL) - p = stringcat(p," (partial)"); - while(p < text+35) - *(p++) = ' '; - if (stats->LHuserseconds > 0) - { - avg = stats->LHuserseconds / (60*60); - } - else - { - avg = (stats->userpeak + stats->userlow) / 2; - } - sprintf(p,"%-7lu %-4i %i",avg,stats->userpeak,stats->userlow); - to_user(from,FMT_PLAIN,text); - sprintf(text,"Messages: %i Notices: %i Joins: %i Parts: %i Kicks: %i Quits: %i", - stats->privmsg,stats->notice,stats->joins,stats->parts,stats->kicks,stats->quits); - } - else - { - stringcpy(p," (no current data)"); - } - to_user(from,FMT_PLAIN,text); - } -} - -#endif /* STATS */ diff --git a/src/toybox.c b/src/toybox.c index f230119..a91137f 100644 --- a/src/toybox.c +++ b/src/toybox.c @@ -157,6 +157,11 @@ int read_bigcharset(char *fname) return(0); } +int read_ascii(char *rest) +{ + to_user_q(global_from,FMT_PLAIN,rest); +} + /* * * @@ -322,13 +327,6 @@ void do_8ball(COMMAND_ARGS) to_user_q(from,FMT_PLAIN,message); } -char *ascii_from; - -int read_ascii(char *rest) -{ - to_user_q(ascii_from,FMT_PLAIN,rest); -} - void do_ascii(COMMAND_ARGS) { char fname[MSGLEN]; @@ -368,8 +366,105 @@ ascii_badfile: goto ascii_badfile; #endif - ascii_from = from; + global_from = from; readline(fd,&read_ascii); /* readline closes fd */ } +/* +help:RAND:[[min[-| ]]max|"nick"|"luser"] + +Tell the user a random number or channel nick. + +Valid forms: + +RAND Number between 1 and 100 (incl. 1 and 100) +RAND 10 Number between 1 and 10 (incl. 1 and 10) +RAND 0 10 Number between 0 and 10 (incl. 0 and 10) +RAND 0-10 Same +RAND nick Random channel non-bot user +RAND luser Random channel user with no bot access + +By default, the bot picks a number between 1 and 100 (incl. 1 and 100) + +If the command ``RAND nick'' is issued in a channel, the bot picks a random channel +user (after eliminating all known bots) and says the nick in the channel. + +If the command ``RAND luser'' is issued in a channel, the bot picks a random channel +user that has no access in the bots userlist and says the nick in the channel. + +*/ +void do_rand(COMMAND_ARGS) +{ + const char *opt; + const ChanUser *cu; + int r,min = 1,max = 100,maxaccess = -1; + + if (!rest && *rest == 0) + goto pick_randnum; + + if (attrtab[(uchar)*rest] & NUM) + { + max = 0; + while(attrtab[(uchar)*rest] & NUM) + max = 10 * max + (*(rest++) - '0'); + if (*rest == '-' || *rest == ' ') + rest++; + if ((attrtab[(uchar)*rest] & NUM) == 0) + goto pick_randnum; + min = max; + max = 0; + while(attrtab[(uchar)*rest] & NUM) + max = 10 * max + (*(rest++) - '0'); + goto pick_randnum; + } + opt = chop(&rest); + if (stringcasecmp(opt,"nick") == 0) + maxaccess = OWNERLEVEL; + if (stringcasecmp(opt,"luser") == 0) + maxaccess = 0; + if (maxaccess >= 0 && CurrentChan) + { + max = 0; + for(cu=CurrentChan->users;cu;cu=cu->next) + { + if (get_useraccess(get_nuh(cu),to) <= maxaccess) + max++; + } + if (max < 2) + { + to_user_q(from,"Unable to pick at random, too few choices"); + return; + } + r = RANDOM(0,max); +#ifdef DEBUG + debug("(do_rand) pick a rand user: max = %i, r = %i\n",max,r); +#endif + max = 0; + for(cu=CurrentChan->users;cu;cu=cu->next) + { + if (get_useraccess(get_nuh(cu),to) <= maxaccess) + { + if (r == max) + { + to_user_q(from,"Random %suser: %s",(maxaccess == 0) ? "l" : "",cu->nick); + return; + } + max++; + } + } + to_user_q(from,"Unable to pick at random..."); + return; + } +pick_randnum: + if (max == 0 || max < min) + max = 100; + if (min < 0 || min > max) + min = 1; + r = RANDOM(min,max); +#ifdef DEBUG + debug("(do_rand) pick a rand number: min = %i, max = %i, r = %i\n",min,max,r); +#endif + to_user_q(from,"Random number: %i",r); +} + #endif /* TOYBOX */ diff --git a/src/urlcap.c b/src/urlcap.c deleted file mode 100644 index 3c69969..0000000 --- a/src/urlcap.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - - EnergyMech, IRC bot software - Copyright (c) 2018 proton - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ -#define URLCAP_C -#include "config.h" - -#ifdef URLCAPTURE - -#include "defines.h" -#include "structs.h" -#include "global.h" -#include "h.h" -#include "text.h" - -char *urlhost(const char *url) -{ - char copy[strlen(url)]; - const char *end,*beg,*dst; - int n = 0; - - beg = end = url; - while(*end) - { - if (*end == '@') - beg = end+1; - else - if (*end == '/') - { - if (n == 1) - beg = end+1; - else - if (n == 2) - break; - n++; - } - end++; - } - stringcpy_n(copy,beg,(end-beg)); -#ifdef DEBUG - debug("(urlhost) host = %s\n",copy); -#endif -} - -void urlcapture(const char *rest) -{ - Strp *sp,*nx; - char *dest,url[MSGLEN]; - int n; - - dest = url; - while(*rest && *rest != ' ' && dest < url+MSGLEN-1) - *(dest++) = *(rest++); - *dest = 0; - -#ifdef DEBUG - debug("(urlcapture) URL = \"%s\"\n",url); -#endif /* ifdef DEBUG */ - urlhost(url); - - send_spy(SPYSTR_URL,"%s",url); - - if ((n = urlhistmax) < 0) - return; - - prepend_strp(&urlhistory,url); - - for(sp=urlhistory;sp;sp=sp->next) - { - if (n <= 0) - { - purge_strplist(sp->next); - sp->next = NULL; - return; - } - n--; - } -} - -/* - * - * Commands associated with URLCAPTURE - * - */ - -/*---Help:URLHIST:[max] - -Display a list of URLs seen by the bot in order most recent to oldest. - - [max] Maximum number of URLs to display. -*/ -void do_urlhist(COMMAND_ARGS) -{ - Strp *sp; - char *thenum; - int n,maxnum; - - if (urlhistory == NULL) - { - to_user(from,"No URLs recorded."); - return; - } - - if (!rest || !*rest) - maxnum = urlhistmax; - else - { - thenum = chop(&rest); - maxnum = asc2int(thenum); - } - if ((maxnum < 1) || (maxnum > urlhistmax)) - usage(from); /* usage for CurrentCmd->name */ - - n = 1; - for(sp=urlhistory;sp;sp=sp->next) - { - if (n > maxnum) - break; - to_user(from,"[%i] %s",n,sp->p); - n++; - } -} - -#endif /* ifdef URLCAPTURE */ diff --git a/src/user.c b/src/user.c index 944a248..b314922 100644 --- a/src/user.c +++ b/src/user.c @@ -1505,11 +1505,15 @@ usage: to_user(from,"Problem adding %s (global mask)",mask); return; } +/* +// With ipv6 and other funky crap, this is no longer suitable + if (matches("*@?*.?*",mask)) { to_user(from,"Problem adding %s (invalid mask)",mask); return; } +*/ #endif /* NEWBIE */ addtouser(&user->mask,mask,TRUE); change++;