diff --git a/.gitignore b/.gitignore index 0a6f77a..386a3cd 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,11 @@ src/safepathtest *~ *.bak -*.passwd +mech.passwd mech.conf +mech.users mech.pid +mech.session root.zone* trick.conf @@ -24,5 +26,4 @@ conf debug* *.log *.stats -*.session -energymech.userfile +github diff --git a/FEATURES b/FEATURES new file mode 100644 index 0000000..5758981 --- /dev/null +++ b/FEATURES @@ -0,0 +1,67 @@ +--- Alias support + + Command substitution + +--- Async DNS support + + Normally energymech uses blocking calls to lookup hostnames. +On bad networks this could cause problems because the whole mech +process will lock up until it gets its answer from the domain name +server. Async DNS support, or RawDNS for short, uses low level code +to do hostname lookups asynchronously. + +--- Botnet support + + Standard botnet functionality. Connect to other bots and share userlists +and other informaton. Partyline extends over the whole botnet. + +--- Channel ban support + + Sometimes ypu want to keep people from certain other channels out of your +own channel. With channel ban enabled, the bot will periodically do WHOIS on +users in your channel and if they are in your rivals channel as well, they can +be kicked or banned, etc. + +--- Command output redirect + + Certain commands like HELP normally require you to DCC chat or telnet to the +bot in order to execute. With command output redirect enabled, you can run +commands and force the output to be sent to a different target, like a nick, +channel or even file. + +--- CTCP + + Standard CTCP replies, VERSION, PING and FINGER. CTCP is not necessary for +DCC chat and DCC file support to operate. + +--- DCC file support + +--- Debug support + + If you have a problem running a mech, debug output could explain whats going on. +Very necessary to include if you are a developer... + +--- Dynamic channel limit (+l) +--- Dynamic command levels support +--- Greet support +--- HTTP server support +--- Host info support +--- IRC proxy support +--- IRCD extensions support +--- Newbie support +--- Note support +--- Notify support +--- Password hashing with MD5 +--- Password hashing with SHA +--- Scripting with Python +--- Scripting with Tcl +--- Seen support +--- Session support +--- Statistics support +--- Telnet support +--- Trivia support +--- Toybox fun and games +--- Uptime support +--- URL capture support +--- WinGate support + diff --git a/Makefile b/Makefile index dc32a4f..278a711 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,8 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -MISCFILES = COPYING CREDITS README README.TCL TODO VERSIONS VERSIONS-1 Makefile configure \ - checkmech sample.conf sample.py sample.tcl sample.userfile default.bigchars +MISCFILES = CREDITS LICENSE README README.TCL TODO VERSIONS VERSIONS-1 Makefile configure \ + checkmech sample.conf sample.py sample.tcl sample.userfile default.bigchars public/README HELPFILES = help/8BALL help/ACCESS help/ALIAS help/AWAY help/BAN help/BANLIST help/BYE \ help/CCHAN help/CHACCESS help/CHANBAN help/CHANNELS help/CHAT help/CLEARSHIT \ @@ -45,23 +45,24 @@ RANDFILES = messages/8ball.txt messages/away.txt messages/insult.txt \ messages/kick.txt messages/nick.txt messages/pickup.txt \ messages/say.txt messages/signoff.txt messages/version.txt -STUBFILES = src/Makefile.in src/config.h.in src/ld/mech.ldscript +STUBFILES = src/Makefile.in src/config.h.in src/ld/README src/ld/elf32-i386 src/ld/elf64-x86-64 -TESTFILES = config/cc.c config/inet_addr.c config/ldtest.c \ +TESTFILES = config/cc.c config/endian.c config/inet_addr.c config/ldtest.c \ config/ptr_size.c config/socket.c config/tcl.c config/which \ config/md5.h config/md5_internal.c config/pw.c \ + config/sha_internal.c config/sha1.h \ config/inet_aton.c config/unaligned.c config/python.c 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/dynamode.c \ - src/function.c src/gencmd.c src/greet.c src/help.c src/irc.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/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/telnet.c src/toybox.c src/trivia.c src/uptime.c src/user.c \ + src/telnet.c src/toybox.c src/trivia.c src/uptime.c src/urlcap.c src/user.c \ src/vars.c src/web.c src/md5/md5.c src/md5/md5.h HDRFILES = src/defines.h src/global.h src/h.h src/settings.h src/structs.h src/text.h src/usage.h @@ -110,7 +111,7 @@ dist: FORCE dist2: FORCE rm -rf /tmp/$(DISTDIR) mkdir /tmp/$(DISTDIR) - tar cf - $(DISTFILES) | ( cd /tmp/$(DISTDIR) ; tar --preserve -xf - ) + tar cf - $(DISTFILES) | ( cd /tmp/$(DISTDIR) ; tar --preserve-permissions -xf - ) cd /tmp ; tar cf - $(DISTDIR) | gzip -9 > $(DISTDIR).tar.gz rm -rf /tmp/$(DISTDIR) chmod 644 /tmp/$(DISTDIR).tar.gz diff --git a/VERSIONS b/VERSIONS index b4265ca..5857583 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,5 +1,11 @@ 3.0.99p4 -- WORK IN PROGRESS (~March, 2018) + * Fixed: If bot guid is changed or deleted in the config, and the bot + is reset, the connection associated with the removed guid + will be cleaned up and closed instead of lingering. + * Added: Support for read only userfiles. If you prefix the filename + with < the file wil never be written to, only ever read. + * Added: Bots now recover Ontime after a reset. * Added: URL capturing with command to display recent URLs seen by the bot. Also spy source "URL" for spy channels. * Fixed: Rewrite of is_safepath() to conform with standard C diff --git a/configure b/configure index 88e6add..0b5c846 100755 --- a/configure +++ b/configure @@ -22,6 +22,9 @@ umask 077 # perl still unsupported has_perl=no +compile=no +install=no +silentopt=no for opt do @@ -242,6 +245,9 @@ do wingate ) ft_wingate=no ;; esac ;; + --compile) compile=yes ;; + --install) install=yes ;; + --silence=options) silentopt=yes ;; --md5=internal) ft_md5=internal ;; --sha=internal) ft_sha=internal ;; --use-cpuflags) cc_arch_opt=yes ;; @@ -300,6 +306,8 @@ Features and packages: --without-FEATURE do not use FEATURE (same as --with-FEATURE=no) --md5=internal Use internal routines for MD5 password hashes instead of system libraries --sha=internal Use internal routines for SHA password hashes instead of system libraries + --use-ofp Try to use compiler flag -fomit-frame-pointer + --no-ofp Do not use compiler flag -fomit-frame-pointer #md5 | ctcp | dccfile | uptime | redirect | greet | perl | dynamode | web \ #note | notify | trivia | toybox | bounce | stats | rawdns | ircd_ext | idwrap | chanban | python ) --with-alias ALIAS support @@ -948,158 +956,163 @@ if [ "$ft_sha" = internal ]; then SHA_O=sha/sha.o fi +out=echo +if [ "$silentopt" == yes ]; then + out=/bin/true +fi + echo -echo "Do you want ..." -echo +$out "Do you want ..." +$out def_alias='#undef ALIAS' unset ans -echo $ac_n "Alias support? ............................. [Y/n] "$ac_c -test "$ft_alias" && echo "$ft_alias" && ans=$ft_alias +$out $ac_n "[STABLE] Alias support? ............................. [Y/n] "$ac_c +test "$ft_alias" && $out "$ft_alias" && ans=$ft_alias test -z "$ft_alias" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_alias='#define ALIAS' -def_toybox='#undef TOYBOX' -unset ans -echo $ac_n "Amusing misc commands (toybox)? ............ [Y/n] "$ac_c -test "$ft_toybox" && echo "$ft_toybox" && ans=$ft_toybox -test -z "$ft_toybox" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_toybox='#define TOYBOX' - def_rawdns='#undef RAWDNS' unset ans -echo $ac_n "Async DNS support? ......................... [y/N] "$ac_c -test "$ft_rawdns" && echo "$ft_rawdns" && ans=$ft_rawdns +$out $ac_n "[ BETA ] Async DNS support? ......................... [y/N] "$ac_c +test "$ft_rawdns" && $out "$ft_rawdns" && ans=$ft_rawdns test -z "$ft_rawdns" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_rawdns='#define RAWDNS' def_botnet='#undef BOTNET' unset ans -echo $ac_n "Botnet support? ............................ [Y/n] "$ac_c -test "$ft_botnet" && echo "$ft_botnet" && ans=$ft_botnet +$out $ac_n "[STABLE] Botnet support? ............................ [Y/n] "$ac_c +test "$ft_botnet" && $out "$ft_botnet" && ans=$ft_botnet test -z "$ft_botnet" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_botnet='#define BOTNET' def_chanban='#undef CHANBAN' unset ans -echo $ac_n "Channel ban support? ....................... [Y/n] "$ac_c -test "$ft_chanban" && echo "$ft_chanban" && ans=$ft_chanban +$out $ac_n "[STABLE] Channel ban support? ....................... [Y/n] "$ac_c +test "$ft_chanban" && $out "$ft_chanban" && ans=$ft_chanban test -z "$ft_chanban" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_chanban='#define CHANBAN' +def_redirect='#undef REDIRECT' +unset ans +$out $ac_n "[STABLE] Command output redirect? ................... [Y/n] "$ac_c +test "$ft_redirect" && $out "$ft_redirect" && ans=$ft_redirect +test -z "$ft_redirect" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_redirect='#define REDIRECT' + def_ctcp='#undef CTCP' unset ans -echo $ac_n "CTCP? ...................................... [Y/n] "$ac_c -test "$ft_ctcp" && echo "$ft_ctcp" && ans=$ft_ctcp +$out $ac_n "[STABLE] CTCP? ...................................... [Y/n] "$ac_c +test "$ft_ctcp" && $out "$ft_ctcp" && ans=$ft_ctcp test -z "$ft_ctcp" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_ctcp='#define CTCP' def_dccfile='#undef DCC_FILE' unset ans -echo $ac_n "DCC file support? .......................... [Y/n] "$ac_c -test "$ft_dccfile" && echo "$ft_dccfile" && ans=$ft_dccfile +$out $ac_n "[STABLE] DCC file support? .......................... [Y/n] "$ac_c +test "$ft_dccfile" && $out "$ft_dccfile" && ans=$ft_dccfile test -z "$ft_dccfile" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_dccfile='#define DCC_FILE' def_debug='#undef DEBUG' unset ans -echo $ac_n "Debug support? ............................. [y/N] "$ac_c -test "$ft_debug" && echo "$ft_debug" && ans=$ft_debug +$out $ac_n "[STABLE] Debug support? ............................. [y/N] "$ac_c +test "$ft_debug" && $out "$ft_debug" && ans=$ft_debug test -z "$ft_debug" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_debug='#define DEBUG' def_dynamode='#undef DYNAMODE' unset ans -echo $ac_n "Dynamic channel limit (+l)? ................ [Y/n] "$ac_c -test "$ft_dynamode" && echo "$ft_dynamode" && ans=$ft_dynamode +$out $ac_n "[STABLE] Dynamic channel limit (+l)? ................ [Y/n] "$ac_c +test "$ft_dynamode" && $out "$ft_dynamode" && ans=$ft_dynamode test -z "$ft_dynamode" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_dynamode='#define DYNAMODE' def_dyncmd='#undef DYNCMD' unset ans -echo $ac_n "Dynamic command levels support? ............ [Y/n] "$ac_c -test "$ft_dyncmd" && echo "$ft_dyncmd" && ans=$ft_dyncmd +$out $ac_n "[STABLE] Dynamic command levels support? ............ [Y/n] "$ac_c +test "$ft_dyncmd" && $out "$ft_dyncmd" && ans=$ft_dyncmd test -z "$ft_dyncmd" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_dyncmd='#define DYNCMD' -def_bounce='#undef BOUNCE' -unset ans -echo $ac_n "IRC proxy support? ......................... [Y/n] "$ac_c -test "$ft_bounce" && echo "$ft_bounce" && ans=$ft_bounce -test -z "$ft_bounce" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_bounce='#define BOUNCE' - -def_ircd_ext='#undef IRCD_EXTENSIONS' -unset ans -echo $ac_n "IRCD extensions support? ................... [Y/n] "$ac_c -test "$ft_ircd_ext" && echo "$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_greet='#undef GREET' unset ans -echo $ac_n "Greet support? ............................. [Y/n] "$ac_c -test "$ft_greet" && echo "$ft_greet" && ans=$ft_greet +$out $ac_n "[STABLE] Greet support? ............................. [Y/n] "$ac_c +test "$ft_greet" && $out "$ft_greet" && ans=$ft_greet test -z "$ft_greet" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_greet='#define GREET' def_web='#undef WEB' unset ans -echo $ac_n "HTTP server support? ....................... [y/N] "$ac_c -test "$ft_web" && echo "$ft_web" && ans=$ft_web +$out $ac_n "[ ALPHA] HTTP server support? ....................... [y/N] "$ac_c +test "$ft_web" && $out "$ft_web" && ans=$ft_web test -z "$ft_web" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_web='#define WEB' +def_hostinfo='#undef HOSTINFO' +unset ans +$out $ac_n "[ BETA ] Host info support? ......................... [Y/n] "$ac_c +test "$ft_hostinfo" && $out "$ft_hostinfo" && ans=$ft_hostinfo +test -z "$ft_hostinfo" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_hostinfo='#define HOSTINFO' + +def_bounce='#undef BOUNCE' +unset ans +$out $ac_n "[STABLE] IRC proxy support? ......................... [Y/n] "$ac_c +test "$ft_bounce" && $out "$ft_bounce" && ans=$ft_bounce +test -z "$ft_bounce" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_bounce='#define BOUNCE' + +def_ircd_ext='#undef IRCD_EXTENSIONS' +unset ans +$out $ac_n "[ BETA ] IRCD extensions support? ................... [Y/n] "$ac_c +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_newbie='#undef NEWBIE' +unset ans +$out $ac_n "[STABLE] Newbie support? ............................ [Y/n] "$ac_c +test "$ft_newbie" && $out "$ft_newbie" && ans=$ft_newbie +test -z "$ft_newbie" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_newbie='#define NEWBIE' + +def_note='#undef NOTE' +unset ans +$out $ac_n "[STABLE] Note support? .............................. [Y/n] "$ac_c +test "$ft_note" && $out "$ft_note" && ans=$ft_note +test -z "$ft_note" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_note='#define NOTE' + +def_notify='#undef NOTIFY' +unset ans +$out $ac_n "[STABLE] Notify support? ............................ [Y/n] "$ac_c +test "$ft_notify" && $out "$ft_notify" && ans=$ft_notify +test -z "$ft_notify" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_notify='#define NOTIFY' + def_md5='#undef MD5CRYPT' unset ans -echo $ac_n "MD5 password support? ...................... [Y/n] "$ac_c +$out $ac_n "[STABLE] Password hashing with MD5? (less secure) ... [Y/n] "$ac_c if [ "$has_md5" = no ]; then - echo 'no (unsupported)' + $out 'no (unsupported)' else - test "$ft_md5" && echo "$ft_md5" && ans=$ft_md5 + test "$ft_md5" && $out "$ft_md5" && ans=$ft_md5 test -z "$ft_md5" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes -o "$ans" = internal && def_md5='#define MD5CRYPT' fi def_sha='#undef SHACRYPT' unset ans -echo $ac_n "SHA password support? ...................... [Y/n] "$ac_c +$out $ac_n "[ BETA ] Password hashing with SHA? (best) .......... [Y/n] "$ac_c if [ "$has_sha" = no ]; then - echo 'no (unsupported)' + $out 'no (unsupported)' else - test "$ft_sha" && echo "$ft_sha" && ans=$ft_sha + test "$ft_sha" && $out "$ft_sha" && ans=$ft_sha test -z "$ft_sha" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes -o "$ans" = internal && def_sha='#define SHACRYPT' fi -def_hostinfo='#undef HOSTINFO' -unset ans -echo $ac_n "Host info support? ......................... [Y/n] "$ac_c -test "$ft_hostinfo" && echo "$ft_hostinfo" && ans=$ft_hostinfo -test -z "$ft_hostinfo" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_hostinfo='#define HOSTINFO' - -def_newbie='#undef NEWBIE' -unset ans -echo $ac_n "Newbie support? ............................ [Y/n] "$ac_c -test "$ft_newbie" && echo "$ft_newbie" && ans=$ft_newbie -test -z "$ft_newbie" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_newbie='#define NEWBIE' - -def_note='#undef NOTE' -unset ans -echo $ac_n "Note support? .............................. [Y/n] "$ac_c -test "$ft_note" && echo "$ft_note" && ans=$ft_note -test -z "$ft_note" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_note='#define NOTE' - -def_notify='#undef NOTIFY' -unset ans -echo $ac_n "Notify support? ............................ [Y/n] "$ac_c -test "$ft_notify" && echo "$ft_notify" && ans=$ft_notify -test -z "$ft_notify" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_notify='#define NOTIFY' - # # perl support not yet functional (2009-05-11) # @@ -1114,20 +1127,13 @@ def_perl='#undef PERL' # test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_perl='#define PERL' # fi -def_redirect='#undef REDIRECT' -unset ans -echo $ac_n "Command output redirect? ................... [Y/n] "$ac_c -test "$ft_redirect" && echo "$ft_redirect" && ans=$ft_redirect -test -z "$ft_redirect" && read ans -test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_redirect='#define REDIRECT' - def_python='#undef PYTHON' unset ans -echo $ac_n "Scripting support (Python)? ................ [y/N] "$ac_c +$out $ac_n "[ BETA ] Scripting with Python? ..................... [y/N] "$ac_c if [ "$has_python" = no ]; then - echo 'no (unsupported)' + $out 'no (unsupported)' else - test "$ft_python" && echo "$ft_python" && ans=$ft_python + test "$ft_python" && $out "$ft_python" && ans=$ft_python test -z "$ft_python" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_python='#define PYTHON' fi @@ -1138,11 +1144,11 @@ fi def_tcl='#undef TCL' unset ans -echo $ac_n "Scripting support (Tcl)? ................... [y/N] "$ac_c +$out $ac_n "[ BETA ] Scripting with Tcl? ........................ [y/N] "$ac_c if [ "$has_tcl" = no ]; then - echo 'no (unsupported)' + $out 'no (unsupported)' else - test "$ft_tcl" && echo "$ft_tcl" && ans=$ft_tcl + test "$ft_tcl" && $out "$ft_tcl" && ans=$ft_tcl test -z "$ft_tcl" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_tcl='#define TCL' fi @@ -1153,61 +1159,68 @@ fi def_seen='#undef SEEN' unset ans -echo $ac_n "Seen support? .............................. [y/N] "$ac_c -test "$ft_seen" && echo "$ft_seen" && ans=$ft_seen +$out $ac_n "[STABLE] Seen support? .............................. [y/N] "$ac_c +test "$ft_seen" && $out "$ft_seen" && ans=$ft_seen test -z "$ft_seen" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_seen='#define SEEN' def_session='#undef SESSION' unset ans -echo $ac_n "Session support? ........................... [Y/n] "$ac_c -test "$ft_session" && echo "$ft_session" && ans=$ft_session +$out $ac_n "[STABLE] Session support? ........................... [Y/n] "$ac_c +test "$ft_session" && $out "$ft_session" && ans=$ft_session test -z "$ft_session" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_session='#define SESSION' def_stats='#undef STATS' unset ans -echo $ac_n "Statistics support? ........................ [Y/n] "$ac_c -test "$ft_stats" && echo "$ft_stats" && ans=$ft_stats +$out $ac_n "[STABLE] Statistics support? ........................ [Y/n] "$ac_c +test "$ft_stats" && $out "$ft_stats" && ans=$ft_stats test -z "$ft_stats" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_stats='#define STATS' def_telnet='#undef TELNET' unset ans -echo $ac_n "Telnet support? ............................ [Y/n] "$ac_c -test "$ft_telnet" && echo "$ft_telnet" && ans=$ft_telnet +$out $ac_n "[STABLE] Telnet support? ............................ [Y/n] "$ac_c +test "$ft_telnet" && $out "$ft_telnet" && ans=$ft_telnet test -z "$ft_telnet" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_telnet='#define TELNET' def_trivia='#undef TRIVIA' unset ans -echo $ac_n "Trivia support? ............................ [y/N] "$ac_c -test "$ft_trivia" && echo "$ft_trivia" && ans=$ft_trivia +$out $ac_n "[STABLE] Trivia support? ............................ [y/N] "$ac_c +test "$ft_trivia" && $out "$ft_trivia" && ans=$ft_trivia test -z "$ft_trivia" && read ans test "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_trivia='#define TRIVIA' +def_toybox='#undef TOYBOX' +unset ans +$out $ac_n "[STABLE] Toybox fun and games? ...................... [Y/n] "$ac_c +test "$ft_toybox" && $out "$ft_toybox" && ans=$ft_toybox +test -z "$ft_toybox" && read ans +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_toybox='#define TOYBOX' + def_uptime='#undef UPTIME' unset ans -echo $ac_n "Uptime support? ............................ [Y/n] "$ac_c -test "$ft_uptime" && echo "$ft_uptime" && ans=$ft_uptime +$out $ac_n "[STABLE] Uptime support? ............................ [Y/n] "$ac_c +test "$ft_uptime" && $out "$ft_uptime" && ans=$ft_uptime test -z "$ft_uptime" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_uptime='#define UPTIME' def_urlcapture='#undef URLCAPTURE' unset ans -echo $ac_n "URL capture support? ....................... [Y/n] "$ac_c -test "$ft_urlcapture" && echo "$ft_urlcapture" && ans=$ft_urlcapture +$out $ac_n "[ BETA ] URL capture support? ....................... [Y/n] "$ac_c +test "$ft_urlcapture" && $out "$ft_urlcapture" && ans=$ft_urlcapture test -z "$ft_urlcapture" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_urlcapture='#define URLCAPTURE' def_wingate='#undef WINGATE' unset ans -echo $ac_n "WinGate support? ........................... [Y/n] "$ac_c -test "$ft_wingate" && echo "$ft_wingate" && ans=$ft_wingate +$out $ac_n "[STABLE] WinGate support? ........................... [Y/n] "$ac_c +test "$ft_wingate" && $out "$ft_wingate" && ans=$ft_wingate test -z "$ft_wingate" && read ans test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_wingate='#define WINGATE' -echo '' +$out '' echo "Creating src/Makefile" O_FLAGS="$cc_optimize_flag $cc_arch_flag $cc_march_flag $cc_ofp_flag" @@ -1295,6 +1308,16 @@ s|@PTSIZE_DEFINE64@|$PTSIZE_DEFINE64|; s|@UNALIGNED_MEM@|$UNALIGNED_MEM|; " < src/config.h.in >> src/config.h +if [ "$install" == "yes" ]; then + make -C src energymech + exit +fi + +if [ "$compile" == "yes" ]; then + make -C src energymech + exit +fi + echo '' echo 'All done. You can now "make clean install"' echo '' diff --git a/help/SPY b/help/SPY index 94fd002..56d062b 100644 --- a/help/SPY +++ b/help/SPY @@ -17,6 +17,6 @@ excess flood if not careful. (none) Send output to you (default). channel Send output to the specified channel. >file Send output to file. Lines are appended to the end of the file. - This file needs to exist before logging to it. + If the file does not exist, it is created. See also: rspy diff --git a/sample.userfile b/sample.userfile index 2124064..cb8742a 100644 --- a/sample.userfile +++ b/sample.userfile @@ -1,4 +1,5 @@ user example mask *!*@*.example.com chan * -opt u100 +opt p0u100 +pass ___absolutely_do_not_use_this_file___ diff --git a/src/Makefile.in b/src/Makefile.in index 3f45bb6..d053243 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -121,6 +121,9 @@ aliastest: alias.c safepathtest: function.c $(CROSS_COMPILE)$(CC) $(CFLAGS) -o safepathtest $< $(LPROF) $(LIBS) $(LDSCRIPT) -DTEST +commands: + grep -E '(void do_.*\(COMMAND_ARGS\)|/*---Help:)' *c + # # # diff --git a/src/alias.c b/src/alias.c index 9cc78bb..50d5192 100644 --- a/src/alias.c +++ b/src/alias.c @@ -249,6 +249,9 @@ void do_alias(COMMAND_ARGS) set_mallocdoer(do_alias); alias->format = Strdup(rest); to_user(from,"Replaced alias: %s --> %s",cmd,rest); +#ifdef DEBUG + debug("(do_alias) Replaced alias: %s --> %s\n",cmd,rest); +#endif return; } } @@ -260,6 +263,9 @@ void do_alias(COMMAND_ARGS) alias->next = aliaslist; aliaslist = alias; to_user(from,"Added alias: %s --> %s",cmd,rest); +#ifdef DEBUG + debug("(do_alias) Added alias: %s --> %s\n",cmd,rest); +#endif } void do_unalias(COMMAND_ARGS) diff --git a/src/auth.c b/src/auth.c index a2a914d..0da7092 100644 --- a/src/auth.c +++ b/src/auth.c @@ -417,8 +417,9 @@ int make_auth(const char *userhost, const User *user) * */ -/* - * Usage: VERIFY +/*---Help:AUTH: + */ +/*---Help:VERIFY: */ void do_auth(COMMAND_ARGS) { diff --git a/src/channel.c b/src/channel.c index 77e95d2..098a022 100644 --- a/src/channel.c +++ b/src/channel.c @@ -58,7 +58,7 @@ void check_idlekick(void) } } -__attr (CORE_SEG, regparm(2)) +__attr(CORE_SEG, __regparm(2)) Chan *find_channel(const char *name, int anychannel) { Chan *chan; @@ -625,7 +625,7 @@ void remove_chanuser(Chan *chan, char *nick) /* * Requires CurrentChan to be set properly */ -__attr(CORE_SEG, __regparm (2) ) +__attr(CORE_SEG, __regparm(2)) void make_chanuser(char *nick, char *userhost) { ChanUser *new; diff --git a/src/core.c b/src/core.c index d9ff40f..24f72bf 100644 --- a/src/core.c +++ b/src/core.c @@ -864,7 +864,44 @@ typedef struct } HookTimer; + //using that struct, calculate when the next time will be + //start by determining what the time is now + + thistime = now; + + //which second is it + thissecond = thistime % 60; + + if (ht->second1 == 0x3FFFFFFF && ht->second2 == 0x3FFFFFFF) + { + // dont add waiting period to get to the proper second + } + + //which minute is it + thistime = (thistime - thissecond) / 60; + thisminute = thistime % 60; + if (ht->minute1 == 0x3FFFFFFF && ht->minute2 == 0x3FFFFFFF) + { + // dont add waiting period to get to the proper minute + } + + //which hour is it + thistime = (thistime - thisminute) / 60; + thishour = thistime % 24; + if (ht->hour == 0xFFFFFF) + { + // dont add waiting period to get to the proper hour + } + + //which weekday is it + thistime = (thistime - thishour) / 60; //thistime is now = day since epoch + if (ht->weekday == 0x7F) // every day + { + // dont add waiting period to get to the correct day + } + #endif /* 0 */ + /* * return -1 on failure */ diff --git a/src/debug.c b/src/debug.c index 43966d2..9274994 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2009 proton + 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 @@ -42,19 +42,49 @@ LS const struct } StructList[] = { +{ "aME\t", sizeof(aME) }, // for memory allocation debugging +{ "aMEA", sizeof(aMEA) }, +#ifdef ALIAS +{ "Alias", sizeof(Alias) }, +#endif /* ALIAS */ { "Auth", sizeof(Auth) }, { "Ban\t", sizeof(Ban) }, +#ifdef BOTNET +{ "BotInfo", sizeof(BotInfo) }, +{ "BotNet", sizeof(BotNet) }, +#endif { "Chan", sizeof(Chan) }, { "ChanStats", sizeof(ChanStats) }, { "ChanUser", sizeof(ChanUser) }, { "Client", sizeof(Client) }, +{ "ShortClient", sizeof(ShortClient) }, +#ifdef RAWDNS +{ "dnsAuthority", sizeof(dnsAuthority) }, +{ "dnsList", sizeof(dnsList) }, +{ "dnsQuery", sizeof(dnsQuery) }, +#endif +#ifdef SCRIPTING +{ "Hook", sizeof(Hook) }, +{ "HookTimer", sizeof(HookTimer) }, +#endif { "ircLink", sizeof(ircLink) }, { "IReq", sizeof(IReq) }, +{ "KickSay", sizeof(KickSay) }, { "KillSock", sizeof(KillSock) }, { "Mech", sizeof(Mech) }, +#ifdef BOTNET +{ "NetCfg", sizeof(NetCfg) }, +#endif +#ifdef NOTE +{ "Note", sizeof(Note) }, +#endif /* NOTE */ #ifdef NOTIFY +{ "nfLog", sizeof(nfLog) }, { "Notify", sizeof(Notify) }, #endif /* NOTIFY */ +{ "OnMsg", sizeof(OnMsg) }, +{ "qKick", sizeof(qKick) }, +{ "qMode", sizeof(qMode) }, #ifdef SEEN { "Seen", sizeof(Seen) }, #endif /* SEEN */ @@ -62,15 +92,20 @@ LS const struct { "ServerGroup", sizeof(ServerGroup) }, { "Setting", sizeof(Setting) }, { "Shit", sizeof(Shit) }, +{ "Spy\t", sizeof(Spy) }, { "Strp", sizeof(Strp) }, #ifdef TRIVIA { "TrivScore", sizeof(TrivScore) }, #endif /* TRIVIA */ +{ "UniVar", sizeof(UniVar) }, { "User", sizeof(User) }, -{ "OnMsg", sizeof(OnMsg) }, -{ "Spy\t", sizeof(Spy) }, +#ifdef WEB +{ "WebDoc", sizeof(WebDoc) }, +{ "WebSock", sizeof(WebSock) }, +#endif { NULL, }}; + LS struct { void *func; diff --git a/src/defines.h b/src/defines.h index 379d436..6d44f78 100644 --- a/src/defines.h +++ b/src/defines.h @@ -367,6 +367,14 @@ enum { /* check_mass() */ +#define INDEX_FLOOD 0 +#define INDEX_BAN 1 +#define INDEX_DEOP 2 +#define INDEX_KICK 3 +#define INDEX_NICK 4 +#define INDEX_CAPS 5 +#define INDEX_MAX 6 + #define CHK_CAPS 0 #define CHK_PUB 1 #define CHK_PUBLIC CHK_PUB diff --git a/src/gencmd.c b/src/gencmd.c index 4f4dd71..4e13fc4 100644 --- a/src/gencmd.c +++ b/src/gencmd.c @@ -58,7 +58,8 @@ struct /* * public access commands */ - { 0, "VERIFY", "do_auth", 0 | NOPUB }, + { 0, "AUTH", "do_auth", 0 | NOPUB | CBANG }, // double up on AUTH/VERIFY to better + { 0, "VERIFY", "do_auth", 0 | NOPUB | CBANG }, // catch login attempts #ifdef TOYBOX { 0, "8BALL", "do_8ball", 0 | CBANG }, #endif /* TOYBOX */ diff --git a/src/h.h b/src/h.h index f9fcb08..c85fa13 100644 --- a/src/h.h +++ b/src/h.h @@ -106,6 +106,9 @@ } #endif /* DEBUG */ +LS int makecrc(const char *); +LS void send_supress(const char *, const char *); +LS void netchanSupress(BotNet *, char *); LS Chan *find_channel(const char *, int) __attr(CORE_SEG, __regparm (2) ); LS Chan *find_channel_ac(const char *) __attr(CORE_SEG, __regparm (1) ); diff --git a/src/hostinfo.c b/src/hostinfo.c index 0a0acb2..c58c6b2 100644 --- a/src/hostinfo.c +++ b/src/hostinfo.c @@ -42,7 +42,7 @@ void do_hostinfo(COMMAND_ARGS) struct utsname un; if (uname(&un) == 0) - to_user(from,"%s %s %s",un.sysname,un.release,un.machine); + to_user_q(from,"%s %s %s",un.sysname,un.release,un.machine); } char vmpeak[32]; @@ -128,7 +128,7 @@ void do_meminfo(COMMAND_ARGS) return; readline(fd,&parse_proc_status); // readline closes fd - to_user(from,"VM %s (Max %s), RSS %s [ Code %s, Data %s, Libs %s, Stack %s ]", + to_user_q(from,"VM %s (Max %s), RSS %s [ Code %s, Data %s, Libs %s, Stack %s ]", vmsize,vmpeak,vmrss,vmexe,vmdata,vmlib,vmstk); } diff --git a/src/main.c b/src/main.c index a4d8fc4..2155212 100644 --- a/src/main.c +++ b/src/main.c @@ -795,6 +795,10 @@ int main(int argc, char **argv, char **envp) /* * Code to detect and recover after a RESET */ +/* +execve( ./energymech, argv = { ./energymech }, envp = { MECHRESET=d3 f1881:2:X12 } ) +(recover_debug) debug fd recovered +*/ while(*envp) { char *p1; @@ -812,6 +816,9 @@ int main(int argc, char **argv, char **envp) if (*p2 == 0) { mechresetenv = p1; + do_fork = FALSE; + if (*p1 == 'd') + mechresetenv = recover_debug(p1+1); break; } envp++; @@ -1003,7 +1010,7 @@ int main(int argc, char **argv, char **envp) if (!mechresetenv) to_file(1,INFO_RUNNING); - if (!mechresetenv && do_fork) + if (do_fork) { close(0); close(1); diff --git a/src/net.c b/src/net.c index 2d690de..de732b9 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2009 proton + 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 @@ -78,6 +78,7 @@ LS const LinkCmd basicProto[] = { 'B', 'L', basicLink }, { 'B', 'Q', basicQuit }, { 'C', 'O', netchanNeedop }, +{ 'C', 'S', netchanSupress }, // experimental command supression { 'P', 'A', partyAuth }, #ifdef REDIRECT { 'P', 'C', partyCommand }, @@ -97,7 +98,7 @@ LS int deadlinks = FALSE; * */ -Mech *get_netbot(void) +Mech *get_netbot(void) //get local bot with the lowes guid to act as local master { Mech *netbot,*bot; int uid; diff --git a/src/net_chan.c b/src/net_chan.c index 7e5bf19..c4074d9 100644 --- a/src/net_chan.c +++ b/src/net_chan.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2004 proton + 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 @@ -30,6 +30,36 @@ #include "text.h" #include "mcmd.h" +int makecrc(const char *args) +{ + int crc = 0; + + while(*args) + { + crc += ((12345 * *args) % 321) + 4567; + args++; + } + + return(crc); +} + +void send_supress(const char *command, const char *args) +{ + Mech *backup; + int crc; + + crc = makecrc(args); + for(backup=botlist;backup;backup=backup->next) + { + if (backup != current) + { + backup->supres_cmd = command; + backup->supres_crc = crc; + } + } + botnet_relay(NULL,"CS%s %i\n",command,crc); +} + ChanUser *find_chanbot(Chan *chan, char *nick) { ChanUser *cu; @@ -141,4 +171,39 @@ void netchanNeedop(BotNet *source, char *rest) } } +void netchanSupress(BotNet *source, char *rest) +{ + Mech *backup; + const char *cmd; + int crc,i,j; + + botnet_relay(source,"CS%s\n",rest); + + cmd = chop(&rest); + + // convert command to const command + for(i=0;mcmd[i].name;i++) + { + j = Strcasecmp(mcmd[i].name,cmd); + if (j < 0) + continue; + if (j > 0) + return; + cmd = mcmd[i].name; + break; + } + + if (mcmd[i].name == NULL) + return; + + crc = a2i(rest); + + // to all local bots + for(backup=botlist;backup;backup=backup->next) + { + backup->supres_cmd = cmd; + backup->supres_crc = crc; + } +} + #endif /* BOTNET */ diff --git a/src/ons.c b/src/ons.c index 89cb8e8..2fc5ae7 100644 --- a/src/ons.c +++ b/src/ons.c @@ -325,15 +325,15 @@ void on_nick(char *from, char *newnick) if ((maxcount = chan->setting[INT_NCL].int_var) < 2) continue; - if ((now - cu->nicktime) > NICKFLOODTIME) + if ((now - cu->action_time[INDEX_NICK]) > NICKFLOODTIME) { - cu->nicktime = now + (NICKFLOODTIME / (maxcount - 1)); - cu->nicknum = 1; + cu->action_time[INDEX_NICK] = now + (NICKFLOODTIME / (maxcount - 1)); + cu->action_num[INDEX_NICK] = 1; } else { - cu->nicktime += (NICKFLOODTIME / (maxcount - 1)); - if (++cu->nicknum >= maxcount) + cu->action_time[INDEX_NICK] += (NICKFLOODTIME / (maxcount - 1)); + if (++cu->action_num[INDEX_NICK] >= maxcount) { deop_ban(chan,cu,NULL); send_kick(chan,newnick,KICK_NICKFLOOD); @@ -342,7 +342,7 @@ void on_nick(char *from, char *newnick) } } -void on_msg(char *from, char *to, char *msg) +void on_msg(char *from, char *to, char *rest) { #ifdef SCRIPTING Hook *hook; @@ -368,7 +368,7 @@ void on_msg(char *from, char *to, char *msg) */ #ifdef NOTE - if (notelist && catch_note(from,to,msg)) + if (notelist && catch_note(from,to,rest)) return; #endif /* NOTE */ @@ -378,7 +378,7 @@ void on_msg(char *from, char *to, char *msg) */ if (CurrentChan && !CurrentChan->setting[TOG_PUB].int_var) { - common_public(CurrentChan,from,"<%s> %s",msg); + common_public(CurrentChan,from,"<%s> %s",rest); return; } @@ -398,7 +398,7 @@ void on_msg(char *from, char *to, char *msg) /* * remember where the string started */ - origstart = msg; + origstart = rest; if (from == CoreUser.name) { @@ -412,7 +412,7 @@ void on_msg(char *from, char *to, char *msg) /* * check for command bots nick replacing command char */ - if ((p2 = (uchar*)(command = chop(&msg))) == NULL) + if ((p2 = (uchar*)(command = chop(&rest))) == NULL) return; p1 = (uchar*)current->nick; @@ -421,7 +421,7 @@ void on_msg(char *from, char *to, char *msg) if (!i || ((p2 > (uchar*)command) && (*p2 == ':' || *p2 == ';' || *p2 == ',') && p2[1] == 0)) { - if ((command = chop(&msg)) == NULL) + if ((command = chop(&rest)) == NULL) return; has_cc = TRUE; } @@ -449,13 +449,13 @@ recheck_alias: { if (!Strcasecmp(alias->alias,command)) { - unchop(command,msg); + unchop(command,rest); afmt(amem,alias->format,command); #ifdef DEBUG debug("(on_msg) [ALIAS] %s --> %s\n",command,amem); #endif /* DEBUG */ - msg = amem; - pt = chop(&msg); + rest = amem; + pt = chop(&rest); i = Strcasecmp(pt,command); command = pt; arec++; @@ -483,7 +483,7 @@ recheck_alias: */ if (hook->flags == HOOK_COMMAND && !Strcasecmp(command,hook->type.command)) { - if (hook->func(from,msg,hook)) + if (hook->func(from,rest,hook)) /* if the hook returns non-zero, the input should not be parsed internally */ i = 1; } @@ -518,8 +518,34 @@ recheck_alias: #endif /* DEBUG */ return; } + CurrentCmd = &mcmd[i]; +#ifdef BOTNET + // experimental command supression + if (CurrentCmd->name == current->supres_cmd) + { + int crc; + + crc = makecrc(rest); + if (current->supres_crc == crc) + { + // another bot has already executed this command and is trying to supress its execution on other bots + current->supres_cmd = NULL; + current->supres_crc = 0; +#ifdef DEBUG + debug("(on_msg) command \"%s\" from %s was supressed\n",CurrentCmd->name,CurrentNick); +#endif + return; + } + } + //if command should be supressed ... + if (CurrentChan) + { + send_supress(CurrentCmd->name,rest); + } +#endif + /* * convert the command to uppercase */ @@ -566,7 +592,7 @@ recheck_alias: if (mcmd[i].caxs) { /* get channel name; 1: msg, 2: to, 3: active channel */ - to = get_channel(to,&msg); + to = get_channel(to,&rest); if (!ischannel(to)) return; uaccess = get_authaccess(from,to); @@ -593,7 +619,7 @@ recheck_alias: /* * CARGS check: at least one argument is required */ - if (mcmd[i].args && !*msg) + if (mcmd[i].args && !*rest) { if (uaccess) usage_command(from,command); return; @@ -611,7 +637,7 @@ recheck_alias: redirect.method = R_PRIVMSG; } else - if (begin_redirect(from,msg) < 0) + if (begin_redirect(from,rest) < 0) return; } #endif /* REDIRECT */ @@ -619,7 +645,7 @@ recheck_alias: if (mcmd[i].dcc && dcc_only_command(from)) return; - mcmd[i].func(from,to,msg,acmd[i]); + mcmd[i].func(from,to,rest,acmd[i]); #ifdef DEBUG CurrentCmd = NULL; @@ -637,7 +663,7 @@ recheck_alias: /* * un-chop() the message string */ - unchop(origstart,msg); + unchop(origstart,rest); if (CurrentChan) { diff --git a/src/parse.c b/src/parse.c index bb92dd2..cc60f50 100644 --- a/src/parse.c +++ b/src/parse.c @@ -350,6 +350,28 @@ void parse_ping(char *from, char *rest) to_server("PONG :%s\n",rest); } +void parse_pong(char *from, char *rest) +{ + time_t ot; + char *src; + +#ifdef DEBUG + debug("(parse_pong) rest == %s\n",rest); +#endif + + if (rest[0] == ':' && rest[1] == 'O' && rest[2] == 'T') + { + ot = 0; + src = &rest[3]; + while(attrtab[(uchar)*src] & NUM) + ot = (ot * 10) + (*src++ - '0'); + current->ontime = ot; +#ifdef DEBUG + debug("(parse_pong) recovering ontime = %lu (%s)\n",ot,idle2str(now - ot,TRUE)); +#endif + } +} + void parse_privmsg(char *from, char *rest) { ChanUser *cu; @@ -1366,6 +1388,7 @@ LS const struct { 0x4E49434B, NEEDFROM, on_nick }, /* NICK */ { 0x4B49434B, NEEDFROM, on_kick }, /* KICK */ { 0x50494E47, 0, parse_ping }, /* PING */ + { 0x504F4E47, DROPONE, parse_pong }, /* PONG */ { 0x544F5049, NEEDFROM, parse_topic }, /* TOPIC */ { 0x4E4F5449, NEEDFROM, parse_notice }, /* NOTICE */ { 0x51554954, NEEDFROM, parse_quit }, /* QUIT */ @@ -1497,12 +1520,13 @@ void parseline(char *rest) cmdhash = 0; } } - if (!cmdhash) + if (cmdhash == 0) return; #endif /* SCRIPTING */ cmdhash = stringhash(command); + //debug("cmdhash = %08X\n",cmdhash); for(i=0;pFuncs[i].hash;i++) { if (cmdhash == pFuncs[i].hash) @@ -1510,9 +1534,26 @@ void parseline(char *rest) if ((pFuncs[i].flags & NEEDFROM) && !from) return; if (pFuncs[i].flags & DROPONE) - chop(&rest); /* discard bot nick */ + chop(&rest); /* discard one argument (usually bot nick) */ pFuncs[i].func(from,rest); return; } } + //debug("unmatched cmdhash %08X\n",cmdhash); } + +/* + +(in) {2} :weber.freenode.net PONG weber.freenode.net :OT1521044136 +cmdhash = 504F4E47 +unmatched cmdhash 504F4E47 + +(in) {2} :weber.freenode.net 347 jooboy #amdx :End of Channel Invite List +cmdhash = 00333437 +unmatched cmdhash 00333437 + +(in) {2} :weber.freenode.net 349 jooboy #amdx :End of Channel Exception List +cmdhash = 00333439 +unmatched cmdhash 00333439 + +*/ diff --git a/src/prot.c b/src/prot.c index 9134e87..ff0f2df 100644 --- a/src/prot.c +++ b/src/prot.c @@ -277,11 +277,11 @@ void update_modes(Chan *chan) */ int check_mass(Chan *chan, ChanUser *doer, int type) { - time_t *when; - int *num,limit; + time_t when; + int num,limit; /* - * must handle servers ... + * must handle servers ... (netsplits, chanserv, nickserv, ...) */ if (!doer) return(FALSE); @@ -300,38 +300,37 @@ int check_mass(Chan *chan, ChanUser *doer, int type) */ //case CHK_CAPS: case INT_CKL: - num = &doer->capsnum; + num = INDEX_CAPS; break; //case CHK_PUB: case INT_FL: - num = &doer->floodnum; + num = INDEX_FLOOD; break; /* * three things we dont want channel ops to do */ //case CHK_DEOP: case INT_MDL: - num = &doer->deopnum; + num = INDEX_DEOP; break; //case CHK_BAN: case INT_MBL: - num = &doer->bannum; + num = INDEX_BAN; break; default: /* case CHK_KICK: */ /* case INT_MKL: */ - num = &doer->kicknum; + num = INDEX_KICK; break; } - when = (time_t*)&num[1]; - if ((now - *when) > 10) + if ((now - doer->action_time[num]) > 10) { - *when = now; - *num = 0; + doer->action_time[num] = now; + doer->action_num[num] = 0; } - ++(*num); - if (*num >= limit && limit) + ++(doer->action_num[num]); + if (doer->action_num[num] >= limit && limit) return(TRUE); return(FALSE); } diff --git a/src/reset.c b/src/reset.c index 1888bd3..6006fa2 100644 --- a/src/reset.c +++ b/src/reset.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2008 proton + 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 @@ -105,6 +105,7 @@ char *recover_client(char *env) } } close(fd); + killsock(fd); return(p); found_user: @@ -183,6 +184,8 @@ char *recover_debug(char *env) #endif /* DEBUG */ +//execve( ./energymech, argv = { ./energymech }, envp = { MECHRESET=d3 f1881:2:X12 f99:4:X12 } ) + char *recover_server(char *env) { struct sockaddr_in sai; @@ -268,9 +271,17 @@ char *recover_server(char *env) debug("(recover_server) {%i} server socket recovered\n",fd); #endif /* DEBUG */ to_file(fd,"LUSERS\n"); + fd = -1; break; } } + // if we recover a guid:socket without a matching bot in config, it got removed or changed guid + // if the guid changed, we cant guess which old<-->new is the matching one so + if (fd != -1) + { + to_file(fd,"QUIT :I'm no longer wanted *cry*\n"); + killsock(fd); + } return(p); } @@ -376,22 +387,24 @@ void do_reset(COMMAND_ARGS) /* * Save server connections */ - for(backup=botlist;backup;backup=backup->next) + backup = current; + for(current=botlist;current;current=current->next) { - if ((backup->connect == CN_ONLINE) && ((MSGLEN - (p - env)) > 25)) + if ((current->connect == CN_ONLINE) && ((MSGLEN - (p - env)) > 25)) { - unset_closeonexec(backup->sock); + unset_closeonexec(current->sock); if (n) *(p++) = ' '; #ifdef IRCD_EXTENSIONS - sprintf(p,"f%i:%i:X%i",backup->guid,backup->sock,backup->ircx_flags); + sprintf(p,"f%i:%i:X%i",current->guid,current->sock,current->ircx_flags); #else /* IRCD_EXTENSIONS */ - sprintf(p,"f%i:%i",backup->guid,backup->sock); + sprintf(p,"f%i:%i",current->guid,current->sock); #endif /* IRCD_EXTENSIONS */ p = STREND(p); n++; + to_server("PING :OT%lu\n",current->ontime); } - for(client=backup->clientlist;client;client=client->next) + for(client=current->clientlist;client;client=client->next) { #ifdef TELNET if ((client->flags & (DCC_ACTIVE|DCC_TELNET)) == 0) @@ -408,15 +421,16 @@ void do_reset(COMMAND_ARGS) *(p++) = ' '; #ifdef TELNET sprintf(p,(client->flags & DCC_TELNET) ? "t%i:%i:%s" : "c%i:%i:%s", - backup->guid,client->sock,client->user->name); + current->guid,current->sock,client->user->name); #else - sprintf(p,"c%i:%i:%s",backup->guid,client->sock,client->user->name); + sprintf(p,"c%i:%i:%s",current->guid,current->sock,client->user->name); #endif /* TELNET */ p = STREND(p); n++; } } } + current = backup; #ifdef DEBUG debug("(do_reset) %s [%i]\n",env,(int)(p - env)); diff --git a/src/structs.h b/src/structs.h index e70ff08..60abadf 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts 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 @@ -320,20 +320,8 @@ typedef struct ChanUser int flags; - /* distance between &_num -> &_time is used in check_mass */ - int floodnum; - time_t floodtime; - int bannum; - time_t bantime; - int deopnum; - time_t deoptime; - int kicknum; - time_t kicktime; - int nicknum; - time_t nicktime; - int capsnum; - time_t capstime; - + uint8_t action_num[INDEX_MAX]; + time_t action_time[INDEX_MAX]; time_t idletime; #ifdef CHANBAN @@ -514,6 +502,11 @@ typedef struct Mech int server; /* ident of my current server */ int nextserver; +#ifdef BOTNET + const char *supres_cmd; + int supres_crc; +#endif + /* * Line buffer for non-essential stuff */ @@ -549,7 +542,6 @@ typedef struct Mech #endif /* NOTIFY */ Spy *spylist; - int spy; #ifdef NOTIFY @@ -659,7 +651,7 @@ typedef struct BotNet /* * do not touch the above vars! - * they are copied partially in net.c + * they are copied partially in that order in net.c */ int guid; /* remote bot guid */ @@ -793,7 +785,7 @@ typedef struct OnMsg redir:1, lbuf:1, cbang:1, - acchan:1; + acchan:1; // -- 20 bits char *cmdarg; } OnMsg; @@ -810,7 +802,7 @@ typedef struct dnsAuthority } dnsAuthority; typedef struct dnsList -{ +{ struct dnsList *next; time_t when; struct in_addr ip; diff --git a/src/user.c b/src/user.c index b878570..963cca6 100644 --- a/src/user.c +++ b/src/user.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts 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 @@ -294,9 +294,24 @@ int read_userlist(char *filename) User *olduserlist; User *newuserlist; int in; +#ifdef DEBUG + int r; +#endif if (!filename) return(FALSE); + if (*filename == '<') // read only userfile + filename++; +#ifdef DEBUG + if ((r = is_safepath(filename,FILE_MUST_EXIST)) != FILE_IS_SAFE) + { + debug("(write_userlist) %s: unsafe filename (%i)...\n",filename,r); + return(FALSE); + } +#else + if (is_safepath(filename,FILE_MUST_EXIST) != FILE_IS_SAFE) + return(FALSE); +#endif if ((in = open(filename,O_RDONLY)) < 0) return(FALSE); @@ -345,7 +360,7 @@ int write_userlist(char *filename) char *p,flags[7]; int i,f; #ifdef DEBUG - int dodeb; + int dodeb,r; #endif /* DEBUG */ if (!filename) @@ -354,6 +369,27 @@ int write_userlist(char *filename) if (!current->ul_save) return(TRUE); + if (*filename == '<') // we dont write to read only userfiles +#ifdef DEBUG + { + debug("(write_userlist) %s: writing to read only userfile is prohibited...\n",filename); + return(FALSE); + } +#else + return(FALSE); +#endif + +#ifdef DEBUG + if ((r = is_safepath(filename,FILE_MAY_EXIST)) != FILE_IS_SAFE) + { + debug("(write_userlist) %s: unsafe filename (%i)...\n",filename,r); + return(FALSE); + } +#else + if (is_safepath(filename,FILE_MAY_EXIST) != FILE_IS_SAFE) + return(FALSE); +#endif + if ((f = open(filename,O_WRONLY|O_CREAT|O_TRUNC,NEWFILEMODE)) < 0) return(FALSE);