diff --git a/.gitignore b/.gitignore index 465f572..6e3a36a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ src/config.h src/mcmd.h src/usercombo.h src/githash.h +src/hashdata.cache trivia/*.index # compiled files @@ -32,14 +33,21 @@ trivia/megatrivia.txt *.stats # developer files +dev/* .use_size +.use_warn conf debug* -src/musl.c +src/benchmark* src/nostdlib src/x src/y src/z +x +y +z randdata test.conf postfix.sh +gmon.out + diff --git a/FEATURES b/FEATURES index 5758981..5dbac26 100644 --- a/FEATURES +++ b/FEATURES @@ -42,26 +42,60 @@ DCC chat and DCC file support to operate. Very necessary to include if you are a developer... --- Dynamic channel limit (+l) + + Make the bot update the channel user limit (+l) to a value that only allows +a limited number of users to join within a certain time period. + --- Dynamic command levels support + + Permit altering at runtime the access level needed to use commands. Including +the possibility to disable commands. + --- Greet support --- HTTP server support + + Warning: ALPHA grade code. Not recommended for casual use. Make energymech +respond to HTTP requests on a user configurable port. + --- Host info support + + Include features to monitor the server that the energymech runs on. + --- IRC proxy support --- IRCD extensions support + + BETA code. Support for non-standard IRC server features. + --- Newbie support + + Extra safeguards and messages for beginners. + --- Note support --- Notify support --- Password hashing with MD5 + + Encrypt user passwords with md5. + --- Password hashing with SHA + + Encrypt user passwords with sha1 or sha512. + --- Scripting with Python --- Scripting with Tcl --- Seen support --- Session support --- Statistics support --- Telnet support + + Support for connecting to the energymech partyline with telnet/netcat. + --- Trivia support --- Toybox fun and games --- Uptime support + + Send bot uptime packets to the bot uptime tracker (https://www.eggheads.org/uptime) + --- URL capture support --- WinGate support + Ancient tech. Support for wingate proxy. diff --git a/Makefile b/Makefile index baa36ab..2e213f4 100644 --- a/Makefile +++ b/Makefile @@ -17,52 +17,55 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -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 +MISCFILES = CREDITS FEATURES LICENSE README README.TCL TODO VERSIONS VERSIONS-2.x Makefile \ + configure checkmech sample.conf sample.py sample.tcl sample.userfile \ + common/default.bigchars public/README trivia/README ASCIIFILES = ascii/README ascii/bbw ascii/camel ascii/goatse ascii/mech ascii/phooler -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 \ - help/CMD help/CORE help/CSERV help/CTCP help/CYCLE help/DEOP help/DIE \ - help/DNS help/DNSSERVER help/DO help/DOWN help/ECHO help/ESAY help/FEATURES \ - help/FORGET help/GREET help/HELP help/IDLE help/INSULT help/INVITE help/JOIN help/KB \ - help/KICK help/KS help/LAST help/LEVELS help/LINK help/LOAD help/LUSERS help/ME \ - help/MODE help/MSG help/NAMES help/NEXTSERVER help/NICK help/NOTIFY help/ONTIME \ - help/OP help/PART help/PASSWD help/PROTECTION help/PYTHON help/PYTHONSCRIPT \ - help/QSHIT help/RESET help/RKS help/RSHIT help/RSPY help/RT help/SAVE help/SAY \ - help/SCREW help/SEEN help/SERVER help/SERVERGROUP help/SET help/SETAAWAY \ - help/SETAOP help/SETAUB help/SETAVOICE help/SETCC help/SETCHANBAN help/SETCKL \ - help/SETDCC help/SETENFM help/SETENFMODES help/SETENFPASS help/SETFL help/SETFPL \ - help/SETIKT help/SETKS help/SETMAL help/SETMBL help/SETMDL help/SETMKL \ - help/SETMODES help/SETMPL help/SETNCL help/SETPASS help/SETPROT help/SETPUB \ - help/SETRK help/SETSD help/SETSERVERGROUP help/SETSHIT help/SETSO help/SETSTATS \ - help/SETTOP help/SHIT help/SHITLIST help/SHOWIDLE help/SHUTDOWN help/SITEBAN \ - help/SITEKB help/SPY help/STATS help/TCL help/TCLSCRIPT help/TIME help/TOPIC \ - help/UNALIAS help/UNBAN help/UNVOICE help/UP help/UPTIME help/USAGE help/USER \ - help/USERHOST help/USERLIST help/VER help/VERIFY help/VOICE help/WALL help/WHO \ - help/WHOIS help/WHOM +HELPFILES = help/8BALL help/ACCESS help/ALIAS help/AWAY help/BAN help/BANLIST help/BOOT \ + help/BYE help/CCHAN help/CHACCESS help/CHANBAN help/CHANNELS help/CHAT \ + help/CLEARSHIT help/CMD help/CORE help/CSERV help/CTCP help/CYCLE help/DEBUG \ + help/DEOP help/DIE help/DNS help/DNSSERVER help/DO help/DOWN help/ECHO \ + help/ESAY help/FEATURES help/FORGET help/GREET help/HELP help/IDLE help/INSULT \ + help/INVITE help/JOIN help/KB help/KICK help/KS help/LAST help/LEVELS help/LINK \ + help/LOAD help/LUSERS help/ME help/MODE help/MSG help/NAMES help/NEXTSERVER \ + help/NICK help/NOTE help/NOTIFY help/ONTIME help/OP help/PART help/PASSWD \ + help/PROTECTION help/PYTHON help/PYTHONSCRIPT help/QSHIT help/RAND help/READ \ + help/RESET help/RKS help/RSHIT help/RSPY help/RT help/SAVE help/SAY help/SCREW \ + help/SEEN help/SERVER help/SERVERGROUP help/SET help/SETAAWAY help/SETAOP \ + help/SETAUB help/SETAVOICE help/SETCC help/SETCHANBAN help/SETCKL help/SETDCC \ + help/SETENFM help/SETENFMODES help/SETENFPASS help/SETFL help/SETFPL help/SETIKT \ + help/SETKS help/SETMAL help/SETMBL help/SETMDL help/SETMKL help/SETMODES \ + help/SETMPL help/SETNCL help/SETPASS help/SETPROT help/SETPUB help/SETRK \ + help/SETSD help/SETSERVERGROUP help/SETSHIT help/SETSO help/SETSTATS help/SETTOP \ + help/SHIT help/SHITLIST help/SHOWIDLE help/SHUTDOWN help/SITEBAN help/SITEKB \ + help/SPY help/STATS help/TCL help/TCLSCRIPT help/TIME help/TOPIC help/UNALIAS \ + help/UNBAN help/UNVOICE help/UP help/UPTIME help/USAGE help/USER help/USERHOST \ + help/USERLIST help/VER help/VERIFY help/VOICE help/WALL help/WHO help/WHOIS help/WHOM -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 +RANDFILES = common/8ball.txt common/away.txt common/insult.txt \ + common/kick.txt common/nick.txt common/pickup.txt \ + common/say.txt common/signoff.txt common/version.txt 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/endian.c config/inet_addr.c config/inet_aton.c config/ldtest.c config/md5.h config/md5_internal.c \ - config/perl.c config/ptr_size.c config/python.c config/pw.c config/sha1.h config/sha_internal.c config/socket.c config/tcl.c \ +TESTFILES = config/cc.c config/endian.c config/inet_addr.c config/inet_aton.c config/ldtest.c \ + config/md5.h config/md5.c config/perl.c config/ptr_size.c config/python.c config/pw.c \ + config/sha1.h config/sha1.c config/sha512.c config/socket.c config/tcl.c \ config/unaligned.c config/which TRIVFILES = trivia/mkindex.c -SRCFILES = src/alias.c src/auth.c src/bounce.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/main.c \ - src/net.c src/note.c src/ons.c src/parse.c src/partyline.c src/perl.c src/prot.c \ - src/python.c src/reset.c src/seen.c src/shit.c src/io.c src/spy.c src/tcl.c \ - src/toybox.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 +SRCFILES = src/alias.c src/auth.c src/bounce.c src/calc.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/main.c src/net.c src/note.c src/ons.c src/parse.c src/partyline.c \ + src/perl.c src/prot.c src/python.c src/reset.c src/seen.c src/shit.c src/io.c \ + src/spy.c src/tcl.c src/toybox.c src/uptime.c src/user.c src/vars.c src/web.c \ + src/lib/md5.c src/lib/md5.h src/string.c -HDRFILES = src/defines.h src/global.h src/h.h src/settings.h src/structs.h src/text.h src/usage.h +HDRFILES = src/commands.h src/defines.h src/global.h src/h.h src/onhash.h src/settings.h \ + src/structs.h src/text.h src/usage.h CONFFILES = src/Makefile src/config.h @@ -86,14 +89,18 @@ clean: install: $(MAKE) -C src install - test -x postfix.sh && ./postfix.sh + @if [ -x test ]; then \ + ./postfix.sh; \ + fi mega: $(MAKE) -C src mega -mega-install: +mega-install mi: $(MAKE) -C src mega-install - test -x postfix.sh && ./postfix.sh + @if [ -x test ]; then \ + ./postfix.sh; \ + fi # # code validation tests diff --git a/README b/README index fe5632f..2c09b01 100644 --- a/README +++ b/README @@ -120,7 +120,7 @@ Extra files for users of EnergyMech can be found at: Files, documentation and tips can be found at: - http://www.energymech.net + (no official website currently) ---*--- @@ -129,4 +129,4 @@ IT COMES TO CONFIGURING AND USING IT. ---*--- -proton, April 17th, 2018. +proton, November 5th, 2025. diff --git a/TODO b/TODO index 5333bd6..a1b8b26 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,9 @@ /* - * EnergyMech TODO (March 16th, 2018) + * EnergyMech TODO (November 6th, 2025) */ + - copy a master read_fds for select instead of building a new one each loop + - Toybox hangman game - Support for MD5 and SHA enabled at the same time for compatibility/fallback @@ -19,6 +21,7 @@ - DalNet Nickserv/Chanserv support (needed? they dont tolerate much bots on that network /proton) - Update/complete the help files. + - Parse help files out of source code comments. - Mode +/-o commands to check for SO and if SO is set, check userlevel and make sure user has access before sending MODEs. diff --git a/VERSIONS b/VERSIONS index bb97927..cbcd642 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,4 +1,53 @@ -3.1 -- WORK IN PROGRESS (~May, 2018) +3.5(.dev) -- + + * Fixed: Channel stats would be desynched after bot being kicked and rejoining. + * Added: New debug command: INJECT . Inject data as if it came from the server itself. + * Fixed: prot_action enforced protection levels above SET PROT. + * Fixed: Apparently Eggheads changed the uptime protocol without telling anyone. + * Changed: Branchless more compact base64 conversion for RANDSRC in send_spy(). + * Changed: New botnet connection announced on spy status instead of spy botnet. + * Changed: Adjusted output of INFO command. + * Changed: Rewrote how SERVERGROUP works. Config files might need changes. + * Removed: SERVERGROUP command. + * Changed: Nicks/Wantnick/Userhost dynamically allocated only for 'too long' strings. + * Removed: IDWRAP code. It was my personal thing. + * Changed: on_msg now matches commands using a hash function instead + of iterating through the list of commands using strcasecmp. + * Added: More help files; BOOT, DEBUG, NOTE, READ + * Changed: Updated several helpfiles. + * Changed: Table of builtin commands taken out of gencmd.c and put into + commands.h for easier editing. + * Added: ESAY $load to show system CPU loadavg (HOSTINFO feature). + * Changed: Bumped version because of undocumented changes. + +3.2 -- October 21, 2025. + + * Added: Server maxontime is actually used. + * Fixed: Crash in SETPASS + * Fixed: FORGET command Issue #20 + * Added: Support for a posfix.sh command at the end of the compilation + process for developers. + * Added: Host info added to CORE (with HOSTINFO support). + * Plenty of unlisted changes... + * Changed: Do not log commands until all the checks are done. + * Added: Debug info on code layout in debug files. + * Changed: HOSTINFO changed to SYSINFO. + * Fixed: Compiler warnings. + * Changed: More code layout adjustments. + * Added: Superuser doing AUTH with no arguments will list active auths. + * Changed: Default uptime host set to uptime.eggheads.org. + * Fixed: CHAT crash bug. + * Changed: Reorder HELP command list to alphabetical order. + * Added: Binary as source for CV command. + * Added: Newbie warning about using -f with sessions support. + * Added: CALC command (still alpha code). + * Added: Spy RANDSRC: generate randomness from IRC activity. + * Fixed: away.txt grammar (m4t). + * Fixed: 8ball.txt language fixes. + * Changed: ESAY overflow adjustment. + * Changed: January 15, 2025: Proton no longer single. Sorry to all the ladies. + +3.1 -- May 25, 2020. * Fixed: If the network interface goes down, the mech will mark all servers as unconnectable, permanently, so even when the network comes back up... Fixed! diff --git a/config/fdset.c b/config/fdset.c new file mode 100644 index 0000000..132f7d5 --- /dev/null +++ b/config/fdset.c @@ -0,0 +1,12 @@ +#include +#include + +int main(int argc, char **argv, char **envp) +{ + fd_set readfds; + int sz; + + sz = sizeof(readfds); + printf("%i\n",sz); + return(0); +} diff --git a/config/inet_addr.c b/config/inet_addr.c index 1b7b58e..b6f024d 100644 --- a/config/inet_addr.c +++ b/config/inet_addr.c @@ -1,9 +1,20 @@ #include #include -int main(int argc, char **argv) +#include +#include +int main(int argc, char **argv) { struct in_addr ia; ia.s_addr = inet_addr("0.0.0.0"); + if (argc == 2) + { + if (strcmp("safamily",argv[1]) == 0) + printf("%i\n",(int)sizeof(sa_family_t)); + if (strcmp("sockaddr",argv[1]) == 0) + printf("%i\n",(int)sizeof(struct sockaddr_in)); + if (strcmp("sockaddrv6",argv[1]) == 0) + printf("%i\n",(int)sizeof(struct sockaddr_in6)); + } return(0); } diff --git a/config/md5_internal.c b/config/md5.c similarity index 100% rename from config/md5_internal.c rename to config/md5.c diff --git a/config/sha_internal.c b/config/sha1.c similarity index 100% rename from config/sha_internal.c rename to config/sha1.c diff --git a/config/sha512.c b/config/sha512.c new file mode 120000 index 0000000..b48277a --- /dev/null +++ b/config/sha512.c @@ -0,0 +1 @@ +../src/lib/sha512.c \ No newline at end of file diff --git a/configure b/configure index abd4abf..c5bb330 100755 --- a/configure +++ b/configure @@ -24,6 +24,8 @@ compile=no install=no silentopt=no try_libmusl=no +no_flto=no +use_fnostrictalias=no # default optimization goal, speed = -O2, size = -Os optitype=size @@ -103,7 +105,6 @@ do dyncmd ) ft_dyncmd=$yesno ;; greet ) ft_greet=$yesno ;; hostinfo ) ft_hostinfo=$yesno ;; - idwrap ) ft_idwrap=$yesno ;; ircd_ext ) ft_ircd_ext=$yesno ;; libmusl ) try_libmusl=$yesno ;; md5 ) ft_md5=$yesno ;; @@ -154,7 +155,7 @@ do esac case "$feature" in - alias | botnet | bounce | chanban | ctcp | dccfile | debug | dynamode | dyncmd | greet | hostinfo | idwrap | ircd_ext | libmusl | md5 \ + alias | botnet | bounce | chanban | ctcp | dccfile | debug | dynamode | dyncmd | greet | hostinfo | ircd_ext | libmusl | md5 \ | 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 @@ -206,8 +207,6 @@ do greet_no ) ft_greet=no ;; hostinfo_yes | hostinfo_ ) ft_hostinfo=yes ;; hostinfo_no ) ft_hostinfo=no ;; - idwrap_yes | idwrap_ ) ft_idwrap=yes ;; - idwrap_no ) ft_idwrap=no ;; ircd_ext_yes | ircd_ext_ ) ft_ircd_ext=yes ;; ircd_ext_no ) ft_ircd_ext=no ;; libmusl_yes | libmusl_ ) try_libmusl=/usr/local/musl/bin/musl-gcc ;; @@ -273,11 +272,10 @@ do dyncmd ) ft_dyncmd=no ;; greet ) ft_greet=no ;; hostinfo ) ft_hostinfo=no ;; - idwrap ) ft_idwrap=no ;; ircd_ext ) ft_ircd_ext=no ;; - libmusl ) try_libmusl=no ;; + libmusl ) try_libmusl=no ;; md5 ) ft_md5=no ;; - netcfg ) ft_netcfg=no ;; + netcfg ) ft_netcfg=no ;; newbie ) ft_newbie=no ;; note ) ft_note=no ;; notify ) ft_notify=no ;; @@ -306,12 +304,15 @@ do --silence=options) silentopt=yes ;; --md5=internal) ft_md5=internal ;; --sha=internal) ft_sha=internal ;; + --sha=internal512) ft_sha=internal512 ;; --use-cpuflags) cc_arch_opt=yes ;; --no-cpuflags) cc_arch_opt=no ;; --use-optimize) cc_optimize_opt=yes ;; --no-optimize) cc_optimize_opt=no ;; --optimize=speed) optitype=speed ;; --optimize=size) optitype=size ;; + --use-nostrictalias) use_fnostrictalias=yes ;; + --no-nostrictalias) use_fnostrictalias=no ;; --use-gnudebug) cc_g_opt=yes ;; --no-gnudebug) cc_g_opt=no ;; --use-warnflag) cc_wall_opt=yes ;; @@ -320,6 +321,8 @@ do --no-pipeflag) cc_pipe_opt=no ;; --use-ofp) cc_ofp_opt=yes ;; --no-ofp) cc_ofp_opt=no ;; + --use-flto) no_flto=no ;; + --no-flto) no_flto=yes ;; --default-yes) ft_default=yes set_feature_defaults ;; --default-no) ft_default=no set_feature_defaults ;; --help | -h) @@ -338,6 +341,8 @@ Features and packages: --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 + --use-flto Try to compile with Link-Time Optimizatons + --no-flto Dont use Link-Time Optimizations --with-alias ALIAS support --with-botnet Botnet support --with-bounce @@ -557,7 +562,7 @@ cf_cflags= if [ -n "$CFLAGS" ]; then if $CC $CFLAGS -c -o $TESTO $TESTC 1> /dev/null 2> /dev/null && test -r $TESTO; then cf_cflags="$CFLAGS" - echo $ac_n "$CFLAGS "$ac_c + echo $ac_n "$CFLAGS (from environment CFLAGS) "$ac_c fi fi @@ -589,7 +594,7 @@ if [ -z "$cf_cflags" -a -n "$cf_GNUCC" ]; then fi fi fi - if [ "$cc_wall_flag" = -Wall -a "$cf_GNUCC" = 33 ]; then + if [ "$use_fnostrictalias" = yes -a "$cc_wall_opt" = -Wall ]; then cc_fnostrictalias="-fno-strict-aliasing" echo $ac_n "-fno-strict-aliasing "$ac_c fi @@ -627,6 +632,9 @@ if [ -z "$cf_cflags" -a -n "$cf_GNUCC" ]; then fi fi +# +# test for -pipe flag +# if [ -z "$cf_cflags" -a -z "$cc_pipe_opt" ]; then if $CC -pipe -c -o $TESTO $TESTC 1> /dev/null 2> /dev/null && test -r $TESTO; then cc_pipe_flag="-pipe" @@ -634,6 +642,20 @@ if [ -z "$cf_cflags" -a -z "$cc_pipe_opt" ]; then fi fi +# +# test -flto (link-time optimizations) +# +if [ -z "$no_flto" -o "$no_flto" = no ]; then + if [ -z "$cf_cflags" ]; then + if $CC -flto -c -o $TESTO $TESTC 1> /dev/null 2> /dev/null && test -r $TESTO; then + cc_flto_flag="-flto" + echo $ac_n "-flto "$ac_c + fi + fi +else + cc_flto_flag= +fi + oflag="-O2" if [ "$optitype" = size ]; then oflag="-Os" @@ -652,6 +674,14 @@ if [ -z "$cf_cflags" -a -z "$cc_optimize_opt" ]; then fi fi +cc_omitprotect_flag="" +if [ "$optitype" = size ]; then + if $CC $oflag -fcf-protection=none -o $TESTO $TESTC 1> /dev/null 2> /dev/null; then + cc_omitprotect_flag="-fcf-protection=none " + echo $ac_n "$cc_omitprotect_flag "$ac_c + fi +fi + echo $ac_t "" if [ "$ft_prof" = yes ]; then @@ -677,6 +707,20 @@ fi rm -f $TESTO $TESTP +# +# size of select fd_set +# +TESTC=config/fdset.c +size_fdset=128 +echo $ac_n "checking size of select fd_set ... "$ac_c +$CC -o $TESTP $TESTC 1> /dev/null 2> /dev/null +if [ -x $TESTP ]; then + size_fdset=`$TESTP` +fi +echo $ac_t "$size_fdset bytes" + +rm -f $TESTP + # # 32bit? 64bit? # @@ -690,7 +734,11 @@ if [ -z "$ptr_size" ]; then if [ -x $TESTP ]; then ptr_size=`$TESTP` fi - echo $ac_t "$ptr_size" + if [ "$ptr_size" = 8 ]; then + echo $ac_t "64 bit" + else + echo $ac_t "$ptr_size" + fi fi case _"$ptr_size"_ in @@ -798,6 +846,17 @@ else fi fi echo $ac_t "$has_inet_addr" +if [ "$has_inet_addr" = no ]; then + echo "error: missing inet_addr(), cant proceed without it." + exit +fi + +echo $ac_n "checking sizeof(sa_family_t) ... "$ac_c +safamily=unknown +if [ -x $TESTP ]; then + safamily=`$TESTP` +fi +echo $ac_t "$safamily" rm -f $TESTP # @@ -853,20 +912,37 @@ if [ ! "$ft_sha" = no ]; then TESTC=config/pw.c echo $ac_n "checking for SHA in crypt() ... "$ac_c sha_internal= + sha_object= crypt_func='-DCRYPT_FUNC=crypt' CRYPT_FUNCTION='#define CRYPT_FUNC crypt' + if [ "$ft_sha" = internal512 ]; then + sha_internal=config/sha512.c + sha_object=config/sha512.o + crypt_func='-DCRYPT_FUNC=crypt_sha512' + CRYPT_FUNCTION='#define CRYPT_FUNC crypt_sha512' + $CC -o $TESTP $sha_internal -DTEST 1> /dev/null 2> /dev/null + fi if [ "$ft_sha" = internal ]; then - sha_internal=config/sha_internal.c + sha_internal=config/sha1.c + sha_object=config/sha1.o crypt_func='-DCRYPT_FUNC=sha_crypt' CRYPT_FUNCTION='#define CRYPT_FUNC sha_crypt' fi - $CC -o $TESTP $TESTC $sha_internal $crypt_func 1> /dev/null 2> /dev/null + # if [ ! -x $TESTP ]; then + $CC -o $TESTP $TESTC $sha_object $crypt_func 1> /dev/null 2> /dev/null + fi + # + if [ ! -x $TESTP ]; then + crypt_func='-DCRYPT_FUNC=crypt' + CRYPT_FUNCTION='#define CRYPT_FUNC crypt' libcrypt=-lcrypt has_sha=yes $CC -o $TESTP $TESTC $crypt_func $libcrypt 1> /dev/null 2> /dev/null fi if [ ! -x $TESTP ]; then + crypt_func='-DCRYPT_FUNC=crypt' + CRYPT_FUNCTION='#define CRYPT_FUNC crypt' libcrypt=/usr/lib/libcrypt.so has_sha=yes $CC -o $TESTP $TESTC $crypt_func $libcrypt 1> /dev/null 2> /dev/null @@ -878,7 +954,9 @@ if [ ! "$ft_sha" = no ]; then if [ -x $TESTP ]; then pwhash=`$TESTP` case "$pwhash" in + SHA512 ) has_sha=internal512 ;; MD5 ) has_md5=yes ;; + SHA ) has_sha=yes ;; SHAMD5 ) has_md5=yes has_sha=yes @@ -887,9 +965,8 @@ if [ ! "$ft_sha" = no ]; then fi echo $ac_t "$has_sha" [ "$has_sha" = yes -a "$sha_internal" ] && has_sha=internal - rm -f $TESTP + rm -f $TESTP $sha_object fi - # # check for MD5 capabilities in libc/glibc/libcrypt # @@ -898,13 +975,13 @@ if [ "$has_md5" = yes ]; then elif [ "$ft_md5" = no ]; then has_md5=notest elif [ ! "$ft_md5" = no ]; then - TESTC=config/pw.c echo $ac_n "checking for MD5 in crypt() ... "$ac_c + TESTC=config/pw.c md5_internal= crypt_func='-DCRYPT_FUNC=crypt' CRYPT_FUNCTION='#define CRYPT_FUNC crypt' if [ "$ft_md5" = internal ]; then - md5_internal=config/md5_internal.c + md5_internal=config/md5.c crypt_func='-DCRYPT_FUNC=md5_crypt' CRYPT_FUNCTION='#define CRYPT_FUNC md5_crypt' fi @@ -1058,26 +1135,6 @@ fi echo $ac_t "$has_ldscript" rm -f $TESTP -# -# idwrap -# -has_idwrap=no -def_idwrap='#undef IDWRAP' -IDWRAP_PATH='/* nothing */' - -if [ -r .use_idwrap -o "$ft_idwrap" = yes ]; then - echo $ac_n "checking for idwrap path ... "$ac_c - if test -z "$idwrappath"; then - idwrappath="/tmp/.ident/" - fi - if test -d $idwrappath; then - IDWRAP_PATH='"'"$idwrappath"'"' - has_idwrap="$IDWRAP_PATH" - def_idwrap='#define IDWRAP' - fi - echo $ac_t "$has_idwrap" -fi - # # # @@ -1107,7 +1164,11 @@ SHA_C= SHA_O= if [ "$ft_sha" = internal ]; then SHA_C=lib/sha1.c - SHA_O=lib/sha.o + SHA_O=lib/sha1.o +fi +if [ "$ft_sha" = internal512 ]; then + SHA_C=lib/sha512.c + SHA_O=lib/sha512.o fi out=echo @@ -1306,7 +1367,7 @@ if [ "$has_sha" = no ]; then else 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' + test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes -o "$ans" = internal -o "$ans" = internal512 && def_sha='#define SHACRYPT' fi def_perl='#undef PERL' @@ -1405,12 +1466,12 @@ 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' +def_urlcap='#undef URLCAPTURE' unset ans $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' +test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ans" = Yes && def_urlcap='#define URLCAPTURE' def_wingate='#undef WINGATE' unset ans @@ -1422,7 +1483,7 @@ test -z "$ans" -o "$ans" = y -o "$ans" = Y -o "$ans" = yes -o "$ans" = YES -o "$ $out '' echo "Creating src/Makefile" -O_FLAGS="$cc_optimize_flag $cc_arch_flag $cc_march_flag $cc_ofp_flag" +O_FLAGS="$cc_optimize_flag $cc_arch_flag $cc_march_flag $cc_ofp_flag $cc_omitprotect_flag" W_FLAGS="$cc_wall_flag $cc_wshadow_flag $cc_fnostrictalias" libflags="$libcrypt $libtcl $libnsl $libsocket $libresolv $libpython $libperl" lflags="$cc_g_flag -o" @@ -1430,7 +1491,7 @@ cprof="$cc_pg_flag $cc_pg_define" lprof="$cc_pg_flag $cc_pg_define $libpgdl" if [ -z "$cf_cflags" ]; then - cf_cflags='$(PIPEFLAG) $(GDBFLAG) $(WARNFLAG) $(OPTIMIZE)' + cf_cflags='$(PIPEFLAG) $(GDBFLAG) $(FLTO_FLAG) $(WARNFLAG) $(OPTIMIZE)' fi echo '# This file is generated from Makefile.in' > src/Makefile @@ -1439,6 +1500,7 @@ s%@CC@%$CCshort%; s%@ldscript@%$ldscript%; s%@pipeflag@%$cc_pipe_flag%; s%@gdbflag@%$cc_g_flag%; +s%@flto_flag@%$cc_flto_flag%; /@cprof@/ { s,@cprof@,$cprof,; }; /@lprof@/ { s,@lprof@,$lprof,; }; /@lflags@/ { s,@lflags@,$lflags,; }; @@ -1482,7 +1544,6 @@ sed " s|@DEF_DYNAMODE@|$def_dynamode|; s|@DEF_GREET@|$def_greet|; s|@DEF_HOSTINFO@|$def_hostinfo|; - s|@DEF_IDWRAP@|$def_idwrap|; s|@DEF_IRCD_EXT@|$def_ircd_ext|; s|@DEF_MD5@|$def_md5|; s|@DEF_SHA@|$def_sha|; @@ -1503,7 +1564,7 @@ s|@DEF_SUPPRESS@|$def_suppress|; s|@DEF_TOYBOX@|$def_toybox|; s|@DEF_TRIVIA@|$def_trivia|; s|@DEF_UPTIME@|$def_uptime|; -s|@DEF_URLCAPTURE@|$def_urlcapture|; + s|@DEF_URLCAP@|$def_urlcap|; s|@DEF_WEB@|$def_web|; s|@DEF_WINGATE@|$def_wingate|; @@ -1514,14 +1575,13 @@ s|@DEF_CRYPT_FUNCTION@|$CRYPT_FUNCTION|; s|@CRYPT_HAS_SHA@|$CRYPT_HAS_SHA|; s|@CRYPT_HAS_MD5@|$CRYPT_HAS_MD5|; s|@CRYPT_HAS_DES@|$CRYPT_HAS_DES|; -s|@IDWRAP_PATH@|$IDWRAP_PATH|; s|@PTSIZE_DEFINE32@|$PTSIZE_DEFINE32|; s|@PTSIZE_DEFINE64@|$PTSIZE_DEFINE64|; s|@UNALIGNED_MEM@|$UNALIGNED_MEM|; " < src/config.h.in >> src/config.h save_myconfig() { - names="alias botnet bounce chanban ctcp dccfile debug dynamode dyncmd greet hostinfo idwrap ircd_ext libmusl md5 + names="alias botnet bounce chanban ctcp dccfile debug dynamode dyncmd greet hostinfo ircd_ext libmusl md5 netcfg newbie note notify perl profiling python rawdns redirect seen session sha stats suppress tcl telnet toybox trivia uptime urlcapture web wingate" echo "./configure \\" > ./myconfig @@ -1539,6 +1599,7 @@ save_myconfig() { test "$silentopt" = yes && echo "--silence=options \\" >> ./myconfig test "$ft_md5" = internal && echo "--md5=internal \\" >> ./myconfig test "$ft_sha" = internal && echo "--sha=internal \\" >> ./myconfig + test "$ft_sha" = internal512 && echo "--sha=internal512 \\" >> ./myconfig test "$optitype" = speed && echo "--optimize=speed \\" >> ./myconfig test "$optitype" = size && echo "--optimize=size \\" >> ./myconfig test "$cc_ofp_opt" = yes && echo "--use-ofp \\" >> ./myconfig diff --git a/help/ALIAS b/help/ALIAS index 6e5b1ae..0f2431e 100644 --- a/help/ALIAS +++ b/help/ALIAS @@ -17,5 +17,7 @@ MEEP one two three four -> SAY two one three four Aliases may call other aliases and aliases can be used to replace built in commands. Aliases can recurse a maximum of 20 times (prevents infinite loops). - + +If no argument is given, all current aliases will be listed. + See also: unalias diff --git a/help/BOOT b/help/BOOT new file mode 100644 index 0000000..c244c40 --- /dev/null +++ b/help/BOOT @@ -0,0 +1,4 @@ + +Boot a user from the partyline. + +See also: core, whom diff --git a/help/CORE b/help/CORE index 992b516..a52a6b9 100644 --- a/help/CORE +++ b/help/CORE @@ -1,6 +1,6 @@ Shows core information about the bot. - + Current nick Nick of the bot you are connected to and its Guid. Users in userlist Total number of userlist entries, as well as users with userlevel access (0-100) and bot level access (200). @@ -14,5 +14,5 @@ Started Time when the bot was first started. Uptime How long (in days, hours, minutes and seconds) the bot has been running. Version Source code version of the bot. Features List of which features were compiled into the bot. - + See also: ver, uptime, ontime, features diff --git a/help/DEBUG b/help/DEBUG new file mode 100644 index 0000000..9829ba4 --- /dev/null +++ b/help/DEBUG @@ -0,0 +1,10 @@ + +On - Turn On debug and write output to +Off - Turn Off debug + +If no arguments are given, debug data will be written +to a file named "debug.". + +Only available if compiled with debug support. + +See also: crash diff --git a/help/DIE b/help/DIE index fc5958c..08565cf 100644 --- a/help/DIE +++ b/help/DIE @@ -1,7 +1,7 @@ - + Kills the bot. If session file is in use, use the SHUTDOWN command instead to preserve the configurations for all bots. If DIE is used, the killed bot(s) will not be saved to the session file. - -See also: reset, shutdown + +See also: nick, reset, shutdown diff --git a/help/FEATURES b/help/FEATURES index f83ef56..6559160 100644 --- a/help/FEATURES +++ b/help/FEATURES @@ -1,9 +1,9 @@ The Energymech contains a list of which features were included when the source was compiled. - + You can view this list at the command prompt in your shell with ./(name of executable) -v - + Or, once the bot is started, with the command CORE or ESAY $cap - + See also: core, esay diff --git a/help/NICK b/help/NICK index 907ad38..e364499 100644 --- a/help/NICK +++ b/help/NICK @@ -1,4 +1,12 @@ -Usage: NICK - Changes the nick of the bot. If the nick given is already - in use, the bot will not change its nickname until the - occupied nick is available. + +Changes the nick of the bot. If the nick given is already +in use, the bot will not change its nickname until the +occupied nick is available. + +If a guid is given, the nick of the bot with the given guid +will be changed. + +If no bot with the given guid exists, a new bot will be +created with the given guid. + +See also: die diff --git a/help/NOTE b/help/NOTE new file mode 100644 index 0000000..f4aa3d0 --- /dev/null +++ b/help/NOTE @@ -0,0 +1,4 @@ + +Record a note for another user. + +See also: read diff --git a/help/ONTIME b/help/ONTIME index 0296944..b2669c1 100644 --- a/help/ONTIME +++ b/help/ONTIME @@ -1,3 +1,4 @@ -Usage: ONTIME - Shows time connected to current server. - See also: UPTIME + +Shows time connected to current server. + +See also: time, uptime diff --git a/help/READ b/help/READ new file mode 100644 index 0000000..72fd055 --- /dev/null +++ b/help/READ @@ -0,0 +1,4 @@ + +Read a note left by another user. + +See also: note diff --git a/help/RSHIT b/help/RSHIT index b7d926a..6af6823 100644 --- a/help/RSHIT +++ b/help/RSHIT @@ -1,3 +1,4 @@ -Usage: RSHIT - Removes someone from the shitlist - See also: SHIT, SHITLIST + +Removes someone from the shitlist + +See also: shit, qshit, shitlist, clearshit diff --git a/help/SETSO b/help/SETSO index 3beca17..dff73e0 100644 --- a/help/SETSO +++ b/help/SETSO @@ -1,3 +1,4 @@ Usage: TOG [channel] SO [0|1|on|off] - Toggles strict opping. If on, if people not in the userlist - are opped, they will be deopped. + +Toggles strict opping. If on, if people not in the userlist +are opped, they will be deopped. diff --git a/help/SHIT b/help/SHIT index 708c900..cf37f73 100644 --- a/help/SHIT +++ b/help/SHIT @@ -1,12 +1,16 @@ Shitlists someone on all channels (*) or a certain channel -Level - can be 1 through 3 + +Level - can be 1 through 4 1 - doesn't let the person be opped or voiced 2 - will kb the person 3 - rebans the person when unbanned by anyone 4 - add a channel ban (see CHANBAN), requires chanban support + Expire - the number of days the entry will be good for (default is 30) Reason - reason for the shitlist...displays it on kickban + Note: The bot checks for shitlisted users on join, nick switch, and when the bot is opped -See also: rshit, qshit, shitlist + +See also: rshit, qshit, shitlist, clearshit diff --git a/help/SHITLIST b/help/SHITLIST index ab90dff..b680568 100644 --- a/help/SHITLIST +++ b/help/SHITLIST @@ -1,3 +1,4 @@ -Usage: SHITLIST - Shows the bots shitlist. - See also: SHIT, RSHIT, QSHIT, SHITLVL + +Shows the bots shitlist. + +See also: shit, rshit, qshit, shitlvl diff --git a/help/SPY b/help/SPY index 56d062b..0278153 100644 --- a/help/SPY +++ b/help/SPY @@ -1,22 +1,24 @@ - + Spy on a certain source of messages. When you join DCC chat, the STATUS source is added by default as a spy source for you. If no arguments are given, the current list of active spy -channels is shown. Output is not line buffered and can cause -excess flood if not careful. - +channels is shown. + (sources) STATUS Status messages. MESSAGE Pivate messages that the bot receives. RAWIRC Lines received from irc server before processing. + RANDSRC Collect randomness from IRC activity, best saved to a file. + SYSMON Hostinfo events. + URL Captured URLs. guid: Messages from a bot specified by guid. botnick: Messages from a bot specified by nick. channel Activities on the specified channel. - + (destinations) (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. If the file does not exist, it is created. - + See also: rspy diff --git a/help/TIME b/help/TIME index d6cb03f..0db1195 100644 --- a/help/TIME +++ b/help/TIME @@ -1,3 +1,4 @@ -Usage: TIME - Show current time (where the bot is) - See also: UPTIME, ONTIME + +Show current time (where the bot is) + +See also: ontime, uptime diff --git a/help/UPTIME b/help/UPTIME index 0724261..e57831e 100644 --- a/help/UPTIME +++ b/help/UPTIME @@ -1,3 +1,4 @@ -Usage: UPTIME - Shows how long the bot has been running. - See also: ONTIME + +Shows how long the bot has been running. + +See also: core, ontime, time diff --git a/help/VER b/help/VER index 24e1482..d7c84bb 100644 --- a/help/VER +++ b/help/VER @@ -1,2 +1,4 @@ -Usage: VER - Returns the version of EnergyMech that is running + +Returns the version of EnergyMech that is running + +See also: core, features diff --git a/help/WHO b/help/WHO index 728a9f3..fe7d887 100644 --- a/help/WHO +++ b/help/WHO @@ -1,7 +1,8 @@ -Usage: WHO [-ops|-nonops] [pattern] - Lists people in a channel that the bot is in now, - or was in. The optional parameters can be used to - list only ops or only non ops respectively. - If a pattern is given, only users matching the pattern - will be listed. - See also: NAMES + +Lists people in a channel that the bot is in now, +or was in. The optional parameters can be used to +list only ops or only non ops respectively. +If a pattern is given, only users matching the pattern +will be listed. + +See also: names diff --git a/help/WHOM b/help/WHOM index 565bebd..429184a 100644 --- a/help/WHOM +++ b/help/WHOM @@ -1,2 +1,4 @@ -Usage: WHOM - Show who are connected to the partyline. + +Show who are connected to the partyline. + +See also: core, boot diff --git a/sample.conf b/sample.conf index d828935..ab97138 100644 --- a/sample.conf +++ b/sample.conf @@ -9,35 +9,40 @@ set ctimeout 60 ; We don't currently support SSL or ipv6 but there's an easy workaround ; see socat.sh -servergroup undernet -server amsterdam.nl.eu.undernet.org 6663 -server amsterdam2.nl.eu.undernet.org 6663 -server bucharest.ro.eu.undernet.org 6663 -server carouge.ch.eu.undernet.org 6663 -server ede.nl.eu.undernet.org 6669 -server elsene.be.eu.undernet.org 6669 -server fulda.de.eu.undernet.org 6663 -server geneva.ch.eu.undernet.org 6663 -server graz.at.eu.undernet.org 6663 -server graz2.at.eu.undernet.org 6663 -server helsinki.fi.eu.undernet.org 6669 -server lelystad.nl.eu.undernet.org 6668 -server london.uk.eu.undernet.org 6666 -server london2.uk.eu.undernet.org 6663 -server milan.it.eu.undernet.org 6663 -server oslo1.no.eu.undernet.org 6663 -server oslo2.no.eu.undernet.org 6663 -server stockholm.se.eu.undernet.org 6669 -server surrey.uk.eu.undernet.org 6669 -server zagreb.hr.eu.undernet.org 6666 -server panamacity.pa.undernet.org 6663 -server ashburn.va.us.undernet.org 6663 -server fairfax.va.us.undernet.org 6666 -server mesa.az.us.undernet.org 6666 -server miami.fl.us.undernet.org 6669 -server princeton.nj.us.undernet.org 6663 -server sanjose.ca.us.undernet.org 6663 -server sterling.va.us.undernet.org 6669 +; Use only undernet servers +set servergroup undernet + +; Our list of servers +; server [port] [@group] ["password"] +; +server amsterdam.nl.eu.undernet.org 6663 @undernet +server amsterdam2.nl.eu.undernet.org 6663 @undernet +server bucharest.ro.eu.undernet.org 6663 @undernet +server carouge.ch.eu.undernet.org 6663 @undernet +server ede.nl.eu.undernet.org 6669 @undernet +server elsene.be.eu.undernet.org 6669 @undernet +server fulda.de.eu.undernet.org 6663 @undernet +server geneva.ch.eu.undernet.org 6663 @undernet +server graz.at.eu.undernet.org 6663 @undernet +server graz2.at.eu.undernet.org 6663 @undernet +server helsinki.fi.eu.undernet.org 6669 @undernet +server lelystad.nl.eu.undernet.org 6668 @undernet +server london.uk.eu.undernet.org 6666 @undernet +server london2.uk.eu.undernet.org 6663 @undernet +server milan.it.eu.undernet.org 6663 @undernet +server oslo1.no.eu.undernet.org 6663 @undernet +server oslo2.no.eu.undernet.org 6663 @undernet +server stockholm.se.eu.undernet.org 6669 @undernet +server surrey.uk.eu.undernet.org 6669 @undernet +server zagreb.hr.eu.undernet.org 6666 @undernet +server panamacity.pa.undernet.org 6663 @undernet +server ashburn.va.us.undernet.org 6663 @undernet +server fairfax.va.us.undernet.org 6666 @undernet +server mesa.az.us.undernet.org 6666 @undernet +server miami.fl.us.undernet.org 6669 @undernet +server princeton.nj.us.undernet.org 6663 @undernet +server sanjose.ca.us.undernet.org 6663 @undernet +server sterling.va.us.undernet.org 6669 @undernet ; ; this is sorta how a botnet configuration would look like... diff --git a/socat.sh b/socat.sh index 9816896..8cc5b80 100755 --- a/socat.sh +++ b/socat.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Simple wrapper that alows energymech to connect to SSL and/or ipv6 servers +# Simple wrapper that allows energymech to connect to SSL and/or ipv6 servers # Run it before running energymech # Listen port. In the energymech config put 'server localhost 6003' diff --git a/src/Makefile.in b/src/Makefile.in index b433628..74b9218 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,6 +1,6 @@ # # EnergyMech, IRC bot software -# Copyright (c) 1997-2021 proton +# Copyright (c) 1997-2025 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 @@ -27,6 +27,7 @@ LPROF = @lprof@ LIBS = @libflags@ PIPEFLAG = @pipeflag@ GDBFLAG = @gdbflag@ +FLTO_FLAG = @flto_flag@ WARNFLAG = @W_FLAGS@ OPTIMIZE = @O_FLAGS@ PYINCLUDE = @PYINCLUDE@ @@ -35,7 +36,7 @@ I_PERL = @I_PERL@ L_PERL = @L_PERL@ CFLAGS = @CFLAGS@ -LFLAGS = $(PIPEFLAG) $(GDBFLAG) +LFLAGS = $(PIPEFLAG) $(GDBFLAG) $(FLTO_FLAG) CC = @CC@ MV = mv -f @@ -49,13 +50,13 @@ TESTFILES = aliastest calctest safepathtest OFILES = alias.o auth.o bounce.o calc.o channel.o core.o ctcp.o debug.o dns.o function.o greet.o \ help.o hostinfo.o io.o irc.o main.o net.o note.o ons.o parse.o partyline.o \ - perl.o prot.o python.o reset.o seen.o shit.o spy.o tcl.o toybox.o \ - uptime.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 spy.o string.o tcl.o toybox.o \ + uptime.o user.o vars.o web.o @MD5_O@ @SHA_O@ SRCFILES = alias.c auth.c bounce.c calc.c channel.c core.c ctcp.c debug.c dns.c function.c greet.c \ help.c hostinfo.c io.c irc.c main.c net.c note.c ons.c parse.c partyline.c \ - perl.c prot.c python.c reset.c seen.c shit.c spy.c tcl.c toybox.c \ - uptime.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 spy.c string.c tcl.c toybox.c \ + uptime.c user.c vars.c web.c @MD5_C@ @SHA_C@ .PHONY: all clean mega-install mega mega-static test commands @@ -66,7 +67,7 @@ all: $(INSTALLNAME) # instead of doing extra parsing and handling while the bot is running. # -gencmd: gencmd.c io.c config.h structs.h +gencmd: gencmd.c io.c config.h structs.h onhash.h commands.h $(CC) $(LFLAGS) -o gencmd gencmd.c mcmd.h: gencmd @@ -104,12 +105,12 @@ $(INSTALLNAME)-static: $(OFILES) # resulting in a smaller, more efficient, binary. this process uses lots more memory at compile time. # -mega-install: mega $(SRCFILES) $(INCS) usage.h +mega-install mi:mega $(SRCFILES) $(INCS) usage.h $(CHMOD) $(INSTALLMODE) $(INSTALLNAME) $(MV) $(INSTALLNAME) $(INSTALLDIR) -mega: $(SRCFILES) $(INCS) usage.h - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o $(INSTALLNAME) main.c -DMEGA_C -DGENDATE="`./gencmd date`" -I. $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) $(TCLINCLUDE) $(I_PERL) $(L_PERL) +mega: $(SRCFILES) $(INCS) usage.h @SHA_O@ + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o $(INSTALLNAME) main.c -DMEGA_C -DGENDATE="`./gencmd date`" -I. @SHA_O@ $(LPROF) $(LIBS) $(LDSCRIPT) $(PYINCLUDE) $(TCLINCLUDE) $(I_PERL) $(L_PERL) #@oc@ $(CROSS_COMPILE)objcopy -R .note -R .comment $(INSTALLNAME) @sz@ size $(INSTALLNAME) @@ -127,14 +128,14 @@ test: $(TESTFILES) ./calctest ./safepathtest -aliastest: alias.c githash.h lib/string.o - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o aliastest $< lib/string.o $(LPROF) $(LIBS) -DTEST +aliastest: alias.c githash.h mcmd.h string.o function.o + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o aliastest $< string.o function.o $(LPROF) $(LIBS) -DTEST -calctest: calc.c githash.h mcmd.h lib/string.o - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o calctest $< lib/string.o $(LPROF) $(LIBS) -DTEST +calctest: calc.c githash.h mcmd.h string.o + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o calctest $< string.o $(LPROF) $(LIBS) -DTEST -safepathtest: function.c githash.h lib/string.o - $(CROSS_COMPILE)$(CC) $(CFLAGS) -o safepathtest $< lib/string.o $(LPROF) $(LIBS) -DTEST +safepathtest: function.c githash.h string.o + $(CROSS_COMPILE)$(CC) $(CFLAGS) -o safepathtest $< string.o $(LPROF) $(LIBS) -DTEST commands: grep -E '(void do_.*\(COMMAND_ARGS\)|/*---Help:)' *c @@ -149,8 +150,8 @@ lib/md5.o: lib/md5.c $(INCS) lib/sha1.o: lib/sha1.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< -o $@ -Ilib $(CPROF) -lib/string.o: lib/string.c $(BASEINCLUDES) - $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< -o $@ -I. $(CPROF) +lib/sha512.o: lib/sha512.c $(INCS) + $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< -o $@ -Ilib $(CPROF) alias.o: alias.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) @@ -206,7 +207,7 @@ net.o: net.c $(INCS) note.o: note.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) -ons.o: ons.c $(INCS) +ons.o: ons.c $(INCS) onhash.h $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) parse.o: parse.c $(INCS) @@ -236,6 +237,9 @@ shit.o: shit.c $(INCS) spy.o: spy.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) +string.o: string.c $(BASEINCLUDES) + $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) + tcl.o: tcl.c $(INCS) $(CROSS_COMPILE)$(CC) $(CFLAGS) -c $< $(CPROF) $(TCLINCLUDE) diff --git a/src/alias.c b/src/alias.c index e600922..dc663a7 100644 --- a/src/alias.c +++ b/src/alias.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2020 proton + Copyright (c) 1997-2025 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 @@ -32,22 +32,20 @@ #include "mcmd.h" #ifdef TEST - #include "debug.c" -char result[MSGLEN]; -char *input = "alias one two three four five six seven eight nine ten"; +char result[MSGLEN]; +char *alias_test_input = "alias one two three four five -6- seven eight nine ten"; -void *Calloc(int size) -{ - return(calloc(1,size)); -} +void run_debug(void) {} void testcase(const char *test, const char *expect) { - afmt(result,test,input); - if (strcmp(result,expect) == 0) debug("testcase SUCCESS: test \"%s\" -> got \"%s\"\n",test,expect); - else debug("testcase FAIL: test \"%s\", expected \"%s\", got \"%s\"\n",test,expect,result); + afmt(result,test,alias_test_input); + if (strcmp(result,expect) == 0) + debug("testcase SUCCESS: test \"%s\" -> got \"%s\"\n",test,expect); + else + debug("testcase FAIL: test \"%s\", expected \"%s\", got \"%s\"\n",test,expect,result); } int main(int argc, char **argv, char **envp) @@ -72,14 +70,16 @@ int main(int argc, char **argv, char **envp) testcase("cmd $2 $1","cmd two one"); testcase("cmd $8-","cmd eight nine ten"); testcase("cmd $4-5","cmd four five"); - testcase("cmd $5-6","cmd five six"); + testcase("cmd $5-6","cmd five -6-"); + testcase("cmd $5-7","cmd five -6- seven"); testcase("cmd $~","cmd noob"); + testcase("cmd $~1234567890","cmd noob1234567890"); testcase("cmd $one $two","cmd $one $two"); exit(0); } - debug("input = %s\n",input); + debug("input = %s\n",alias_test_input); debug("format = %s\n",format); - afmt(result,format,input); + afmt(result,format,alias_test_input); debug("result = %s\n",result); exit(0); } @@ -90,46 +90,37 @@ int main(int argc, char **argv, char **envp) * copy_to = buffer to put resulting new command into * src = Alias format string * input = input from user + * size: 0x159 + * size: 0x163 */ -void afmt(char *copy_to, const char *src, const char *input) -{ -#define BUFTAIL (copy_to+MSGLEN-1) /* avoid buffer overflows */ - const char *argstart,*argend; - char *dest; - int startnum,endnum,spc; +#define OUTPUTEND (output+MSGLEN-1) /* avoid buffer overflows */ +#define startnum n[0] +#define endnum n[1] + +void afmt(char *output, const char *src, const char *input) +{ + const char *argstart,*argend; + int spc,n[3]; - dest = copy_to; while(*src) { - if (src[0] == '$' && src[1] == '$') + if (*src == '$' && src[1] == '$') src++; else if (*src == '$' && src[1] == '~') { src += 2; argstart = CurrentNick; - while(*argstart && dest <= BUFTAIL) - *(dest++) = *(argstart++); + while(*argstart && output <= OUTPUTEND) + *(output++) = *(argstart++); } else - if (*src == '$' && (attrtab[(uchar)src[1]] & NUM) == NUM) + if (*src == '$' && (src[1] >= '0' && src[1] <= '9')) { src++; - startnum = endnum = 0; - while(attrtab[(uchar)*src] & NUM) - startnum = (startnum * 10) + (*(src++) - '0'); - if (*src == ' ' || *src == 0) - endnum = startnum; - else - if (*src == '-') - { - src++; - if ((attrtab[(uchar)*src] & NUM) != NUM) - endnum = 9999; - else - while(attrtab[(uchar)*src] & NUM) - endnum = (endnum * 10) + (*src++ - '0'); - } + parse_range((char**)&src,n); + if (n[2] && n[1] == -1) + endnum = 9999; argstart = input; if (startnum) @@ -154,25 +145,15 @@ void afmt(char *copy_to, const char *src, const char *input) argend++; } } -#ifdef DEBUG -#ifndef TEST - debug("(afmt) args #%i-#%i, characters %i-%i\n",startnum,endnum,argstart-input,argend-input); -#endif /* ifndef TEST */ -#endif /* DEBUG */ - while(*argstart && argstart < argend && dest <= BUFTAIL) - *(dest++) = *(argstart++); + while(*argstart && argstart < argend && output <= OUTPUTEND) + *(output++) = *(argstart++); continue; } - if (dest >= BUFTAIL) + if (output >= OUTPUTEND) break; - *(dest++) = *(src++); + *(output++) = *(src++); } - *dest = 0; -#ifdef DEBUG -#ifndef TEST - debug("(afmt) start %i end %i spc %i\n",startnum,endnum,spc); -#endif /* ifndef TEST */ -#endif /* DEBUG */ + *output = 0; } #ifndef TEST @@ -270,13 +251,14 @@ void do_alias(COMMAND_ARGS) set_mallocdoer(do_alias); alias = (Alias*)Calloc(sizeof(Alias)+strlen(cmd)); stringcpy(alias->alias,cmd); + alias->hash = mkhash(cmd); set_mallocdoer(do_alias); alias->format = stringdup(rest); 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); + debug("(do_alias) Added alias: %s [#%i] --> %s\n",cmd,alias->hash,rest); #endif } diff --git a/src/auth.c b/src/auth.c index 76cf49f..a7f6abc 100644 --- a/src/auth.c +++ b/src/auth.c @@ -63,7 +63,7 @@ char *cipher(char *arg) static char res[40]; uint32_t B1a,B2a,B3a,B4a; uint32_t B1b,B2b,B3b,B4b; - uchar *ptr; + unsigned char *ptr; uint32_t R1; int i; @@ -72,7 +72,7 @@ char *cipher(char *arg) B1a = B2a = B3a = B4a = 0; B1b = B2b = B3b = B4b = 0; - ptr = arg; + ptr = (unsigned char *)arg; while(*ptr) { @@ -259,7 +259,7 @@ void change_authnick(char *nuh, char *newnuh) set_mallocdoer(change_authnick); auth = (Auth*)Calloc(sizeof(Auth) + strlen(newnuh)); auth->user = oldauth->user; - auth->active = now; + auth->active = cx.now; auth->next = current->authlist; current->authlist = auth; stringcpy(auth->nuh,newnuh); @@ -271,10 +271,10 @@ void change_authnick(char *nuh, char *newnuh) } } -LS User *au_user; -LS const char *au_userhost; -LS const char *au_channel; -LS int au_access; +User *au_user; +const char *au_userhost; +const char *au_channel; +int au_access; void aucheck(User *user) { @@ -282,6 +282,7 @@ void aucheck(User *user) if (au_channel) { + /* does the user record have channel access? */ for(ump=user->chan;ump;ump=ump->next) { if (*ump->p == '*' || !stringcasecmp(au_channel,ump->p)) @@ -348,7 +349,7 @@ int get_authaccess(const char *userhost, const char *channel) User *user; Strp *ump; - if (userhost == CoreUser.name) + if (userhost == cx.CoreUser.name) return(100); if (CurrentDCC && CurrentDCC->user->name == userhost) { @@ -390,7 +391,7 @@ int make_auth(const char *userhost, const User *user) set_mallocdoer(make_auth); auth = (Auth*)Calloc(sizeof(Auth) + strlen(userhost)); auth->user = (User*)user; - auth->active = now; + auth->active = cx.now; stringcpy(auth->nuh,userhost); auth->next = current->authlist; @@ -418,6 +419,25 @@ int make_auth(const char *userhost, const User *user) * */ +void do_auth_noargs(const char *from) +{ + Auth *au; + + if (get_authaccess(from,MATCH_ALL) < 100) + return; + + /* no args + owner: List active auths */ + table_buffer("\037Active Auths\037"); + if (current->authlist == NULL) + table_buffer("(none)"); + for(au=current->authlist;au;au=au->next) + { + table_buffer("%s\t%i\t%s\t%s",au->user->name,au->user->x.x.access,au->nuh, + idle2str(au->active,TRUE)); + } + table_send(from,3); +} + /* help:AUTH help:VERIFY @@ -434,7 +454,6 @@ See also: passwd, setpass */ void do_auth(COMMAND_ARGS) { - Auth *au; #ifdef BOTNET char *checksum; #endif /* BOTNET */ @@ -443,22 +462,7 @@ void do_auth(COMMAND_ARGS) char *pass; int hostmatch; - if ((pass = chop(&rest)) == NULL) - { - if (get_authaccess(from,MATCH_ALL) == 100) - { - /* empty pass + owner: List active auths */ - table_buffer("\037Active Auths\037"); - if (current->authlist == NULL) - table_buffer("(none)"); - for(au=current->authlist;au;au=au->next) - { - table_buffer("%s\t%i\t%s\t%s",au->user->name,au->user->x.x.access,au->nuh,idle2str(now - au->active,TRUE)); - } - table_send(from,3); - } - return; - } + pass = chop(&rest); /* * chop chop diff --git a/src/bounce.c b/src/bounce.c index de2f651..7ccc237 100644 --- a/src/bounce.c +++ b/src/bounce.c @@ -45,16 +45,8 @@ #define BNC_ACTIVE 5 #define BNC_DEAD 6 -#ifdef IDWRAP - -#define USE_VHOST 2 - -#else /* not IDWRAP */ - #define USE_VHOST TRUE -#endif /* IDWRAP */ - void bounce_parse(ircLink *irc, char *message) { Mech fakebot; @@ -90,7 +82,7 @@ void bounce_parse(ircLink *irc, char *message) if (irc->userLine && irc->nickLine) { to_file(irc->usersock,TEXT_ASK_HANDLE,irc->nick); - irc->active = now; + irc->active = cx.now; ++irc->status; } return; @@ -143,7 +135,7 @@ void bounce_parse(ircLink *irc, char *message) { to_file(irc->usersock,TEXT_ASK_SERVER,irc->nick); irc->status = BNC_ASK_SERVER; - irc->active = now; + irc->active = cx.now; return; } } @@ -175,10 +167,6 @@ void bounce_parse(ircLink *irc, char *message) #ifdef WINGATE current->setting[STR_WINGATE].str_var = NULL; #endif /* WINGATE */ -#ifdef IDWRAP - current->identfile = NULL; - current->setting[STR_IDENT].str_var = irc->handle; -#endif /* IDWRAP */ if (virtual) { @@ -188,30 +176,15 @@ void bounce_parse(ircLink *irc, char *message) if ((irc->servsock = SockConnect(server,iport,USE_VHOST)) >= 0) { irc->status = BNC_CONNECTING; - irc->active = now + 60; /* 120 second timeout */ -#ifdef IDWRAP - irc->idfile = current->identfile; -#endif /* IDWRAP */ + irc->active = cx.now + 60; /* 120 second timeout */ } } } -#ifdef IDWRAP - -void bounce_cleanup(void) -{ - ircLink *irc; - - for(irc=bnclist;irc;irc=irc->next) - { - if (irc->idfile) - unlink(irc->idfile); - } -} - -#endif /* IDWRAP */ - -void new_port_bounce(const struct Setting *no_op) +/* + * any time setting is changed + */ +void new_port_bounce(const struct Setting *dontcare) { if (bounce_sock != -1) close(bounce_sock); @@ -276,7 +249,7 @@ void process_bounce(void) irc = (ircLink*)Calloc(sizeof(ircLink)); /* sets all to zero */ irc->next = bnclist; bnclist = irc; - irc->active = now; + irc->active = cx.now; irc->usersock = s; --irc->servsock; /* == -1 */ } @@ -324,7 +297,7 @@ void process_bounce(void) debug("(process_bounce) {%i} servsock connected\n",irc->servsock); #endif /* DEBUG */ irc->status = BNC_ACTIVE; - irc->active = now; + irc->active = cx.now; to_file(irc->servsock,"USER %s\n",irc->userLine); if (to_file(irc->servsock,"NICK %s\n",irc->nickLine) < 0) { @@ -341,7 +314,7 @@ void process_bounce(void) */ if (FD_ISSET(irc->servsock,&read_fds)) { - irc->active = now; + irc->active = cx.now; while((p = sockread(irc->servsock,irc->servmem,message))) { if (to_file(irc->usersock,FMT_PLAINLINE,message) < 0) @@ -365,7 +338,7 @@ void process_bounce(void) pp = &bnclist; while((irc = *pp)) { - if (irc->status == BNC_DEAD || ((irc->status != BNC_ACTIVE) && ((now - irc->active) > 60))) + if (irc->status == BNC_DEAD || ((irc->status != BNC_ACTIVE) && ((cx.now - irc->active) > 60))) { #ifdef DEBUG debug("(process_bounce) {%i} {%i} BNC_DEAD or timeout, removing...\n",irc->usersock,irc->servsock); @@ -379,13 +352,6 @@ void process_bounce(void) Free((char**)&irc->nickLine); Free((char**)&irc->nick); Free((char**)&irc->handle); -#ifdef IDWRAP - if (irc->idfile) - { - unlink(irc->idfile); - Free((char**)&irc->idfile); - } -#endif /* IDWRAP */ Free((char**)&irc); continue; } diff --git a/src/calc.c b/src/calc.c index 826fa4e..02de2d8 100644 --- a/src/calc.c +++ b/src/calc.c @@ -128,7 +128,6 @@ new_blank: op = 0; para = 0; -op_or_num: if (*input == '+') { op = OPER_ADD; @@ -204,9 +203,11 @@ iterate: para = -1; for(i=0;i<=cop_count;i++) { +#ifdef TEST if (cop[i].paralevel >= 0) printf("number %lu, operation %i, decimals %i, paralevel %i\n", cop[i].number,cop[i].operation,cop[i].decimals,cop[i].paralevel); +#endif /* TEST */ if (cop[i].paralevel >= para) para = cop[i].paralevel; } @@ -281,7 +282,7 @@ int bas2int(const char *src, int base) char ch; errno = EINVAL; - n = 0; + v = n = 0; while(*src) { @@ -291,22 +292,20 @@ int bas2int(const char *src, int base) switch(base) { case 16: - ch = tolowertab[(uchar)*src]; if (*src <= '9') v = *src - '0'; else - if (ch >= 'a' && ch <= 'f') - v = ch - 'a' + 10; - else - return(-1); + { + ch = tolowertab[(uchar)*src]; + if (ch >= 'a' && ch <= 'f') + v = ch - 'a' + 10; + else + return(-1); + } break; case 8: - if (*src >= '8') - return(-1); - v = *src - '0'; - break; case 2: - if (*src >= '2') + if(*src >= ('0'+base)) return(-1); v = *src - '0'; } @@ -329,7 +328,6 @@ void do_calc(COMMAND_ARGS) { char prep[MSGLEN]; CalcOp cop[MAX_COP]; - int cp = 0; memset(&cop,0,sizeof(cop)); @@ -345,22 +343,22 @@ void do_calc(COMMAND_ARGS) void do_convert(COMMAND_ARGS) { char output[200]; - char *ops, *srcnum, *dst; + char *srcnum, *dst; + char inval, outval; int num, todec, tochr, tooct, tohex, tobin; - ops = chop(&rest); - srcnum = chop(&rest); - - if (ops == NULL || srcnum == NULL) + if (cx.rest_end < rest+2) return; - todec = tochr = tooct = tohex = tobin = 0; + inval = rest[0]; + outval = rest[1]; + rest += 2; + srcnum = chop(&rest); - switch(ops[1]) + todec = tochr = tooct = tohex = tobin = (outval == ' ' || outval == 0) ? 0 : 1; + + switch(outval) { - case 0: - todec = tochr = tooct = tohex = tobin = 1; - break; case 'b': tobin = 1; break; @@ -375,19 +373,12 @@ void do_convert(COMMAND_ARGS) break; } + num = 0; errno = EINVAL; - switch(*ops) + switch(inval) { case 'b': - errno = 0; - for(num=0;*srcnum;) - { - num = num << 1; - if (*srcnum != '0' && *srcnum != '1') - return; - num += *srcnum - '0'; - srcnum++; - } + num = bas2int(srcnum,2); break; case 'c': num = srcnum[0]; @@ -396,8 +387,7 @@ void do_convert(COMMAND_ARGS) errno = tochr = 0; break; case 'd': - num = asc2int(srcnum); - /*todec = 0;*/ + num = asc2int(srcnum); /* sets errno */ break; case 'h': if (*srcnum == '$') @@ -405,11 +395,9 @@ void do_convert(COMMAND_ARGS) if (*srcnum == '0' && srcnum[1] == 'x') srcnum += 2; num = bas2int(srcnum,16); - /*tohex = 1;*/ break; case 'o': num = bas2int(srcnum,8); - /* tooct = 0;*/ break; } if (errno) diff --git a/src/channel.c b/src/channel.c index 05ce725..03f46bd 100644 --- a/src/channel.c +++ b/src/channel.c @@ -40,13 +40,15 @@ void check_idlekick(void) for(chan=current->chanlist;chan;chan=chan->next) { + if (!chan->bot_is_op) + continue; limit = chan->setting[INT_IKT].int_var; - timeout = (now - (60 * limit)); + if (limit == 0) + continue; + timeout = (cx.now - (60 * limit)); for(cu=chan->users;cu;cu=cu->next) { cu->flags &= ~CU_KSWARN; /* remove KS warnings */ - if (!chan->bot_is_op || limit == 0) - continue; if (cu->flags & CU_CHANOP) continue; if (timeout < cu->idletime) @@ -207,9 +209,9 @@ int reverse_mode(char *from, Chan *chan, int m, int s) mode = (char)m; sign = (char)s; - if (STRCHR(ptr,mode) && (sign == '+')) + if (stringchr(ptr,mode) && (sign == '+')) return(FALSE); - if (!STRCHR(ptr,mode) && (sign == '-')) + if (!stringchr(ptr,mode) && (sign == '-')) return(FALSE); if (get_useraccess(from,chan->name) >= ASSTLEVEL) { @@ -268,6 +270,12 @@ void chan_modestr(Chan *chan, char *dest) } } +char *get_nuh(const ChanUser *user) +{ + sprintf(nuh_buf,"%s!%s",user->nick,user->userhost); + return(nuh_buf); +} + char *find_nuh(char *nick) { Chan *chan; @@ -281,6 +289,36 @@ char *find_nuh(char *nick) return(NULL); } +/* + * NOTE! beware of conflicts in the use of nuh_buf, its also used by find_nuh() + */ +char *nick2uh(char *from, char *userhost) +{ + if (stringchr(userhost,'!') && stringchr(userhost,'@')) + { + stringcpy(nuh_buf,userhost); + } + else + if (!stringchr(userhost,'!') && !stringchr(userhost,'@')) + { + /* find_nuh() stores nickuserhost in nuh_buf */ + if (find_nuh(userhost) == NULL) + { + if (from) + to_user(from,"No information found for %s",userhost); + return(NULL); + } + } + else + { + stringcpy(nuh_buf,"*!"); + if (!stringchr(userhost,'@')) + stringcat(nuh_buf,"*@"); + stringcat(nuh_buf,userhost); + } + return(nuh_buf); +} + Ban *make_ban(Ban **banlist, char *from, char *banmask, time_t when) { Ban *new; @@ -359,7 +397,7 @@ void channel_massmode(const Chan *chan, char *pattern, int filtmode, char mode, if ((pat = chop(&pattern)) == NULL) return; - ispat = (STRCHR(pat,'*')) ? TRUE : FALSE; + ispat = (stringchr(pat,'*')) ? TRUE : FALSE; maxmode = current->setting[INT_MODES].int_var; mal = chan->setting[INT_MAL].int_var; *burst = 0; @@ -376,7 +414,7 @@ void channel_massmode(const Chan *chan, char *pattern, int filtmode, char mode, s = deopstring; while(*s) s++; debug("(...) deopstring "mx_pfmt" uh "mx_pfmt" ("mx_pfmt")\n",(mx_ptr)deopstring,(mx_ptr)uh,(mx_ptr)s); - s = STRCHR(deopstring,0); + s = stringchr(deopstring,0); debug("(...) deopstring "mx_pfmt" uh "mx_pfmt" ("mx_pfmt")\n",(mx_ptr)deopstring,(mx_ptr)uh,(mx_ptr)s); } #endif /* DEBUG */ @@ -427,7 +465,7 @@ void channel_massmode(const Chan *chan, char *pattern, int filtmode, char mode, /* * never deop yourself, stupid bot */ - if (nickcmp(pat,current->nick)) + if (nickcmp(pat,getbotnick(current))) willdo = TRUE; } else @@ -453,7 +491,7 @@ void channel_massmode(const Chan *chan, char *pattern, int filtmode, char mode, cu = cu->next; if (!cu && (pat = chop(&pattern))) { - ispat = (STRCHR(pat,'*')) ? TRUE : FALSE; + ispat = (stringchr(pat,'*')) ? TRUE : FALSE; cu = chan->users; } } @@ -499,7 +537,7 @@ void channel_massunban(Chan *chan, char *pattern, time_t seconds) { if (!matches(pattern,ban->banstring) || !matches(ban->banstring,pattern)) { - if (!seconds || ((now - ban->time) > seconds)) + if (!seconds || ((cx.now - ban->time) > seconds)) { if (chan->setting[TOG_SHIT].int_var) { @@ -643,7 +681,7 @@ void make_chanuser(char *nick, char *userhost) new = (ChanUser*)Calloc(sizeof(ChanUser) + strlen(userhost)); /* Calloc sets it all to zero */ - new->idletime = now; + new->idletime = cx.now; new->next = CurrentChan->users; CurrentChan->users = new; stringcpy(new->userhost,userhost); @@ -661,12 +699,6 @@ void purge_chanusers(Chan *chan) remove_chanuser(chan,chan->users->nick); } -char *get_nuh(const ChanUser *user) -{ - sprintf(nuh_buf,"%s!%s",user->nick,user->userhost); - return(nuh_buf); -} - /* * * commands associated with channels @@ -890,9 +922,10 @@ void do_mode(COMMAND_ARGS) } else { + /* todo: is it really necessary to chop? */ target = chop(&rest); - if (!nickcmp(current->nick,target)) + if (!nickcmp(target,getbotnick(current))) { to_server("MODE %s %s\n",target,rest); } @@ -972,7 +1005,7 @@ void do_cchan(COMMAND_ARGS) to_user(from,ERR_CHAN,channel); return; } - to_user(from,"Current channel: %s", + to_user_q(from,"Current channel: %s", (current->activechan) ? current->activechan->name : TEXT_NONE); } @@ -1185,9 +1218,9 @@ void do_showidle(COMMAND_ARGS) table_buffer(str_underline("Users on %s that are idle more than %i seconds"),chan->name,n); for(cu=chan->users;cu;cu=cu->next) { - if (n >= (now - cu->idletime)) + if (n >= (cx.now - cu->idletime)) continue; - table_buffer("%s\r %s\t%s",idle2str((now - cu->idletime),TRUE),cu->nick,cu->userhost); + table_buffer("%s\r %s\t%s",idle2str(cu->idletime,TRUE),cu->nick,cu->userhost); } table_send(from,1); } @@ -1218,5 +1251,5 @@ void do_idle(COMMAND_ARGS) to_user(from,TEXT_UNKNOWNUSER,rest); return; } - to_user(from,"%s has been idle for %s",rest,idle2str(now - cu2->idletime,TRUE)); + to_user(from,"%s has been idle for %s",rest,idle2str(cu2->idletime,TRUE)); } diff --git a/src/commands.h b/src/commands.h new file mode 100644 index 0000000..97db75f --- /dev/null +++ b/src/commands.h @@ -0,0 +1,277 @@ +/* + + EnergyMech, IRC bot software + Copyright (c) 1997-2025 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. + +*/ + +/* + + These are defined in config.h + + DCC 0x000100 requires DCC + CC 0x000200 requires commandchar + PASS 0x000400 requires password / authentication + CARGS 0x000800 requires args + NOPUB 0x001000 ignore in channel (for password commands) + NOCMD 0x002000 not allowed to be executed thru CMD + GAXS 0x004000 check global access + CAXS 0x008000 check channel access + REDIR 0x010000 may be redirected + LBUF 0x020000 can be linebuffered to server + CBANG 0x040000 command may be prefixed with a bang (!) + ACCHAN 0x080000 needs an active channel + SUPRES 0x100000 command is not suitable to run on many bots at once, try to suppress it + NOARGF 0x200000 run a special function if no arguments are supplied + + CLEVEL 0x000ff + +*/ + +#define CCPW CC|PASS + +struct CommandList +{ + int pass; /* multiple passes to sort & such */ + const char *name; + const char *func; + uint32_t flags; + char *cmdarg; + +} pre_mcmd[] = +{ + /* + * Level 0: public access commands, no CCPW + */ + { 0, "AUTH", "do_auth", 0 | NOPUB | CBANG | NOARGF }, // double up on AUTH/VERIFY to better + { 0, "VERIFY", "do_auth", 0 | NOPUB | CBANG | NOARGF }, // catch login attempts +#ifdef TOYBOX + { 0, "8BALL", "do_8ball", 0 | CBANG | SUPRES }, + { 0, "RAND", "do_rand", 0 | CBANG | SUPRES }, +#endif /* TOYBOX */ + { 0, "CV", "do_convert", 0 | CBANG | SUPRES }, + { 0, "CALC", "do_calc", 0 | CBANG | SUPRES }, + + /* + * Level 5: Semi-public commands, No PW required. CC included by default. + */ + { 0, "BYE", "do_bye", 5 }, + { 0, "DOWN", "do_opdeopme", 5 | CAXS }, +#ifdef DCC_FILE + { 0, "SEND", "do_send", 5 | NOCMD | CBANG | CARGS | LBUF }, +#endif /* DCC_FILE */ + + /* + * Level 10: All commands level 10+ PW by default (plus CC from Level 5+). + */ + { 0, "ACCESS", "do_access", 10 }, + { 0, "CHAT", "do_chat", 10 | NOCMD }, +#ifdef RAWDNS + { 0, "DNS", "do_dns", 10 | GAXS | CARGS | SUPRES }, +#endif /* RAWDNS */ + { 0, "ECHO", "do_echo", 10 | CARGS }, + { 0, "HELP", "do_help", 10 | REDIR | LBUF | SUPRES }, + { 0, "PASSWD", "do_passwd", 10 | NOPUB | CARGS }, + { 0, "USAGE", "do_usage", 10 | REDIR | CARGS }, + + /* + * Level 20 + */ + { 0, "ONTIME", "do_upontime", 20 , "Ontime: %s" }, + { 0, "UPTIME", "do_upontime", 20 , "Uptime: %s" }, + { 0, "VER", "do_version", 20 }, + { 0, "WHOM", "do_whom", 20 | REDIR | LBUF }, +#ifdef SEEN + { 0, "SEEN", "do_seen", 20 | CBANG }, +#endif /* SEEN */ +#ifdef URLCAPTURE + { 0, "URLHIST", "do_urlhist", 20 | REDIR | LBUF }, +#endif /* ifdef URLCAPTURE */ + + /* + * Level 40 + */ + { 0, "BAN", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x00ban\\0bann" }, + { 0, "BANLIST", "do_banlist", 40 | CAXS | DCC | REDIR | LBUF | ACCHAN }, + { 0, "CCHAN", "do_cchan", 40 | CCPW }, /* global_access ? */ + { 0, "CSERV", "do_cserv", 40 | CCPW }, + { 0, "CHANNELS", "do_channels", 40 | CCPW | DCC }, + { 0, "DEOP", "do_opvoice", 40 | CAXS | CARGS , "o-" }, + { 0, "ESAY", "do_esay", 40 | CAXS | CARGS }, + { 0, "IDLE", "do_idle", 40 | CCPW | CARGS }, + { 0, "INVITE", "do_invite", 40 | CAXS | ACCHAN }, + { 0, "KB", "do_kickban", 40 | CAXS | CARGS | ACCHAN , "\\x04kickban\\0kickbann" }, + { 0, "KICK", "do_kickban", 40 | CAXS | CARGS | ACCHAN , "\\x07kick\\0kick" }, + { 0, "LUSERS", "do_irclusers", 40 | CCPW | DCC | REDIR | LBUF }, + { 0, "ME", "do_sayme", 40 | CCPW | CARGS }, + { 0, "MODE", "do_mode", 40 | CCPW | CARGS }, + { 0, "NAMES", "do_names", 40 | CCPW }, + { 0, "OP", "do_opvoice", 40 | CAXS , "o+" }, + { 0, "SAY", "do_sayme", 40 | CCPW | CARGS }, + { 0, "SCREW", "do_kickban", 40 | CAXS | CARGS | ACCHAN , "\\x02screwban\\0screwbann" }, + { 0, "SET", "do_set", 40 | CCPW }, + { 0, "SITEBAN", "do_kickban", 40 | CAXS | CARGS | ACCHAN , "\\x01siteban\\0sitebann" }, + { 0, "SITEKB", "do_kickban", 40 | CAXS | CARGS | ACCHAN , "\\x05sitekickban\\0sitekickbann" }, + { 0, "TIME", "do_time", 40 | CCPW }, + { 0, "TOPIC", "do_topic", 40 | CAXS | CARGS | ACCHAN | SUPRES }, + { 0, "UNBAN", "do_unban", 40 | CAXS }, + { 0, "UNVOICE", "do_opvoice", 40 | CAXS | CARGS , "v-" }, + { 0, "UP", "do_opdeopme", 40 | CAXS }, + { 0, "USER", "do_user", 40 | CCPW | CARGS }, + { 0, "USERHOST", "do_ircwhois", 40 | CCPW | CARGS }, + { 0, "VOICE", "do_opvoice", 40 | CAXS , "v+" }, + { 0, "WALL", "do_wall", 40 | CCPW | CAXS | CARGS | ACCHAN }, + { 0, "WHO", "do_who", 40 | CCPW | CAXS | DCC }, + { 0, "WHOIS", "do_ircwhois", 40 | CCPW | CARGS | DCC | REDIR | LBUF }, +#ifdef NOTE + { 0, "NOTE", "do_note", 40 | CCPW | CARGS }, + { 0, "READ", "do_read", 40 | CCPW }, +#endif /* NOTE */ +#ifdef STATS + { 0, "INFO", "do_info", 40 | CCPW | REDIR | CAXS | DCC }, +#endif /* STATS */ + + /* + * Level 50 + */ + { 0, "QSHIT", "do_shit", 50 | CCPW | CARGS }, + { 0, "RSHIT", "do_rshit", 50 | CCPW | CARGS }, + { 0, "SHIT", "do_shit", 50 | CCPW | CARGS }, + { 0, "SHITLIST", "do_shitlist", 50 | CCPW | DCC | REDIR | LBUF }, +#ifdef GREET + { 0, "GREET", "do_greet", 50 | CCPW | CARGS }, +#endif /* GREET */ +#ifdef TOYBOX + { 0, "INSULT", "do_randmsg", 50 | CCPW , RANDINSULTFILE }, + { 0, "PICKUP", "do_randmsg", 50 | CCPW , RANDPICKUPFILE }, + { 0, "RSAY", "do_randmsg", 50 | CCPW , RANDSAYFILE }, + { 0, "RT", "do_randtopic", 50 | CCPW | CAXS | ACCHAN }, + { 0, "ASCII", "do_ascii", 50 | CCPW | CAXS | CARGS | SUPRES }, +#endif /* TOYBOX */ +#ifdef TRIVIA + { 0, "TRIVIA", "do_trivia", 50 | CCPW | CAXS | CARGS | CBANG }, +#endif /* TRIVIA */ + + /* + * Level 60 + */ + { 0, "SHOWIDLE", "do_showidle", 60 | CAXS | DCC | ACCHAN }, + { 0, "USERLIST", "do_userlist", 60 | DCC }, +#ifdef CTCP + { 0, "CTCP", "do_ping_ctcp", 60 | CARGS }, + { 0, "PING", "do_ping_ctcp", 60 | CARGS }, +#endif /* CTCP */ + + /* + * Level 70 == JOINLEVEL + */ + { 0, "CYCLE", "do_cycle", 70 | CAXS | ACCHAN }, + { 0, "FORGET", "do_forget", 70 | CAXS }, + { 0, "JOIN", "do_join", 70 | CARGS }, + { 0, "KS", "do_kicksay", 70 | REDIR | LBUF }, + { 0, "PART", "do_part", 70 | CAXS | ACCHAN }, + { 0, "RKS", "do_rkicksay", 70 | CARGS }, + { 0, "SETPASS", "do_setpass", 70 | NOPUB | CARGS }, +#ifdef NOTIFY + { 0, "NOTIFY", "do_notify", 70 | DCC | GAXS | REDIR | LBUF }, +#endif /* NOTIFY */ + + /* + * Level 80 == ASSTLEVEL + */ + { 0, "AWAY", "do_away", 80 | GAXS }, + { 0, "BOOT", "do_boot", 80 | GAXS | CARGS }, +#if defined(BOTNET) && defined(REDIRECT) + { 0, "CMD", "do_cmd", 80 | CARGS }, +#endif /* BOTNET && REDIRECT */ + { 0, "CQ", "do_clearqueue", 80 | GAXS }, + { 0, "LAST", "do_last", 80 | DCC }, + { 0, "LOAD", "do_load", 80 | GAXS }, + { 0, "MSG", "do_msg", 80 | CARGS }, + { 0, "NEXTSERVER", "do_server", 80 | CCPW | GAXS }, + { 0, "SAVE", "do_save", 80 | CCPW | GAXS }, + { 0, "SERVER", "do_server", 80 | CCPW | GAXS | REDIR | NOPUB | NOARGF }, + { 0, "STATS", "do_ircstats", 80 | CCPW | DCC | CARGS }, +#ifdef ALIAS + { 0, "ALIAS", "do_alias", 80 | CCPW | GAXS }, + { 0, "UNALIAS", "do_unalias", 80 | CCPW | GAXS | CARGS }, +#endif /* ALIAS */ +#ifdef TOYBOX + { 0, "BIGSAY", "do_bigsay", 80 | CCPW | CAXS | CARGS | SUPRES }, +#endif /* TOYBOX */ + + /* + * Level 90 + */ + { 0, "CLEARSHIT", "do_clearshit", 90 | CCPW | GAXS }, + { 0, "DO", "do_do", 90 | CCPW | GAXS | CARGS }, + { 0, "NICK", "do_nick", 90 | CCPW | GAXS | CARGS }, + { 0, "RSPY", "do_rspy", 90 | CCPW | CARGS }, + { 0, "SPY", "do_spy", 90 | CCPW }, +#ifdef BOTNET + { 0, "LINK", "do_link", 90 | CCPW | GAXS | NOPUB | NOARGF }, +#endif /* BOTNET */ +#ifdef DYNCMD + { 0, "CHACCESS", "do_chaccess", 90 | CCPW | GAXS | CARGS }, +#endif /* DYNCMD */ +#ifdef UPTIME + { 0, "UPSEND", "do_upsend", 90 | CCPW | GAXS }, +#endif /* UPTIME */ + + /* + * Level 100 + */ +#ifdef HOSTINFO + { 0, "SYSINFO", "do_sysinfo", 100 | CCPW | GAXS }, + { 0, "MEMINFO", "do_meminfo", 100 | CCPW | GAXS }, + { 0, "CPUINFO", "do_cpuinfo", 100 | CCPW | GAXS }, + { 0, "FILEMON", "do_filemon", 100 | CCPW | GAXS | CARGS }, +#endif /* HOSTINFO */ +#ifdef RAWDNS + { 0, "DNSSERVER", "do_dnsserver", 100 | CCPW | GAXS }, + { 0, "DNSROOT", "do_dnsroot", 100 | CCPW | GAXS | CARGS }, +#endif /* RAWDNS */ + { 0, "CORE", "do_core", 100 | CCPW | REDIR | DCC }, + { 0, "DIE", "do_die", 100 | CCPW | GAXS }, + { 0, "RESET", "do_reset", 100 | CCPW | GAXS | NOCMD }, + { 0, "SHUTDOWN", "do_shutdown", 100 | CCPW | GAXS | NOPUB | NOCMD }, +#ifdef DEBUG + { 0, "DEBUG", "do_debug", 100 | CCPW | GAXS }, + { 0, "CRASH", "do_crash", 100 | CCPW | GAXS }, + { 0, "INJECT", "do_inject", 100 | CCPW | CARGS | GAXS }, +#endif /* DEBUG */ +#ifdef PERL +#ifdef PLEASE_HACK_MY_SHELL + { 0, "PERL", "do_perl", 100 | CCPW | GAXS | CARGS }, +#endif /* PLEASE_HACK_MY_SHELL */ + { 0, "PERLSCRIPT", "do_perlscript", 100 | CCPW | GAXS | CARGS }, +#endif /* PERL */ +#ifdef PYTHON +#ifdef PLEASE_HACK_MY_SHELL + { 0, "PYTHON", "do_python", 100 | CCPW | GAXS | CARGS }, +#endif /* PLEASE_HACK_MY_SHELL */ + { 0, "PYTHONSCRIPT", "do_pythonscript", 100 | CCPW | GAXS | CARGS }, +#endif /* PYTHON */ +#ifdef TCL +#ifdef PLEASE_HACK_MY_SHELL + { 0, "TCL", "do_tcl", 100 | CCPW | GAXS | CARGS }, +#endif /* PLEASE_HACK_MY_SHELL */ + { 0, "TCLSCRIPT", "do_tcl", 100 | CCPW | GAXS | CARGS }, +#endif /* TCL */ + /*---*/ + { 0, NULL, NULL, 0 }, +}; diff --git a/src/config.h.in b/src/config.h.in index b0d3438..c33f102 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -71,12 +71,6 @@ */ @DEF_HOSTINFO@ -/* - * IDWRAP: support for idwrap ident spoofing - */ -@DEF_IDWRAP@ -#define IDWRAP_PATH @IDWRAP_PATH@ - /* * IRCD_EXTENSIONS: support some special features of new ircds */ @@ -103,7 +97,7 @@ @DEF_DCCFILE@ #define DCC_PUBLICFILES "public/" #define DCC_PUBLICINCOMING DCC_PUBLICFILES "incoming/" -#define DCC_FILETIMEOUT 90 +#define DCCFILE_TIMEOUT 90 /* * REDIRECT: send command output from certain commands to a different target @@ -195,7 +189,7 @@ /* * URLCAPTURE: capture url's mentioned */ -@DEF_URLCAPTURE@ +@DEF_URLCAP@ /* * WEB: serving documents via HTTP @@ -322,8 +316,8 @@ #define AWAYFORM "AWAY :%s (since %s)\n" -#define KILLSOCKTIMEOUT 30 -#define WAITTIMEOUT 30 +#define KILLSOCK_TIMEOUT 30 +#define WAIT_TIMEOUT 30 #define NICKFLOODTIME 120 /* 240 second window for floods ( 240 / 2 = 120 ) */ @@ -361,6 +355,9 @@ #define NAMELEN 79 #define NAMEBUF NAMELEN+1 +#define SERVERGROUPBUF 16 +#define SERVERGROUPLEN SERVERGROUPBUF-1 + #define MINPASSCHARS 4 #define MAXPASSCHARS 50 @@ -400,6 +397,7 @@ #define CBANG 0x040000 /* command may be prefixed with a bang (!) */ #define ACCHAN 0x080000 /* needs an active channel */ #define SUPRES 0x100000 /* command is not suitable to run on many bots at once, try to suppress it */ +#define NOARGF 0x200000 /* run a special function if no arguments are supplied */ /* * integer only version of RANDOM() @@ -604,6 +602,13 @@ const char __mx_opts[] = "" #undef OPT_COREONLY #endif /* TRIVIA */ +#ifdef UPTIME + OPT_COMMA "uptime" +#undef OPT_COMMA +#define OPT_COMMA ", " +#undef OPT_COREONLY +#endif /* UPTIME */ + #ifdef WINGATES OPT_COMMA "wingate" #undef OPT_COMMA diff --git a/src/core.c b/src/core.c index e667c75..ea7f621 100644 --- a/src/core.c +++ b/src/core.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2024 proton + Parts Copyright (c) 1997-2025 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 @@ -33,22 +33,6 @@ #include #endif /* HOSTINFO */ -#ifdef IDWRAP - -void unlink_identfile(void) -{ - if (current->identfile) - { -#ifdef DEBUG - debug("(unlink_identfile) unlink(%s)\n",current->identfile); -#endif /* DEBUG */ - unlink(current->identfile); - Free((char**)¤t->identfile); - } -} - -#endif /* IDWRAP */ - int conf_callback(char *line) { @@ -57,7 +41,7 @@ int conf_callback(char *line) fix_config_line(line); - on_msg((char*)CoreUser.name,current->nick,line); + on_msg((char*)cx.CoreUser.name,getbotnick(current),line); return(FALSE); } @@ -95,7 +79,7 @@ void readcfgfile(void) CurrentShit = NULL; CurrentChan = NULL; CurrentDCC = (Client*)&CoreClient; - CurrentUser = (User*)&CoreUser; + CurrentUser = (User*)&cx.CoreUser; readline(in,&conf_callback); /* readline closes in */ @@ -108,7 +92,7 @@ void readcfgfile(void) } if ((current) && (current->chanlist == NULL)) - to_file(1,"%s %s will not join any channels\n",ERR_INIT,current->nick); + to_file(1,"init: Warning: %s will not join any channels\n",getbotnick(current)); oc = 0; #ifdef DEBUG @@ -123,8 +107,8 @@ void readcfgfile(void) to_file(1,", ..."); break; } - to_file(1,"%s%s",(oc > 0) ? ", " : "",bot->nick); - oc += strlen(bot->nick); + to_file(1,"%s%s",(oc > 0) ? ", " : EMPTYSTR,getbotnick(bot)); + oc += getbotnicklen(bot); } to_file(1," ]\n"); #ifdef DEBUG @@ -168,7 +152,7 @@ int write_session(void) for(sp=serverlist;sp;sp=sp->next) { to_file(sf,"server %s %i %s\n",sp->name,(sp->port) ? sp->port : 6667, - (sp->pass[0]) ? sp->pass : ""); + (sp->pass[0]) ? sp->pass : EMPTYSTR); } #ifdef BOTNET @@ -243,7 +227,7 @@ int write_session(void) for(bot=botlist;bot;bot=bot->next) { - to_file(sf,"nick %i %s\n",bot->guid,bot->wantnick); + to_file(sf,"nick %i %s\n",bot->guid,getbotwantnick(bot)); /* * current->setting contains channel defaults and global vars */ @@ -277,7 +261,7 @@ int write_session(void) { if (!chan->active && !chan->rejoin) continue; - to_file(sf,"join %s %s\n",chan->name,(chan->key) ? chan->key : ""); + to_file(sf,"join %s %s\n",chan->name,(chan->key) ? chan->key : EMPTYSTR); /* * using CHANSET_SIZE: only the first settings contain stuff */ @@ -327,22 +311,6 @@ int write_session(void) * Bot nicking, adding and killing */ -void setbotnick(Mech *bot, char *nick) -{ - /* - * if its exactly the same we dont need to change it - */ - if (!stringcmp(bot->nick,nick)) - return; - - Free((char**)&bot->nick); - set_mallocdoer(setbotnick); - bot->nick = stringdup(nick); -#ifdef BOTNET - botnet_refreshbotinfo(); -#endif /* BOTNET */ -} - Mech *add_bot(int guid, char *nick) { Mech *bot; @@ -352,10 +320,8 @@ Mech *add_bot(int guid, char *nick) bot->connect = CN_NOSOCK; bot->sock = -1; bot->guid = guid; - set_mallocdoer(add_bot); - bot->nick = stringdup(nick); - set_mallocdoer(add_bot); - bot->wantnick = stringdup(nick); + setbotnick(bot,nick); + setbotwantnick(bot,nick); set_binarydefault(bot->setting); bot->next = botlist; botlist = bot; @@ -375,7 +341,7 @@ void signoff(char *from, char *reason) if (from) { - to_user(from,"Killing mech: %s",current->nick); + to_user(from,"Killing mech: %s",getbotnick(current)); to_user(from,"Saving the lists..."); } fname = current->setting[STR_USERFILE].str_var; @@ -419,12 +385,9 @@ void signoff(char *from, char *reason) if (current->sock != -1) { -#ifdef IDWRAP - unlink_identfile(); -#endif /* IDWRAP */ if (!reason) reason = randstring(SIGNOFFSFILE); - to_server("QUIT :%s\n",(reason) ? reason : ""); + to_server("QUIT :%s\n",(reason) ? reason : EMPTYSTR); killsock(current->sock); current->sock = -1; } @@ -451,9 +414,6 @@ void signoff(char *from, char *reason) /* * little of this n that */ - Free((char**)¤t->nick); - Free((char**)¤t->wantnick); - Free((char**)¤t->userhost); /* * These 2 are used by do_die() to pass reason and doer. @@ -481,10 +441,6 @@ void signoff(char *from, char *reason) */ if ((current = botlist) == NULL) { -#if defined(BOUNCE) && defined(IDWRAP) - bounce_cleanup(); -#endif /* BOUNCE && IDWRAP */ - #ifdef TRIVIA write_triviascore(); #endif /* TRIVIA */ @@ -517,10 +473,13 @@ void kill_all_bots(char *reason) /* * Server lists, connects, etc... */ -Server *add_server(char *host, int port, char *pass) +Server *add_server(const char *host, const int port, const char *pass, const char *group) { Server *sp,**pp; +#ifdef DEBUG + debug("(add_server) host = %s, port = %i, group = %s, pass = '%s'.\n",host,port,group,pass); +#endif /* DEBUG */ pp = &serverlist; while(*pp) { @@ -529,42 +488,21 @@ Server *add_server(char *host, int port, char *pass) return(sp); pp = &sp->next; } +#ifdef DEBUG + debug("(add_server) creating new entry: id %i.\n",serverident+1); +#endif /* DEBUG */ set_mallocdoer(add_server); *pp = sp = (Server*)Calloc(sizeof(Server)); sp->ident = serverident++; + sp->maxontime = -1; + /* caller must make sure host, pass, port and group is all valid */ stringcpy_n(sp->name,host,NAMELEN); - if (pass && *pass) - stringcpy_n(sp->pass,pass,PASSLEN); - sp->port = (port) ? port : DEFAULT_IRC_PORT; - if (currentservergroup) - sp->servergroup = currentservergroup->servergroup; + stringcpy_n(sp->pass,pass,PASSLEN); + stringcpy_n(sp->group,group,SERVERGROUPLEN); + sp->port = port; return(sp); } -ServerGroup *getservergroup(const char *name) -{ - ServerGroup *sg; - - for(sg=servergrouplist;sg;sg=sg->next) - { - if (!stringcasecmp(sg->name,name)) - return(sg); - } - return(NULL); -} - -ServerGroup *getservergroupid(int id) -{ - ServerGroup *sg; - - for(sg=servergrouplist;sg;sg=sg->next) - { - if (sg->servergroup == id) - return(sg); - } - return(NULL); -} - Server *find_server(int id) { Server *sp; @@ -589,7 +527,7 @@ int try_server(Server *sp, char *hostname) hostname = sp->name; } - sp->lastattempt = now; + sp->lastattempt = cx.now; sp->usenum++; #ifdef RAWDNS @@ -606,7 +544,7 @@ int try_server(Server *sp, char *hostname) { current->server = sp->ident; current->connect = CN_DNSLOOKUP; - current->conntry = now; + current->conntry = cx.now; rawdns(hostname); return(0); } @@ -619,24 +557,22 @@ int try_server(Server *sp, char *hostname) } current->away = FALSE; current->connect = CN_TRYING; - current->activity = current->conntry = now; + current->activity = current->conntry = cx.now; *current->modes = 0; return(current->sock); } void connect_to_server(void) { - ServerGroup *sg; Server *sp,*sptry; Chan *chan; - char *s; - int sgi; + char *sgroup; /* * This should prevent the bot from chewing up too * much CPU when it fails to connect to ANYWHERE */ - current->conntry = now; + current->conntry = cx.now; /* * Is this the proper action if there is no serverlist? @@ -678,64 +614,54 @@ void connect_to_server(void) * The purpose of this kludge is to find the least used server * July 7th: added logic for servergroup */ - sptry = NULL; - if ((s = current->setting[STR_SERVERGROUP].str_var)) + if ((sgroup = current->setting[STR_SERVERGROUP].str_var)) { - if ((sg = getservergroup(s))) - sgi = sg->servergroup; #ifdef DEBUG - if (sg) - debug("[CtS] trying servergroup \"%s\" (%i)\n",s,sg->servergroup); - else - debug("[CtS] trying servergroup \"%s\" (not found)\n",s); + debug("[CtS] servergroup set to \"%s\"\n",sgroup); #endif /* DEBUG */ } - else - { - sgi = 0; - } + sptry = NULL; for(sp=serverlist;sp;sp=sp->next) { - if ((sgi == 0 || sp->servergroup == sgi || sp->servergroup == 0) && sp->lastattempt != now) - { - if ((!sptry) || (sp->usenum < sptry->usenum)) - { - if (sp->err == 0 || sp->err == SP_ERRCONN) - sptry = sp; - else - if ( - (sp->err == SP_THROTTLED && (sp->lastattempt + 45) < now) || /* retry throttled after 45 seconds */ - (sp->err == SP_KLINED && (sp->lastattempt + 86400) < now) /* retry Klined after a day */ - ) - sptry = sp; - } - } + if (sp->lastattempt == cx.now) + continue; + if (sgroup && (stringcasecmp(sgroup,sp->group) != 0)) + continue; + if (sptry && (sp->usenum > sptry->usenum)) + continue; + + if (sp->err == 0 || sp->err == SP_ERRCONN) + sptry = sp; + else + if ((sp->err == SP_THROTTLED && (sp->lastattempt + 45) < cx.now) || /* retry throttled after 45 seconds */ + (sp->err == SP_KLINED && (sp->lastattempt + 86400) < cx.now)) /* retry Klined after a day */ + sptry = sp; } /* * Connect... */ if (sptry) - try_server(sptry,NULL); - else { -#ifdef DEBUG - const char *errtxt; - - if (current->connect != CN_SPINNING) - { - debug("[CtS] Serverlist Exhausted:\n"); - for(sp=serverlist;sp;sp=sp->next) - { - errtxt = (const char *[]){"No error","SP_NOAUTH","SP_KLINED","SP_FULLCLASS", - "SP_TIMEOUT","SP_ERRCONN","SP_DIFFPORT","SP_NO_DNS","SP_THROTTLED"}[sp->err]; - debug("[CtS] (%i) %s[%i]: %s(%i) / servergroup %i\n",sp->ident,(sp->realname[0]) ? sp->realname : sp->name, - sp->port,errtxt,sp->err,sp->servergroup); - } - debug("[CtS] Server connection is spinning...\n"); - } - current->connect = CN_SPINNING; -#endif /* DEBUG */ + try_server(sptry,NULL); + return; } +#ifdef DEBUG + if (current->connect != CN_SPINNING) + { + const char *errtxt; + debug("[CtS] Serverlist Exhausted:\n"); + for(sp=serverlist;sp;sp=sp->next) + { + errtxt = (const char *[]){"No error","SP_NOAUTH","SP_KLINED","SP_FULLCLASS", + "SP_TIMEOUT","SP_ERRCONN","SP_DIFFPORT","SP_NO_DNS","SP_THROTTLED"}[sp->err]; + debug("[CtS] (%i) %s[%i]: %s(%i) / servergroup %i\n",sp->ident, + (*sp->realname) ? sp->realname : sp->name, + sp->port,errtxt,sp->err,sp->group); + } + debug("[CtS] Server connection is spinning...\n"); + } + current->connect = CN_SPINNING; +#endif /* DEBUG */ } /* @@ -758,12 +684,12 @@ void register_with_server(void) sendpass = (sp && *sp->pass); to_server((sendpass) ? "PASS :%s\nNICK %s\nUSER %s " MECHUSERLOGIN " 0 :%s\n" : "%sNICK %s\nUSER %s " MECHUSERLOGIN " 0 :%s\n", - (sendpass) ? sp->pass : "", - current->wantnick, + (sendpass) ? sp->pass : EMPTYSTR, + getbotwantnick(current), (ident) ? ident : BOTLOGIN, (ircname) ? ircname : VERSION); current->connect = CN_CONNECTED; - current->conntry = now; + current->conntry = cx.now; } /* @@ -802,7 +728,7 @@ int sub_compile_timer(int limit, uint32_t *flags1, uint32_t *flags2, char *args) s = chop(&args); if (s && *s) { - if ((dash = STRCHR(s,'-'))) + if ((dash = stringchr(s,'-'))) { *(dash++) = 0; if (!*dash) @@ -881,7 +807,7 @@ typedef struct //using that struct, calculate when the next time will be //start by determining what the time is now - thistime = now; + thistime = cx.now; //which second is it thissecond = thistime % 60; @@ -960,26 +886,26 @@ void update(SequenceTime *this) int tt,th; int x,n; - tt = now / 600; /* current 10-minute period */ - th = tt / 6; /* current hour */ + tt = cx.now / 600; /* current 10-minute period */ + th = tt / 6; /* current hour */ #ifdef DEBUG x = 0; if (tt != this->tenminute) { - debug("(update) running: ten minute updates [%i]",tt); + debug("(update) running: ten minute update [%i]",tt); x++; } if (th != this->hour) { - debug("%shour updates [%i]",(x) ? ", " : "(update) running: ",th); + debug("%shour update [%i]",(x) ? ", " : "(update) running: ",th); x++; } if (x) debug("\n"); #endif /* DEBUG */ - short_tv &= ~TV_REJOIN; + cx.short_tv &= ~TV_REJOIN; for(current=botlist;current;current=current->next) { if (current->reset || current->connect != CN_ONLINE) @@ -987,12 +913,12 @@ void update(SequenceTime *this) if (current->rejoin) { - if ((now - current->lastrejoin) > REJOIN_DELAY) + if ((cx.now - current->lastrejoin) > REJOIN_DELAY) { current->rejoin = FALSE; - current->lastrejoin = now; + current->lastrejoin = cx.now; } - short_tv |= TV_REJOIN; + cx.short_tv |= TV_REJOIN; } #ifdef NOTIFY @@ -1031,18 +957,18 @@ void update(SequenceTime *this) check_dynamode(chan); #endif /* DYNAMODE */ } - if ((now - current->lastreset) > RESETINTERVAL) + if ((cx.now - current->lastreset) > RESETINTERVAL) { - current->lastreset = now; - if (stringcmp(current->nick,current->wantnick)) - to_server("NICK %s\n",current->wantnick); + current->lastreset = cx.now; + if (stringcmp(getbotnick(current),getbotwantnick(current))) + to_server("NICK %s\n",getbotwantnick(current)); check_idlekick(); if ((x = current->setting[INT_AAWAY].int_var) && current->away == FALSE) { - if ((now - current->activity) > (x * 60)) + if ((cx.now - current->activity) > (x * 60)) { temp = randstring(AWAYFILE); - to_server(AWAYFORM,(temp && *temp) ? temp : "auto-away",time2away(now)); + to_server(AWAYFORM,(temp && *temp) ? temp : "auto-away",maketimestr(cx.now,TFMT_AWAY)); current->away = TRUE; } } @@ -1073,10 +999,8 @@ void update(SequenceTime *this) temp = TEXT_NOTINSERVLIST; if ((sp = find_server(current->server))) { - int ot = (uint32_t)(now - current->ontime); - - if (sp->maxontime < ot) - sp->maxontime = ot; + if (sp->maxontime > current->ontime) + sp->maxontime = current->ontime; sprintf(globaldata,"%s:%i",(*sp->realname) ? sp->realname : sp->name,sp->port); temp = globaldata; } @@ -1134,10 +1058,10 @@ void process_server_input(void) if (FD_ISSET(current->sock,&write_fds)) { - setbotnick(current,current->wantnick); + setbotnick(current,getbotwantnick(current)); #ifdef DEBUG debug("[PSI] {%i} connection established (%s) [ASYNC]\n", - current->sock,current->wantnick); + current->sock,getbotwantnick(current)); #endif /* DEBUG */ #ifdef WINGATE if ((current->vhost_type & VH_WINGATE_BOTH) == VH_WINGATE) @@ -1161,7 +1085,7 @@ void process_server_input(void) current->vhost_type |= VH_WINGATE_FAIL; } current->connect = CN_WINGATEWAIT; - current->conntry = now; + current->conntry = cx.now; current->heartbeat = 0; return; } @@ -1170,10 +1094,6 @@ void process_server_input(void) * send NICK, USER and maybe PASS */ register_with_server(); -#ifdef IDWRAP - if (current->sock == -1) - unlink_identfile(); -#endif /* IDWRAP */ return; } if (FD_ISSET(current->sock,&read_fds)) @@ -1199,7 +1119,7 @@ get_line: } } #endif /* WINGATE */ - current->conntry = now; + current->conntry = cx.now; current->heartbeat = 0; parse_server_input(linebuf); goto get_line; @@ -1215,7 +1135,7 @@ get_line: } /* server has been quiet for too long */ - if (current->conntry + SERVERSILENCETIMEOUT <= now && current->heartbeat == 0) + if (current->conntry + SERVERSILENCETIMEOUT <= cx.now && current->heartbeat == 0) { #ifdef DEBUG debug("[PSI] {%i} server has been quiet for too long (%is)...\n",current->sock,SERVERSILENCETIMEOUT); @@ -1226,7 +1146,7 @@ get_line: } /* server has been quiet for WAY too long */ - if (current->conntry + (SERVERSILENCETIMEOUT*2) <= now) + if (current->conntry + (SERVERSILENCETIMEOUT*2) <= cx.now) { #ifdef DEBUG debug("[PSI] {%i} server has been quiet for WAY too long (%is), forcing reconnect...\n",current->sock,SERVERSILENCETIMEOUT*2); @@ -1242,11 +1162,10 @@ breaksock: #ifdef DEBUG debug("[PSI] {%i} errno = %i; closing server socket\n",current->sock,errno); #endif /* DEBUG */ +#ifdef WINGATE breaksock2: +#endif /* WINGATE */ *current->sockdata = 0; -#ifdef IDWRAP - unlink_identfile(); -#endif /* IDWRAP */ close(current->sock); current->sock = -1; current->connect = CN_NOSOCK; @@ -1266,15 +1185,16 @@ void do_version(COMMAND_ARGS) void do_core(COMMAND_ARGS) { + char tmp[MSGLEN]; #ifdef HOSTINFO char *h,hostname[256]; struct utsname un; #endif /* HOSTINFO */ - char tmp[MSGLEN]; /* big buffers at the top */ + const char *extra; Server *sp; Chan *chan; User *user; - char *pt; + char *pt; int i,u,su,bu; u = su = bu = 0; @@ -1287,11 +1207,16 @@ void do_core(COMMAND_ARGS) bu++; } - i = stringcmp(current->nick,current->wantnick); + *tmp = 0; + if (*current->modes) + { + sprintf(tmp," (+%s)",current->modes); + } + i = stringcmp(getbotnick(current),getbotwantnick(current)); if (i) - table_buffer(TEXT_CURRNICKWANT,current->nick,current->wantnick,current->guid); + table_buffer(TEXT_CURRNICKWANT,getbotnick(current),tmp,getbotwantnick(current),current->guid); else - table_buffer(TEXT_CURRNICKHAS,current->nick,current->guid); + table_buffer(TEXT_CURRNICKHAS,getbotnick(current),tmp,current->guid); table_buffer(TEXT_USERLISTSTATS,u,su,EXTRA_CHAR(su),bu,EXTRA_CHAR(bu)); pt = tmp; @@ -1325,30 +1250,29 @@ void do_core(COMMAND_ARGS) if (current->setting[STR_VIRTUAL].str_var) { if ((current->vhost_type & VH_IPALIAS_FAIL) == 0) - pt = ""; + extra = EMPTYSTR; else - pt = TEXT_VHINACTIVE; - table_buffer(TEXT_VIRTHOST,current->setting[STR_VIRTUAL].str_var,pt); + extra = TEXT_VHINACTIVE; + table_buffer(TEXT_VIRTHOST,current->setting[STR_VIRTUAL].str_var,extra); } #ifdef WINGATE if (current->setting[STR_WINGATE].str_var && current->setting[INT_WINGPORT].int_var) { if ((current->vhost_type & VH_WINGATE_FAIL) == 0) - pt = ""; + extra = EMPTYSTR; else - pt = TEXT_VHINACTIVE; + extra = TEXT_VHINACTIVE; table_buffer(TEXT_VIRTHOSTWINGATE,current->setting[STR_WINGATE].str_var, - current->setting[INT_WINGPORT].int_var,pt); + current->setting[INT_WINGPORT].int_var,extra); } #endif /* WINGATE */ sp = find_server(current->server); if (sp) - table_buffer(TEXT_CURRSERVER, - (sp->realname[0]) ? sp->realname : sp->name,sp->port); + table_buffer((stringcmp(sp->group,DEFAULTSTR)) ? TEXT_CURRSERVGRP : TEXT_CURRSERVER, + (sp->realname[0]) ? sp->realname : sp->name,sp->port,sp->group); else table_buffer(TEXT_CURRSERVERNOT); - table_buffer(TEXT_SERVERONTIME,idle2str(now - current->ontime,FALSE)); - table_buffer(TEXT_BOTMODES,(*current->modes) ? current->modes : TEXT_NONE); + table_buffer(TEXT_SERVERONTIME,idle2str(current->ontime,FALSE)); #ifdef HOSTINFO hostname[255] = 0; if (gethostname(hostname,250) < 0) @@ -1359,11 +1283,22 @@ void do_core(COMMAND_ARGS) if (uname(&un) == 0) table_buffer(TEXT_HOSTINFO,h,un.sysname,un.release,un.machine); #endif /* HOSTINFO */ - table_buffer(TEXT_CURRENTTIME,time2str(now)); - table_buffer(TEXT_BOTSTARTED,time2str(uptime)); - table_buffer(TEXT_BOTUPTIME,idle2str(now - uptime,FALSE)); + table_buffer(TEXT_CURRENTTIME,maketimestr(cx.now,TFMT_FULL)); + table_buffer(TEXT_BOTSTARTED,maketimestr(uptime,TFMT_FULL)); + table_buffer(TEXT_BOTUPTIME,idle2str(uptime,FALSE)); table_buffer(TEXT_BOTVERSION,VERSION,SRCDATE); table_buffer(TEXT_BOTFEATURES,__mx_opts); +#ifdef DEBUG + extra = EMPTYSTR; + if (debugfile && dodebug) + extra = debugfile; +#ifdef __profiling__ + table_buffer("Debug\t%s%s, Compiled with Profiling", +#else + table_buffer("Debug\t%s%s", +#endif + (dodebug) ? "On, Output = " : "Off",extra); +#endif /* DEBUG */ table_send(from,2); } @@ -1413,196 +1348,143 @@ void do_shutdown(COMMAND_ARGS) /* NOT REACHED */ } -void do_servergroup(COMMAND_ARGS) +void do_server_noargs(const char *from) { - ServerGroup *sg,*new,**sgp; - char *name; + Server *sp; + const char *str_currentserver,*str_ago; + char maxontimebuf[36],*maxontime,*lastconnect; - name = chop(&rest); - - /* - * no args, list servergroups - */ - if (!name) - { - table_buffer(str_underline("id") "\t" str_underline("name")); - for(sg=servergrouplist;sg;sg=sg->next) - { - table_buffer("%i\t%s%s",sg->servergroup,sg->name,(sg == currentservergroup) ? " (current)" : ""); - } - table_send(from,2); + if (partyline_only_command(from)) return; - } + table_buffer(str_underline("server") "\t" str_underline("last connect") "\t" + str_underline("maxontime") "\t" str_underline("group")); - /* - * find pre-existing severgroup by the same name (case-insensitive) - */ - sg = getservergroup(name); - if (!sg) + for(sp=serverlist;sp;sp=sp->next) { -#ifdef DEBUG - debug("(do_servergroup) creating new servergroup: %s\n",name); -#endif /* DEBUG */ - set_mallocdoer(do_servergroup); - new = (ServerGroup*)Calloc(sizeof(ServerGroup) + strlen(name)); - servergroupid++; - new->servergroup = servergroupid; - stringcpy(new->name,name); - sgp = &servergrouplist; - while(*sgp) - sgp = &(*sgp)->next; - sg = *sgp = new; -#ifdef DEBUG + str_ago = str_currentserver = EMPTYSTR; + if (sp->ident == current->server) { - ServerGroup *g; - - for (g=servergrouplist;g;g=g->next) - { - debug("(do_servergroup) %s (%i)\n",g->name,g->servergroup); - } + if (sp->maxontime == -1 || sp->maxontime > current->ontime) + sp->maxontime = current->ontime; + str_currentserver = TEXT_CURRENT; } -#endif /* DEBUG */ + + if (sp->maxontime == -1) + maxontime = TEXT_NEVER; + else + { + maxontime = maxontimebuf; + stringcpy(maxontimebuf,idle2str(sp->maxontime,FALSE)); + } + + if (sp->lastconnect) + { + str_ago = TEXT_AGO; + lastconnect = idle2str(sp->lastconnect,FALSE); + } + else + switch(sp->err) + { + case SP_NOAUTH: + lastconnect = TEXT_SP_NOAUTH; + break; + case SP_KLINED: + lastconnect = TEXT_SP_KLINED; + break; + case SP_FULLCLASS: + lastconnect = TEXT_SP_FULLCLASS; + break; + case SP_TIMEOUT: + lastconnect = TEXT_SP_TIMEOUT; + break; + case SP_ERRCONN: + lastconnect = TEXT_SP_ERRCONN; + break; + case SP_DIFFPORT: + lastconnect = TEXT_SP_DIFFPORT; + break; + case SP_NO_DNS: + lastconnect = TEXT_SP_NO_DNS; + break; + default: + lastconnect = TEXT_NEVER; + } + table_buffer("%s:%i%s\t%s%s\t%s\t%s",(*sp->realname) ? sp->realname : sp->name,sp->port, + str_currentserver,lastconnect,str_ago,maxontime,sp->group); } - currentservergroup = sg; -#ifdef DEBUG - debug("(do_servergroup) current servergroup set to \"%s\" (%i)\n",sg->name,sg->servergroup); -#endif /* DEBUG */ + table_send(from,2); } void do_server(COMMAND_ARGS) { - ServerGroup *sg; Server *sp,*dp,**spp; - char *server,*aport,*pass; - char addc,*last,*quitmsg = TEXT_TRYNEWSERVER; - int n,iport,sgi; + char *server,*aport,*temp; + const char *pass,*group; + char add_or_sub,*quitmsg = TEXT_TRYNEWSERVER; + int n,iport; if (CurrentCmd->name == C_NEXTSERVER) { - quitmsg = TEXT_SWITCHSERVER; - to_user(from,FMT_PLAIN,quitmsg); + to_user(from,FMT_PLAIN,TEXT_SWITCHSERVER); goto do_server_jump; } + + + add_or_sub = *rest; + if (*rest == '-' || *rest == '+') + rest++; + + if (*rest == 0) + goto do_server_einval; + server = chop(&rest); - - /* - * no args, list all known servers - */ - if (!server) - { - char maxontime[36],*cuur; - int ot; - - if (partyline_only_command(from)) - return; - if (servergrouplist->next) - table_buffer(str_underline("server") "\t" str_underline("last connect") "\t" - str_underline("maxontime") "\t" str_underline("group")); - else - table_buffer(str_underline("server") "\t" str_underline("last connect") "\t" str_underline("maxontime")); - sgi = -1; - for(sp=serverlist;sp;sp=sp->next) - { - cuur = ""; - if (sp->ident == current->server) - { - cuur = TEXT_CURRENT; - ot = now - current->ontime; - if (sp->maxontime < ot) - sp->maxontime = ot; - } - stringcpy(maxontime,(sp->maxontime == 0) ? TEXT_NEVER : idle2str(sp->maxontime,FALSE)); - if (sp->lastconnect) - last = idle2str(now - sp->lastconnect,FALSE); - else - { - switch(sp->err) - { - case SP_NOAUTH: - last = TEXT_SP_NOAUTH; - break; - case SP_KLINED: - last = TEXT_SP_KLINED; - break; - case SP_FULLCLASS: - last = TEXT_SP_FULLCLASS; - break; - case SP_TIMEOUT: - last = TEXT_SP_TIMEOUT; - break; - case SP_ERRCONN: - last = TEXT_SP_ERRCONN; - break; - case SP_DIFFPORT: - last = TEXT_SP_DIFFPORT; - break; - case SP_NO_DNS: - last = TEXT_SP_NO_DNS; - break; - default: - last = TEXT_NEVER; - } - } - if (servergrouplist->next) - { - if (sgi != sp->servergroup) - { - sg = getservergroupid(sp->servergroup); - if (sg) - sgi = sg->servergroup; - } - table_buffer("%s:%i\t%s%s%s\t%s\t%s",(*sp->realname) ? sp->realname : sp->name,sp->port, - last,(sp->lastconnect) ? TEXT_AGO : "",cuur,maxontime,(sg) ? sg->name : "(unknown)"); - } - else - table_buffer("%s:%i\t%s%s%s\t%s",(*sp->realname) ? sp->realname : sp->name,sp->port, - last,(sp->lastconnect) ? TEXT_AGO : "",cuur,maxontime); - } - table_send(from,2); - return; - } - - addc = *server; - if (addc == '-' || addc == '+') - { - server++; - if (!*server) - { - usage(from); - return; - } - } - if (strlen(server) >= MAXHOSTLEN) + if ((cx.chop_end - server) >= MAXHOSTLEN) { to_user(from,TEXT_NAMETOOLONG); return; } - aport = chop(&rest); - pass = chop(&rest); + aport = "6667"; + group = DEFAULTSTR; + pass = EMPTYSTR; + do + { + if (*rest == COMMENT_CHAR) + break; + temp = chop(&rest); + if (temp == NULL) + break; + + if (*temp >= '1' && *temp <= '9') + aport = temp; + else + if (*temp == '@' && ((cx.chop_end - temp) <= SERVERGROUPLEN)) + group = temp + 1; + else + if (*temp == '"') + { + char *c; + + temp++; + c = stringchr(temp,'"'); + if (c && ((c - temp) <= PASSLEN)) + pass = temp, *c = 0; + } + else + goto do_server_einval; + } + while(*rest); + iport = asc2int(aport); - if (aport && *aport == COMMENT_CHAR) - { - aport = pass = NULL; - } - else - if (pass && *pass == COMMENT_CHAR) - { - pass = NULL; - } - - if (aport && (errno || iport < 1 || iport > 65534)) + if (errno || iport < 1 || iport > 65534) { +do_server_einval: usage(from); return; } - if (!aport) - { - iport = 0; - } - if (addc == '-') + if (add_or_sub == '-') { if (!serverlist) { @@ -1644,13 +1526,8 @@ void do_server(COMMAND_ARGS) } return; } - sp = add_server(server,iport,pass); - if (!sp) - { - to_user(from,"Problem adding server: %s",server); - return; - } - if (addc || from == CoreUser.name) + sp = add_server(server,iport,pass,group); /* add_server has no failure mode */ + if (add_or_sub == '+' || from == cx.CoreUser.name) return; current->nextserver = sp->ident; @@ -1687,10 +1564,10 @@ void do_away(COMMAND_ARGS) to_server("AWAY\n"); to_user(from,TEXT_NOLONGERAWAY); current->away = FALSE; - current->activity = now; + current->activity = cx.now; return; } - to_server(AWAYFORM,rest,time2away(now)); + to_server(AWAYFORM,rest,maketimestr(cx.now,TFMT_AWAY)); to_user(from,TEXT_NOWSETAWAY); current->away = TRUE; } @@ -1712,15 +1589,15 @@ void do_nick(COMMAND_ARGS) char *nick; int guid; - nick = chop(&rest); - if (!nick || !*nick) + if (!rest || !*rest) { usage(from); /* usage for CurrentCmd->name */ return; } + nick = chop(&rest); guid = asc2int(nick); backup = current; - if (!errno) + if (errno == 0) /* we got a number */ { nick = chop(&rest); for(current=botlist;current;current=current->next) @@ -1731,7 +1608,7 @@ void do_nick(COMMAND_ARGS) break; } } - if (!is_nick(nick)) + if (is_nick(nick) == FALSE) { current = backup; to_user(from,ERR_NICK,nick); @@ -1745,35 +1622,33 @@ void do_nick(COMMAND_ARGS) current = add_bot(guid,nick); if (!sigmaster) sigmaster = guid; - if (from == CoreUser.name) + if (from == cx.CoreUser.name) return; } else { if (current->guid == 0) { - Free((char**)¤t->nick); - set_mallocdoer(do_nick); - current->nick = stringdup(nick); - current->guid = guid; + setbotnick(current,nick); + current->guid = guid; /* guid might be undefined? */ } - Free((char**)¤t->wantnick); - set_mallocdoer(do_nick); - current->wantnick = stringdup(nick); - to_server("NICK %s\n",current->wantnick); + setbotwantnick(current,nick); + to_server("NICK %s\n",getbotwantnick(current)); } current = backup; } void do_time(COMMAND_ARGS) { - to_user_q(from,"Current time: %s",time2away(now)); + to_user_q(from,"Current time: %s",maketimestr(cx.now,TFMT_AWAY)); } void do_upontime(COMMAND_ARGS) { - to_user_q(from,CurrentCmd->cmdarg, - idle2str(now - ((CurrentCmd->name == C_UPTIME) ? uptime : current->ontime),FALSE)); + time_t temp; + + temp = ((CurrentCmd->name == C_UPTIME) ? uptime : current->ontime); + to_user_q(from,CurrentCmd->cmdarg,idle2str(temp,FALSE)); } void do_msg(COMMAND_ARGS) diff --git a/src/ctcp.c b/src/ctcp.c index c01bb96..5abbae9 100644 --- a/src/ctcp.c +++ b/src/ctcp.c @@ -82,7 +82,7 @@ void delete_client(Client *client) pspy = &(*pspy)->next; } send_global(SPYSTR_STATUS,"[%s] %s[%i] has disconnected", - current->nick,client->user->name,client->user->x.x.access); + getbotnick(current),client->user->name,client->user->x.x.access); } #ifdef DCC_FILE if (client->fileno >= 0) @@ -99,7 +99,8 @@ int dcc_sendfile(char *target, char *filename) { struct sockaddr_in sai; Client *client; - int s,f,sz; + int s,f; + unsigned int sz; char tempfile[strlen(filename)+strlen(DCC_PUBLICFILES)+2]; // strlen(DCC_PUBLICFILES) evaluates at compile time to a constant. stringcpy(tempfile,DCC_PUBLICFILES); @@ -127,7 +128,7 @@ int dcc_sendfile(char *target, char *filename) client->sock = s; client->user = NULL; client->flags = DCC_WAIT|DCC_ASYNC|DCC_SEND; - client->lasttime = now; + client->lasttime = cx.now; client->whom = stringcpy(client->filename,filename) + 1; stringcpy(client->whom,target); @@ -215,7 +216,7 @@ void parse_dcc(Client *client) else { client->flags = DCC_SEND; - client->start = now; + client->start = cx.now; dcc_pushfile(client,0); } #endif /* DCC_FILE */ @@ -249,7 +250,7 @@ void parse_dcc(Client *client) if (write(client->sock,&where,4) == -1) return; - client->lasttime = now; + client->lasttime = cx.now; if (oc == client->fileend) { @@ -265,7 +266,7 @@ void parse_dcc(Client *client) { uint32_t where; - client->lasttime = now; + client->lasttime = cx.now; s = client->inputcount; oc = read(client->sock,(client->sockdata+s),(4-s)); if ((oc < 1) && (errno != EINTR) && (errno != EAGAIN)) @@ -318,7 +319,7 @@ void parse_dcc(Client *client) /* * DCC input flood protection */ - s = now - client->lasttime; + s = cx.now - client->lasttime; if (s > 10) { client->inputcount = strlen(ptr); @@ -337,7 +338,7 @@ void parse_dcc(Client *client) */ CurrentShit = NULL; CurrentChan = NULL; - client->lasttime = now; + client->lasttime = cx.now; CurrentDCC = client; CurrentUser = client->user; stringcpy(CurrentNick,CurrentUser->name); @@ -347,11 +348,11 @@ void parse_dcc(Client *client) bp = ptr; chop(&bp); ptr = get_token(&bp,"\001"); - on_action(CurrentUser->name,current->nick,ptr); + on_action(CurrentUser->name,getbotnick(current),ptr); } else { - on_msg(CurrentUser->name,current->nick,ptr); + on_msg(CurrentUser->name,getbotnick(current),ptr); } CurrentDCC = NULL; /* @@ -389,7 +390,7 @@ void process_dcc(void) partyline_banner(client); } else - if ((client->flags & DCC_WAIT) && ((now - client->lasttime) >= WAITTIMEOUT)) + if ((client->flags & DCC_WAIT) && ((cx.now - client->lasttime) >= WAIT_TIMEOUT)) { #ifdef DEBUG debug("(process_dcc) connection timed out (%s)\n", @@ -399,7 +400,7 @@ void process_dcc(void) } #ifdef DCC_FILE else - if ((client->flags & DCC_SEND) && ((now - client->lasttime) >= DCC_FILETIMEOUT)) + if ((client->flags & DCC_SEND) && ((cx.now - client->lasttime) >= DCCFILE_TIMEOUT)) { #ifdef DEBUG debug("(process_dcc) {%i} DCC %s stalled (%s), closing connection\n", @@ -411,7 +412,7 @@ void process_dcc(void) #endif /* DCC_FILE */ #ifdef TELNET else - if ((client->flags & DCC_TELNETPASS) && ((now - client->lasttime) >= TELNET_TIMEOUT)) + if ((client->flags & DCC_TELNETPASS) && ((cx.now - client->lasttime) >= TELNET_TIMEOUT)) { client->flags = DCC_DELETE; } @@ -528,7 +529,7 @@ void ctcp_dcc(char *from, char *to, char *rest) client->fileend = filesz; client->sock = s; client->flags = DCC_WAIT|DCC_SEND|DCC_RECV; - client->lasttime = client->start = now; + client->lasttime = client->start = cx.now; client->whom = stringcpy(client->filename,filename) + 1; stringcpy(client->whom,from); @@ -587,7 +588,7 @@ void ctcp_dcc(char *from, char *to, char *rest) client->sock = x; client->user = user; client->flags = DCC_WAIT|DCC_ASYNC; - client->lasttime = now; + client->lasttime = cx.now; client->next = current->clientlist; current->clientlist = client; } @@ -671,7 +672,7 @@ void ctcp_version(char *from, char *to, char *rest) #endif /* CTCP */ -LS const struct +const struct { char *name; void (*func)(char *, char *, char *); @@ -731,9 +732,9 @@ void on_ctcp(char *from, char *to, char *rest) { for(mul=0;mulname == C_PING || !stringcasecmp(rest,"PING")) { - to_server("PRIVMSG %s :\001PING %lu\001\n",target,now); + to_server("PRIVMSG %s :\001PING %lu\001\n",target,cx.now); return; } if (*rest) diff --git a/src/debug.c b/src/debug.c index 899900b..7579de0 100644 --- a/src/debug.c +++ b/src/debug.c @@ -36,9 +36,11 @@ #define boolstr(x) (x) ? "TRUE" : "FALSE" -LS const char tabs[20] = "\t\t\t\t\t\t\t\t\t\t"; +#define UNKNOWNSTR "(unknown)" -LS const struct +const char tabs[20] = "\t\t\t\t\t\t\t\t\t\t"; + +const struct { char *name; int size; @@ -92,7 +94,6 @@ LS const struct { "Seen", sizeof(Seen) }, #endif /* SEEN */ { "Server", sizeof(Server) }, -{ "ServerGroup", sizeof(ServerGroup) }, { "Setting", sizeof(Setting) }, { "Shit", sizeof(Shit) }, { "Spy\t", sizeof(Spy) }, @@ -115,7 +116,7 @@ LS const struct #define RARE_SE ,"RARE" #define DBUG_SE ,"DBUG" -LS struct +struct { void *func; char *name; @@ -142,7 +143,6 @@ LS struct { do_die, "do_die" RARE_SE }, { do_nick, "do_nick" CMD1_SE }, { do_kicksay, "do_kicksay" CMD1_SE }, -{ do_servergroup, "do_servergroup" CMD1_SE }, { do_set, "do_set" CMD1_SE }, { do_spy, "do_spy" CMD1_SE }, { join_channel, "join_channel" CFG1_SE }, @@ -168,7 +168,8 @@ LS struct { send_kick, "send_kick" }, { send_mode, "send_mode" }, { set_str_varc, "set_str_varc" CFG1_SE }, -{ setbotnick, "setbotnick" }, +{ set_mix16, "set_mix16" CORE_SE }, +{ set_mix64, "set_mix64" CORE_SE }, { sig_hup, "sig_hup" RARE_SE }, { table_buffer, "table_buffer" }, #ifdef ALIAS @@ -206,6 +207,8 @@ LS struct #ifdef PYTHON { python_hook, "python_hook" }, { python_unhook, "python_unhook" }, +{ python_timer_jump, "python_timer_jump" }, +{ python_parse_jump, "python_parse_jump" }, #endif /* PYTHON */ #ifdef RAWDNS { rawdns, "rawdns" }, @@ -223,6 +226,8 @@ LS struct #endif /* STATS */ #ifdef TCL { tcl_hook, "tcl_hook" }, +{ tcl_timer_jump, "tcl_timer_jump" }, +{ tcl_parse_jump, "tcl_parse_jump" }, #endif /* TCL */ #ifdef TELNET { check_telnet, "check_telnet" }, @@ -242,11 +247,34 @@ LS struct #ifdef URLCAPTURE { urlcapture, "urlcapture" CORE_SE }, #endif /* URLCAPTURE */ -{ 0, "(unknown)" }, +{ 0, UNKNOWNSTR }, { NULL, }}; +#ifdef HOSTINFO + +#include + +const DEFstruct inomasks[] = +{ +{ IN_ACCESS, "IN_ACCESS" }, /* File was accessed (read) */ +{ IN_ATTRIB, "IN_ATTRIB" }, /* Metadata changed, e.g., permissions, timestamps, extended attributes, link count, UID, GID, etc. */ +{ IN_CLOSE_WRITE, "IN_CLOSE_WRITE" }, /* File opened for writing was closed */ +{ IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE" }, /* File not opened for writing was closed */ +{ IN_CREATE, "IN_CREATE" }, /* File/directory created in watched directory */ +{ IN_DELETE, "IN_DELETE" }, /* File/directory deleted from watched directory */ +{ IN_DELETE_SELF, "IN_DELETE_SELF" }, /* Watched file/directory was itself deleted */ +{ IN_MODIFY, "IN_MODIFY" }, /* File was modified */ +{ IN_MOVE_SELF, "IN_MOVE_SELF" }, /* Watched file/directory was itself moved */ +{ IN_MOVED_FROM, "IN_MOVED_FROM" }, /* Generated for the directory containing the old filename when a file is renamed */ +{ IN_MOVED_TO, "IN_MOVED_TO" }, /* Generated for the directory containing the new filename when a file is renamed */ +{ IN_OPEN, "IN_OPEN" }, /* File was opened */ +{ 0, }}; + +#endif /* HOSTINFO */ + #ifdef SCRIPTING -LS const DEFstruct SCRIPTdefs[] = + +const DEFstruct SCRIPTdefs[] = { { MEV_PARSE, "MEV_PARSE" }, { MEV_TIMER, "MEV_TIMER" }, @@ -254,18 +282,11 @@ LS const DEFstruct SCRIPTdefs[] = { MEV_BOTNET, "MEV_BOTNET" }, { MEV_DCC_COMPLETE, "MEV_DCC_COMPLETE" }, { MEV_DNSRESULT, "MEV_DNSRESULT" }, -#ifdef TCL -{ .v.func=tcl_timer_jump, "tcl_timer_jump" }, -{ .v.func=tcl_parse_jump, "tcl_parse_jump" }, -#endif /* TCL */ -#ifdef PYTHON -{ .v.func=python_timer_jump, "python_timer_jump" }, -{ .v.func=python_parse_jump, "python_parse_jump" }, -#endif /* PYTHON */ { 0, }}; + #endif /* SCRIPTING */ -LS const DEFstruct CNdefs[] = +const DEFstruct CNdefs[] = { { CN_NOSOCK, "CN_NOSOCK" }, { CN_DNSLOOKUP, "CN_DNSLOOKUP" }, @@ -279,7 +300,7 @@ LS const DEFstruct CNdefs[] = { CN_SPINNING, "CN_SPINNING" }, { 0, }}; -LS const DEFstruct SPdefs[] = +const DEFstruct SPdefs[] = { { SP_NULL, "SP_NULL" }, { SP_NOAUTH, "SP_NOAUTH" }, @@ -291,17 +312,20 @@ LS const DEFstruct SPdefs[] = { 0, }}; #ifdef NOTIFY -LS const DEFstruct NFdefs[] = + +const DEFstruct NFdefs[] = { { NF_OFFLINE, "NF_OFFLINE" }, { NF_WHOIS, "NF_WHOIS" }, { NF_MASKONLINE, "NF_MASKONLINE" }, { NF_NOMATCH, "NF_NOMATCH" }, { 0, }}; + #endif /* NOTIFY */ #ifdef SEEN -LS const DEFstruct SEdefs[] = + +const DEFstruct SEdefs[] = { { SEEN_PARTED, "SEEN_PARTED" }, { SEEN_QUIT, "SEEN_QUIT" }, @@ -311,7 +335,8 @@ LS const DEFstruct SEdefs[] = #endif /* SEEN */ #ifdef BOTNET -LS const DEFstruct BNdefs[] = + +const DEFstruct BNdefs[] = { { BN_UNKNOWN, "BN_UNKNOWN" }, { BN_DEAD, "BN_DEAD" }, @@ -322,9 +347,10 @@ LS const DEFstruct BNdefs[] = { BN_WAITLINK, "BN_WAITLINK" }, { BN_LINKED, "BN_LINKED" }, { 0, }}; + #endif /* BOTNET */ -LS const DEFstruct dcc_flags[] = +const DEFstruct dcc_flags[] = { { DCC_SEND, "DCC_SEND" }, { DCC_RECV, "DCC_RECV" }, @@ -336,7 +362,7 @@ LS const DEFstruct dcc_flags[] = { DCC_DELETE, "DCC_DELETE" }, { 0, }}; -LS const DEFstruct ircx_flags[] = +const DEFstruct ircx_flags[] = { { IRCX_WALLCHOPS, "IRCX_WALLCHOPS" }, { IRCX_WALLVOICES, "IRCX_WALLVOICES" }, @@ -344,7 +370,7 @@ LS const DEFstruct ircx_flags[] = { IRCX_EMODE, "IRCX_EMODE" }, { 0, }}; -LS const DEFstruct chanuser_flags[] = +const DEFstruct chanuser_flags[] = { { CU_VOICE, "CU_VOICE" }, { CU_CHANOP, "CU_CHANOP" }, @@ -362,9 +388,9 @@ void strflags(char *dst, const DEFstruct *flagsstruct, int flags) int i; *dst = 0; - for(i=0;(flagsstruct[i].v.id);i++) + for(i=0;(flagsstruct[i].id);i++) { - if (flagsstruct[i].v.id & flags) + if (flagsstruct[i].id & flags) { if (*dst) stringcat(dst,"|"); @@ -379,22 +405,10 @@ const char *strdef(const DEFstruct *dtab, int num) for(i=0;(dtab[i].idstr);i++) { - if (dtab[i].v.id == num) + if (dtab[i].id == num) return(dtab[i].idstr); } - return("UNKNOWN"); -} - -const char *funcdef(const DEFstruct *dtab, void *func) -{ - int i; - - for(i=0;(dtab[i].idstr);i++) - { - if (dtab[i].v.func == func) - return(dtab[i].idstr); - } - return("UNKNOWN"); + return(UNKNOWNSTR); } void memreset(void) @@ -409,8 +423,8 @@ void memreset(void) } } -LS const void *mem_lowptr; -LS const void *mem_hiptr; +const void *mem_lowptr; +const void *mem_hiptr; void memtouch(const void *addr) { @@ -437,6 +451,18 @@ void memtouch(const void *addr) } } +const char *proc_getname(void *addr) +{ + int i; + + for(i=0;ProcList[i].name;i++) + { + if (ProcList[i].func == addr) + return(ProcList[i].name); + } + return(UNKNOWNSTR); +} + const char *proc_lookup(void *addr, int size) { int i; @@ -495,14 +521,13 @@ char *atime(time_t when) char *pt,*zp; pt = ctime(&when); - zp = STRCHR(pt,'\n'); + zp = stringchr(pt,'\n'); *zp = 0; return(pt); } void debug_server(Server *sp, char *pad) { - ServerGroup *sg; char *pl; if (!sp) @@ -516,17 +541,9 @@ void debug_server(Server *sp, char *pad) debug("%s; ident\t\t%i\n",pad,sp->ident); debug("%s; name\t\t\"%s\"\n",pad,nullbuf(sp->name)); debug("%s; pass\t\t\"%s\"\n",pad,nullbuf(sp->pass)); + debug("%s; group\t\t\"%s\"\n",pad,nullbuf(sp->group)); debug("%s; realname\t\t\"%s\"\n",pad,nullbuf(sp->realname)); debug("%s; usenum\t\t%i\n",pad,sp->usenum); - sg = getservergroupid(sp->servergroup); - if (sg) - { - debug("%s; servergroup\t%s%i \"%s\"\n",pad,pl,sp->servergroup,sg->name); - } - else - { - debug("%s; servergroup\t%s%i (unknown)\n",pad,pl,sp->servergroup); - } debug("%s; port\t\t%i\n",pad,sp->port); debug("%s; err\t\t%s%s (%i)\n",pad,pl,strdef(SPdefs,sp->err),sp->err); debug("%s; lastconnect\t%s%s (%lu)\n",pad,pl,atime(sp->lastconnect),sp->lastconnect); @@ -561,7 +578,7 @@ void debug_settings(UniVar *setting, int type) } debug("%s> setting\n",pad+2); - for(;VarName[i].name;i++) + for(;i= CHANSET_SIZE)) break; @@ -644,7 +661,7 @@ void debug_memory(void) #endif /* URLCAPTURE */ for(bot=botlist;bot;bot=bot->next) { - for(i=CHANSET_SIZE;VarName[i].name;i++) + for(i=CHANSET_SIZE;isetting[i].str_var); @@ -661,7 +678,6 @@ void debug_memory(void) { memtouch(bot->lastcmds[i]); } - memtouch(bot->userhost); } debug("> Memory allocations\n"); for(mea=mrrec;(mea);mea=mea->next) @@ -741,7 +757,7 @@ void debug_botnet(void) struct sockaddr_in sai; BotNet *bn; NetCfg *cfg; - int sz; + unsigned int sz; debug("; linkpass\t\t\"%s\"\n",nullstr(linkpass)); memtouch(linkpass); @@ -826,7 +842,6 @@ void debug_core(void) Seen *seen; #endif /* SEEN */ Server *sp; - ServerGroup *sg; Spy *spy; Strp *st; Shit *shit; @@ -851,31 +866,13 @@ void debug_core(void) } debug(" ; ---\n"); if (current) - debug("; current\t\t"mx_pfmt" \"%s\"\n",(mx_ptr)current,nullstr(current->nick)); + debug("; current\t\t"mx_pfmt" \"%s\"\n",(mx_ptr)current,nullstr(getbotnick(current))); else debug("; current\t\t"mx_pfmt"\n",(mx_ptr)current); debug("; executable\t\t\"%s\"\n",executable); debug("; configfile\t\t\"%s\"\n",configfile); debug("; uptime\t\t%s (%lu)\n",atime(uptime),uptime); - debug("; short_tv\t\t%s (%is wait)\n",boolstr(short_tv),(short_tv) ? 1 : 30); - debug("> currentservergroup\t"mx_pfmt"\n",(mx_ptr)currentservergroup); - if (currentservergroup) - { - sg = currentservergroup; - debug(" ; next\t\t"mx_pfmt"\n",(mx_ptr)sg->next); - debug(" ; servergroup\t\t%i\n",sg->servergroup); - debug(" ; name\t\t\"%s\"\n",nullbuf(sg->name)); - debug(" ; ---\n"); - } - debug("> servergrouplist\t"mx_pfmt"\n",(mx_ptr)servergrouplist); - for(sg=servergrouplist;sg;sg=sg->next) - { - memtouch(sg); - debug(" ; next\t\t"mx_pfmt"\n",(mx_ptr)sg->next); - debug(" ; servergroup\t\t%i\n",sg->servergroup); - debug(" ; name\t\t\"%s\"\n",nullbuf(sg->name)); - debug(" ; ---\n"); - } + debug("; short_tv\t\t%s (%is wait)\n",boolstr(cx.short_tv),(cx.short_tv) ? 1 : 30); debug("> serverlist\t\t"mx_pfmt"\n",(mx_ptr)serverlist); for(sp=serverlist;sp;sp=sp->next) { @@ -887,8 +884,6 @@ void debug_core(void) for(bot=botlist;bot;bot=bot->next) { memtouch(bot); - memtouch(bot->nick); - memtouch(bot->wantnick); debug(" ; Mech*\t\t"mx_pfmt"\n",(mx_ptr)bot); debug(" ; next\t\t"mx_pfmt"\n",(mx_ptr)bot->next); debug(" ; connect\t\t%s (%i)\n",strdef(CNdefs,bot->connect),bot->connect); @@ -906,8 +901,8 @@ void debug_core(void) { debug_server(sp," "); } - debug(" ; nick\t\t\"%s\"\n",nullstr(bot->nick)); - debug(" ; wantnick\t\t\"%s\"\n",nullstr(bot->wantnick)); + debug(" ; nick\t\t\"%s\"\n",nullstr(getbotnick(bot))); + debug(" ; wantnick\t\t\"%s\"\n",nullstr(getbotwantnick(bot))); debug_settings(bot->setting,DSET_GLOBAL); @@ -1361,7 +1356,7 @@ void debug_scripthook(void) for(h=hooklist;h;h=h->next) { memtouch(h); - debug(" ; func\t\t"mx_pfmt" %s\n",(mx_ptr)h->func,funcdef(SCRIPTdefs,h->func)); + debug(" ; func\t\t"mx_pfmt" %s\n",(mx_ptr)h->func,proc_getname(h->func)); debug(" ; guid\t\t%i\n",h->guid); debug(" ; flags\t\t%s (%i)\n",strdef(SCRIPTdefs,h->flags),h->flags); if (h->flags == MEV_TIMER) @@ -1429,13 +1424,14 @@ int wrap_debug(void) backup_dodebug = dodebug; backup_fd = debug_fd; - sprintf(fname,"debug.%lu",now); + sprintf(fname,"debug.%lu",cx.now); if ((fd = open(fname,O_WRONLY|O_CREAT|O_TRUNC,NEWFILEMODE)) < 0) return(0); debug_fd = fd; dodebug = TRUE; run_debug(); + parse_server_input(NULL); close(fd); debug_fd = backup_fd; @@ -1445,8 +1441,49 @@ int wrap_debug(void) return(1); } +void do_inject(COMMAND_ARGS) +{ + set_mallocdoer(do_inject); + current->inject = stringdup(rest); +} + void do_debug(COMMAND_ARGS) { + const char *arg; + int m; + + arg = chop(&rest); + if (arg && strcasecmp(arg,"off") == 0) + { + if (debugfile && debugfilemalloc == TRUE) + Free(&debugfile); + debugfilemalloc = FALSE; + debugfile = NULL; + dodebug = FALSE; + to_user(from,"Debug output turned off"); + return; + } + if (arg && strcasecmp(arg,"on") == 0) + { + m = is_safepath(rest,FILE_MAY_EXIST); + debug("(do_debug) turn on, rest = '%s', %i\n",rest,m); + if (*rest && m == FILE_IS_SAFE) + { + if (debugfile && debugfilemalloc == TRUE) + Free(&debugfile); + debugfilemalloc = TRUE; + set_mallocdoer(do_debug); + debugfile = stringdup(rest); + dodebug = TRUE; + to_user(from,"Debug output turned on, Output = %s",rest); + } + else + { + to_user(from,"debug: Unsafe filename"); + } + return; + + } if (wrap_debug()) to_user(from,"Debug information has been written to file"); else @@ -1466,6 +1503,7 @@ void do_crash(COMMAND_ARGS) void debug(char *format, ...) { va_list msg; + int sz; if (!dodebug) return; @@ -1488,10 +1526,10 @@ void debug(char *format, ...) } va_start(msg,format); - vsnprintf(debugbuf,sizeof(debugbuf),format,msg); + sz = vsnprintf(debugbuf,sizeof(debugbuf),format,msg); va_end(msg); - if ((write(debug_fd,debugbuf,strlen(debugbuf))) < 0) + if ((write(debug_fd,debugbuf,sz)) < 0) dodebug = FALSE; } diff --git a/src/defines.h b/src/defines.h index 276195b..003d36e 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2018 proton + Parts Copyright (c) 1997-2025 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 @@ -21,15 +21,6 @@ #ifndef DEFINES_H #define DEFINES_H 1 -/* - * dont export too many symbols... - */ -#ifdef LIBRARY -#define LS static -#else /* not LIBRARY */ -#define LS /* nothing */ -#endif /* LIBRARY */ - /* * startup == */ @@ -104,16 +95,9 @@ #define QM_PRI_LOW 100 /* - * Bitfield for short_tv being set to 1 or 30 seconds + * stats.c */ - -#define TV_TELNET_NICK 0x0002 -#define TV_UCACHE 0x0004 -#define TV_SERVCONNECT 0x0008 -#define TV_LINEBUF 0x0010 -#define TV_BOTNET 0x0020 -#define TV_REJOIN 0x0040 -#define TV_TRIVIA 0x0080 +#define CSTAT_PARTIAL 1 /* Misc Crap: */ @@ -148,6 +132,227 @@ #define FUH_USERHOST 1 #define FUH_HOST 2 +/* + * why would channel structs contain global vars? + * they shouldnt! and now they dont! :) + */ +#define CHANSET_SIZE INT_AAWAY + +/* + * For botlinks + */ + +/* BotNet->status */ + +#define BN_UNKNOWN 0 +#define BN_DEAD 1 +#define BN_LINKSOCK 2 +#define BN_CONNECT 3 +#define BN_BANNERSENT 4 +#define BN_WAITAUTH 5 +#define BN_WAITLINK 6 +#define BN_LINKED 7 + +#define BNAUTH_PLAINTEXT 0 +#define BNAUTH_DES 1 +#define BNAUTH_MD5 2 +#define BNAUTH_SHA 3 + +/* for server connect status */ + +#define CN_NOSOCK 0 +#define CN_DNSLOOKUP 1 +#define CN_TRYING 2 +#define CN_CONNECTED 3 +#define CN_ONLINE 4 +#define CN_DISCONNECT 5 +#define CN_BOTDIE 6 +#define CN_NEXTSERV 7 +#define CN_WINGATEWAIT 8 +#define CN_SPINNING 9 /* after exhausting serverlist */ + +#define SERVERSILENCETIMEOUT 360 /* server connection idle timeout */ + +/* DCC Kill flags (BYE command) */ + +#define DCC_NULL 0 +#define DCC_COMMAND 1 +#define DCC_KILL 2 + +/* + * is_safepath + */ +#define FILE_IS_SAFE 1 +#define FILE_MUST_EXIST 1 +#define FILE_MAY_EXIST 2 +#define FILE_MUST_NOTEXIST 3 + +/* check_mass() */ + +#define CHK_CAPS 0 +#define CHK_PUB 1 +#define CHK_PUBLIC CHK_PUB +#define CHK_DEOP 2 +#define CHK_BAN 3 +#define CHK_KICK 4 + +#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 IRCX_WALLCHOPS 1 +#define IRCX_WALLVOICES 2 +#define IRCX_IMODE 4 +#define IRCX_EMODE 8 + +/* + * dns.c + */ +#define MAX_NAMESERVERS 4 + +/* + * scripting events + */ +#define MEV_PARSE 0 +#define MEV_TIMER 1 +#define MEV_COMMAND 2 +#define MEV_BOTNET 3 +#define MEV_DCC_COMPLETE 4 +#define MEV_DNSRESULT 5 + +/* + * notify defines + */ +#define NF_OFFLINE 0 +#define NF_WHOIS 1 +#define NF_MASKONLINE 2 /* anything above NF_MASKONLINE is "online" */ +#define NF_NOMATCH 3 + +/* + * redirect.c + */ +#define R_NOTICE 0 +#define R_PRIVMSG 1 +#define R_FILE 2 +#define R_BOTNET 3 + +/* + * seen selector types + */ +#define SEEN_PARTED 0 +#define SEEN_QUIT 1 +#define SEEN_NEWNICK 2 +#define SEEN_KICKED 3 + +/* server error types */ + +#define SP_NULL 0 +#define SP_NOAUTH 1 +#define SP_KLINED 2 +#define SP_FULLCLASS 3 +#define SP_TIMEOUT 4 +#define SP_ERRCONN 5 +#define SP_DIFFPORT 6 +#define SP_NO_DNS 7 +#define SP_THROTTLED 8 + +/* + * spying types, source and target types are mixed + */ +#define SPY_FILE 1 +#define SPY_DCC 2 +#define SPY_CHANNEL 3 +#define SPY_STATUS 4 +#define SPY_MESSAGE 5 +#define SPY_RAWIRC 6 +#define SPY_BOTNET 7 +#ifdef URLCAPTURE +#define SPY_URL 8 +#endif /* URLCAPTURE */ +#ifdef HOSTINFO +#define SPY_SYSMON 9 +#endif /* HOSTINFO */ +#define SPY_RANDSRC 10 + +#define SPYF_ANY 1 +#define SPYF_CHANNEL (1 << SPY_CHANNEL) +#define SPYF_STATUS (1 << SPY_STATUS) +#define SPYF_MESSAGE (1 << SPY_MESSAGE) +#define SPYF_RAWIRC (1 << SPY_RAWIRC) +#define SPYF_BOTNET (1 << SPY_BOTNET) +#define SPYF_URL (1 << SPY_URL) +#define SPYF_RANDSRC (1 << SPY_RANDSRC) + +/* + * function.c :: maketimestr() + */ +#define TFMT_LOG 0x20506 +#define TFMT_FULL 0x60402 +#define TFMT_AWAY 0x40307 +#define TFMT_CLOCK 0x1 +#define TFMT_DATE 0x4 + +/* + * Bitfield for short_tv being set to 1 or 30 seconds + */ + +#define TV_TELNET_NICK 0x0002 +#define TV_UCACHE 0x0004 +#define TV_SERVCONNECT 0x0008 +#define TV_LINEBUF 0x0010 +#define TV_BOTNET 0x0020 +#define TV_REJOIN 0x0040 +#define TV_TRIVIA 0x0080 + +/* + * uptime defines + */ + +#define UPTIME_ENERGYMECH 1 /* http://www.energymech.net */ +#define UPTIME_EGGDROP 2 /* http://www.eggheads.org */ +#define UPTIME_MINIMECH 3 /* http://www.energymech.net */ +#define UPTIME_WINMECH 4 /* http://www.energymech.net */ +#define UPTIME_RACBOT 5 /* http://www.racbot.org */ +#define UPTIME_MIRC 6 /* http://www.mirc.com */ +#define UPTIME_HAL9000 7 /* http://www.2010.org */ +#define UPTIME_ANABOT 8 /* http://www.sirklabs.hu/ana-liza/ */ +#define UPTIME_ANGELBOT 9 /* unknown */ +#define UPTIME_FIRECLAW 10 /* http://www.fireclaw.org */ +#define UPTIME_GARNAX 11 /* http://garnax.mircx.com */ +#define UPTIME_WINEGGDROP 12 /* http://www.eggheads.org */ +#define UPTIME_SUPYBOT 14 /* http://supybot.sourceforge.net */ + +#define UPTIME_GENERICDEATH 5000 /* generic death */ +#define UPTIME_SIGSEGV 5001 +#define UPTIME_SIGBUS 5002 +#define UPTIME_SIGTERM 5003 +#define UPTIME_SIGINT 5004 + +#define UPTIMEHOST "uptime.eggheads.org" + +#ifdef __CYGWIN__ +#define UPTIME_BOTTYPE UPTIME_WINMECH +#else +#define UPTIME_BOTTYPE UPTIME_ENERGYMECH +#endif /* __CYGWIN__ */ + +/* VHOST types */ + +#define VH_ZERO 0 +#define VH_IPALIAS (1 << 1) +#define VH_IPALIAS_FAIL (1 << 2) +#define VH_IPALIAS_BOTH (VH_IPALIAS|VH_IPALIAS_FAIL) +#define VH_WINGATE (1 << 3) +#define VH_WINGATE_FAIL (1 << 4) +#define VH_WINGATE_BOTH (VH_WINGATE|VH_WINGATE_FAIL) + /* Type of Variable: */ #define INT_VAR 0x01 @@ -174,14 +379,6 @@ #define IsChar(x) ((VarName[x].type & CHR_VAR) == CHR_VAR) #define IsProc(x) (VarName[x].type & PROC_VAR) -/* - * is_safepath - */ -#define FILE_IS_SAFE 1 -#define FILE_MUST_EXIST 1 -#define FILE_MAY_EXIST 2 -#define FILE_MUST_NOTEXIST 3 - /* * see settings.h for the actual setting struct */ @@ -301,205 +498,5 @@ enum { SIZE_VARS }; -/* - * why would channel structs contain global vars? - * they shouldnt! and now they dont! :) - */ -#define CHANSET_SIZE INT_AAWAY - -/* - * For botlinks - */ - -#ifdef BOTNET - -/* BotNet->status */ - -#define BN_UNKNOWN 0 -#define BN_DEAD 1 -#define BN_LINKSOCK 2 -#define BN_CONNECT 3 -#define BN_BANNERSENT 4 -#define BN_WAITAUTH 5 -#define BN_WAITLINK 6 -#define BN_LINKED 7 - -#define BNAUTH_PLAINTEXT 0 -#define BNAUTH_DES 1 -#define BNAUTH_MD5 2 -#define BNAUTH_SHA 3 - -#endif /* BOTNET */ - -/* for connect status */ - -#define CN_NOSOCK 0 -#define CN_DNSLOOKUP 1 -#define CN_TRYING 2 -#define CN_CONNECTED 3 -#define CN_ONLINE 4 -#define CN_DISCONNECT 5 -#define CN_BOTDIE 6 -#define CN_NEXTSERV 7 -#define CN_WINGATEWAIT 8 -#define CN_SPINNING 9 /* after exhausting serverlist */ - -#define SERVERSILENCETIMEOUT 360 /* server connection idle timeout */ - -/* DCC Kill flags (BYE command) */ - -#define DCC_NULL 0 -#define DCC_COMMAND 1 -#define DCC_KILL 2 - -/* VHOST types */ - -#define VH_ZERO 0 -#define VH_IPALIAS (1 << 1) -#define VH_IPALIAS_FAIL (1 << 2) -#define VH_IPALIAS_BOTH (VH_IPALIAS|VH_IPALIAS_FAIL) -#define VH_WINGATE (1 << 3) -#define VH_WINGATE_FAIL (1 << 4) -#define VH_WINGATE_BOTH (VH_WINGATE|VH_WINGATE_FAIL) - -/* server error types */ - -#define SP_NULL 0 -#define SP_NOAUTH 1 -#define SP_KLINED 2 -#define SP_FULLCLASS 3 -#define SP_TIMEOUT 4 -#define SP_ERRCONN 5 -#define SP_DIFFPORT 6 -#define SP_NO_DNS 7 -#define SP_THROTTLED 8 - -/* 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 -#define CHK_DEOP 2 -#define CHK_BAN 3 -#define CHK_KICK 4 - -/* - * seen selector types - */ -#define SEEN_PARTED 0 -#define SEEN_QUIT 1 -#define SEEN_NEWNICK 2 -#define SEEN_KICKED 3 - -/* - * spying types, source and target types are mixed - */ -#define SPY_FILE 1 -#define SPY_DCC 2 -#define SPY_CHANNEL 3 -#define SPY_STATUS 4 -#define SPY_MESSAGE 5 -#define SPY_RAWIRC 6 -#define SPY_BOTNET 7 -#ifdef URLCAPTURE -#define SPY_URL 8 -#endif /* URLCAPTURE */ -#ifdef HOSTINFO -#define SPY_SYSMON 9 -#endif /* HOSTINFO */ -#define SPY_RANDSRC 10 - -#define SPYF_ANY 1 -#define SPYF_CHANNEL (1 << SPY_CHANNEL) -#define SPYF_STATUS (1 << SPY_STATUS) -#define SPYF_MESSAGE (1 << SPY_MESSAGE) -#define SPYF_RAWIRC (1 << SPY_RAWIRC) -#define SPYF_BOTNET (1 << SPY_BOTNET) -#define SPYF_URL (1 << SPY_URL) -#define SPYF_RANDSRC (1 << SPY_RANDSRC) -/* - * notify defines - */ -#define NF_OFFLINE 0 -#define NF_WHOIS 1 -#define NF_MASKONLINE 2 /* anything above NF_MASKONLINE is "online" */ -#define NF_NOMATCH 3 - -/* - * uptime defines - */ - -#define UPTIME_ENERGYMECH 1 /* http://www.energymech.net */ -#define UPTIME_EGGDROP 2 /* http://www.eggheads.org */ -#define UPTIME_MINIMECH 3 /* http://www.energymech.net */ -#define UPTIME_WINMECH 4 /* http://www.energymech.net */ -#define UPTIME_RACBOT 5 /* http://www.racbot.org */ -#define UPTIME_MIRC 6 /* http://www.mirc.com */ -#define UPTIME_HAL9000 7 /* http://www.2010.org */ -#define UPTIME_ANABOT 8 /* http://www.sirklabs.hu/ana-liza/ */ -#define UPTIME_ANGELBOT 9 /* unknown */ -#define UPTIME_FIRECLAW 10 /* http://www.fireclaw.org */ -#define UPTIME_GARNAX 11 /* http://garnax.mircx.com */ -#define UPTIME_WINEGGDROP 12 /* http://www.eggheads.org */ -#define UPTIME_SUPYBOT 14 /* http://supybot.sourceforge.net */ - -#define UPTIME_GENERICDEATH 5000 /* generic death */ -#define UPTIME_SIGSEGV 5001 -#define UPTIME_SIGBUS 5002 -#define UPTIME_SIGTERM 5003 -#define UPTIME_SIGINT 5004 - -#define UPTIMEHOST "uptime.eggheads.org" - -#ifdef __CYGWIN__ -#define UPTIME_BOTTYPE UPTIME_WINMECH -#else -#define UPTIME_BOTTYPE UPTIME_ENERGYMECH -#endif /* __CYGWIN__ */ - -/* - * scripting events - */ -#define MEV_PARSE 0 -#define MEV_TIMER 1 -#define MEV_COMMAND 2 -#define MEV_BOTNET 3 -#define MEV_DCC_COMPLETE 4 -#define MEV_DNSRESULT 5 - -/* - * - */ -#define IRCX_WALLCHOPS 1 -#define IRCX_WALLVOICES 2 -#define IRCX_IMODE 4 -#define IRCX_EMODE 8 - -/* - * stats.c - */ -#define CSTAT_PARTIAL 1 - -/* - * dns.c - */ -#define MAX_NAMESERVERS 4 - -/* - * redirect.c - */ -#define R_NOTICE 0 -#define R_PRIVMSG 1 -#define R_FILE 2 -#define R_BOTNET 3 - #endif /* DEFINES_H */ diff --git a/src/dns.c b/src/dns.c index 8f84673..353ea39 100644 --- a/src/dns.c +++ b/src/dns.c @@ -59,9 +59,6 @@ typedef struct dnsRType #define MAX_QUESTIONS 16 -LS int dnssock = -1; -LS int dnsserver = 0; - #ifdef DEBUG char *type_textlist[] = { NULL, "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG", "MR", "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT", }; @@ -233,7 +230,7 @@ void parse_query(int psz, dnsQuery *query) dnsList *dns; const char *src,*rtyp; char token[64],token2[64]; - int sz,n; + int n,pick; src = (const char*)query; @@ -243,7 +240,7 @@ void parse_query(int psz, dnsQuery *query) token[16] = 0; n = ntohs(query->flags); debug("(parse_query) %i: flags = %i { %s %i %s%s%s%s%s }\n", - sz,n,token, + psz,n,token, (n&15), /* result code */ (n&32768) ? "QR 1 (Answer) ":"QR 0 (Question) ", (n&1024) ? "AA ":"", @@ -292,7 +289,7 @@ void parse_query(int psz, dnsQuery *query) #endif /* DEBUG */ if (dns->cname) Free((char**)&dns->cname); - dns->when = now + 30; + dns->when = cx.now + 30; set_mallocdoer(parse_query); dns->cname = stringdup(token2); } @@ -305,7 +302,7 @@ void parse_query(int psz, dnsQuery *query) if (dns->auth && !stringcasecmp(dns->auth->hostname,token)) { dns->auth->ip.s_addr = ip->s_addr; - dns->when = now + 60; + dns->when = cx.now + 60; #ifdef DEBUG debug("(parse_query) a auth: %s = %s\n",token,inet_ntoa(*ip)); #endif /* DEBUG */ @@ -314,7 +311,7 @@ void parse_query(int psz, dnsQuery *query) if (!stringcasecmp(dns->host,token) || (dns->cname && !stringcasecmp(dns->cname,token))) { dns->ip.s_addr = ip->s_addr; - dns->when = now + 3600; + dns->when = cx.now + 3600; #ifdef DEBUG debug("(parse_query) a: %s = %s\n",token,inet_ntoa(*ip)); #endif /* DEBUG */ @@ -336,10 +333,10 @@ void parse_query(int psz, dnsQuery *query) } n = ntohs(query->authorities); - sz = (n > 1) ? RANDOM(1,n) : 1; + pick = (n > 1) ? RANDOM(1,n) : 1; #ifdef DEBUG if (n) - debug("(parse_query) auth: select %i count %i\n",sz,n); + debug("(parse_query) auth: select %i count %i\n",pick,n); #endif /* DEBUG */ while(n) { @@ -352,7 +349,7 @@ void parse_query(int psz, dnsQuery *query) dnsAuthority *da; get_dns_token(src,(const char *)query,token2,psz); - if (sz == n) + if (pick == n) { if (dns->auth == NULL) { @@ -377,7 +374,7 @@ void parse_query(int psz, dnsQuery *query) } } #ifdef DEBUG - debug("(parse_query) authorities: %s = %s%s\n",token,token2,(sz==n) ? MATCH_ALL : ""); + debug("(parse_query) authorities: %s = %s%s\n",token,token2,(pick==n) ? MATCH_ALL : ""); #endif /* DEBUG */ } #ifdef DEBUG @@ -511,12 +508,14 @@ void parse_query(int psz, dnsQuery *query) } if (src) { + int sz; + dns->id = rand(); #ifdef DEBUG debug("(parse_query) %i: asking %s who is `%s'\n",dns->id,inet_ntoa(sai.sin_addr),src); #endif /* DEBUG */ sz = make_query(packet,src); - dns->when = now + 60; + dns->when = cx.now + 60; sai.sin_family = AF_INET; sai.sin_port = htons(53); ((dnsQuery*)packet)->qid = htons(dns->id); @@ -532,13 +531,15 @@ void parse_query(int psz, dnsQuery *query) Free((char**)&dns->auth2); if (src == NULL && dns->ip.s_addr == 0 && dns->cname && dns->host && dns->auth == NULL && dns->auth2 == NULL) { + int sz; + dns->id = rand(); sai.sin_addr.s_addr = (ia_ns[dnsserver].s_addr == 0) ? ia_default.s_addr : ia_ns[dnsserver].s_addr; #ifdef DEBUG debug("(parse_query) %i: asking %s who is `%s' (CNAME question)\n",dns->id,inet_ntoa(sai.sin_addr),dns->cname); #endif /* DEBUG */ sz = make_query(packet,dns->cname); - dns->when = now + 60; + dns->when = cx.now + 60; sai.sin_family = AF_INET; sai.sin_port = htons(53); ((dnsQuery*)packet)->qid = htons(dns->id); @@ -571,7 +572,7 @@ void rawdns(const char *hostname) item = (dnsList*)Calloc(sizeof(dnsList) + strlen(hostname)); stringcpy(item->host,hostname); item->id = ntohs(query->qid); - item->when = now + 30; + item->when = cx.now + 30; item->next = dnslist; dnslist = item; @@ -610,7 +611,7 @@ restart: pdns = &dnslist; while(*pdns) { - if ((*pdns)->when < now) + if ((*pdns)->when < cx.now) { dns = *pdns; if (dns->cname) @@ -640,22 +641,18 @@ restart: void process_rawdns(void) { struct sockaddr_in sai; + unsigned int sz; char packet[512]; - int sz,n; + int n; - if (dnssock == -1) + sz = sizeof(sai); + n = recvfrom(dnssock,packet,512,0,(struct sockaddr*)&sai,&sz); + if (n < sizeof(dnsQuery)) return; - if (FD_ISSET(dnssock,&read_fds)) - { - sz = sizeof(sai); - n = recvfrom(dnssock,packet,512,0,(struct sockaddr*)&sai,&sz); - if (n < sizeof(dnsQuery)) - return; #ifdef DEBUG - debug("(process_rawdns) packet from: %s (%i bytes)\n",inet_ntoa(sai.sin_addr),n); + debug("(process_rawdns) packet from: %s (%i bytes)\n",inet_ntoa(sai.sin_addr),n); #endif /* DEBUG */ - parse_query(n,(dnsQuery*)packet); - } + parse_query(n,(dnsQuery*)packet); } char *poll_rawdns(char *hostname) @@ -675,7 +672,7 @@ char *poll_rawdns(char *hostname) return(NULL); } -LS int backup_debug; +int backup_debug; int read_dnsroot(char *line) { @@ -855,7 +852,7 @@ void do_dns(COMMAND_ARGS) uint32_t ip; /* to date, all hostnames contain atleast one dot */ - if ((STRCHR(rest,'.'))) + if ((stringchr(rest,'.'))) { host = rest; } diff --git a/src/function.c b/src/function.c index 27f1394..560916e 100644 --- a/src/function.c +++ b/src/function.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2020 proton + Parts Copyright (c) 1997-2025 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,12 +30,13 @@ #include "h.h" #include "text.h" -#ifndef TEST +char timebuf[64]; /* max format lentgh == 20+1 */ +char idlestr[64]; /* max format lentgh == 24+1 */ -LS char timebuf[32]; /* max format lentgh == 20+1, round up to 32 */ -LS char idlestr[36]; /* max format lentgh == 24+1, round up to 36 */ -LS const char monlist[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -LS const char daylist[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +const char monlist[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +const char daylist[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + +#ifndef TEST /* * memory allocation routines @@ -91,7 +92,7 @@ void *Calloc(int size) exit(1); } mmep->size = size; - mmep->when = now; + mmep->when = cx.now; mmep->doer = mallocdoer; mallocdoer = NULL; return((void*)mmep->area+4); @@ -126,7 +127,8 @@ void Free(char **mem) { debug("(Free) PANIC: Free(0x"mx_pfmt"); Unregistered memory block\n",(mx_ptr)src); run_debug(); - /*exit(1); /* overreacting. just ignore it and accept the leak. */ + /*exit(1);*/ + /* overreacting. just ignore it and accept the leak. */ return; } mp = mp->next; @@ -167,6 +169,50 @@ void Free(char **mem) #endif /* DEBUG */ +void set_mix16(Mix16 *mix, const char *str) +{ + int sz; + + if (mix->opt >= 16) + { + Free(&mix->x.ptr); + } + + sz = strlen(str); + if (sz < 16) + { + stringcpy(mix->x.string,str); + } + else + { + set_mallocdoer(set_mix16); + mix->x.ptr = stringdup(str); + } + mix->opt = sz; +} + +void set_mix64(Mix64 *mix, const char *str) +{ + int sz; + + if (mix->opt >= 64) + { + Free(&mix->x.ptr); + } + + sz = strlen(str); + if (sz < 64) + { + stringcpy(mix->x.string,str); + } + else + { + set_mallocdoer(set_mix64); + mix->x.ptr = stringdup(str); + } + mix->opt = sz; +} + Strp *make_strp(Strp **pp, const char *string) { set_mallocdoer(make_strp); @@ -223,96 +269,6 @@ void dupe_strp(Strp *sp, Strp **pp) } } -Strp *e_table = NULL; - -void table_buffer(const char *format, ...) -{ - Strp **sp; - va_list msg; - int sz; - - va_start(msg,format); - sz = sizeof(Strp) + vsprintf(globaldata,format,msg); - va_end(msg); - - for(sp=&e_table;*sp;sp=&(*sp)->next) - ; - - set_mallocdoer(table_buffer); - *sp = (Strp*)Calloc(sz); - /* Calloc sets to zero (*sp)->next = NULL; */ - stringcpy((*sp)->p,globaldata); -} - -void table_send(const char *from, const int space) -{ - char message[MAXLEN]; - Strp *sp,*next; - char *src,*o,*end; - int i,u,g,x,z[6]; - - z[0] = z[1] = z[2] = z[3] = z[4] = z[5] = 0; - for(sp=e_table;sp;sp=sp->next) - { - u = i = 0; - src = o = sp->p; - while(*src) - { - if (*src == '\037' || *src == '\002') - u++; - if (*src == '\t' || *src == '\r') - { - x = (src - o) - u; - if (x > z[i]) - z[i] = x; - i++; - o = src+1; - u = 0; - } - src++; - } - } - - for(sp=e_table;sp;sp=next) - { - next = sp->next; - - o = message; - src = sp->p; - g = x = i = 0; - while(*src) - { - if (g) - { - end = src; - while(*end && *end != '\t' && *end != '\r') - end++; - g -= (end - src); - while(g-- > 0) - *(o++) = ' '; - } - if (*src == '\037' || *src == '\002') - x++; - if (*src == '\t' || *src == '\r') - { - if (*src == '\r') - g = z[i+1]; - src++; - x += (z[i++] + space); - while(o < (message + x)) - *(o++) = ' '; - } - else - *(o++) = *(src++); - } - *o = 0; - to_user(from,FMT_PLAIN,message); - - Free((char**)&sp); - } - e_table = NULL; -} - char *getuh(char *nuh) { char *s; @@ -322,12 +278,11 @@ char *getuh(char *nuh) { if (*s == '!') { - nuh = s + 1; /* * We have to grab everything from the first '!' since some * braindamaged ircds allow '!' in the "user" part of the nuh */ - break; + return(s + 1); } s++; } @@ -385,80 +340,63 @@ a: ++(*src); return(token); } +#endif /* ifndef TEST */ + /* * time to string routines */ -char *logtime(time_t when) +char *maketimestr(time_t when, int format) { struct tm *btime; + char *dest,*f,ampm; + int option; btime = localtime(&when); - sprintf(timebuf,"%s %i %i %02i:%02i:%02i", /* max format length: 20+1 */ - monlist[btime->tm_mon],btime->tm_mday,btime->tm_year+1900, - btime->tm_hour,btime->tm_min,btime->tm_sec); - return(timebuf); -} + dest = timebuf; -char *time2str(time_t when) -{ - struct tm *btime; - - if (!when) - return(NULL); - - btime = localtime(&when); - sprintf(timebuf,"%02i:%02i:%02i %s %02i %i", /* max format length: 20+1 */ - btime->tm_hour,btime->tm_min,btime->tm_sec,monlist[btime->tm_mon], - btime->tm_mday,btime->tm_year+1900); - return(timebuf); -} - -char *time2away(time_t when) -{ - struct tm *btime; - char ampm; - - if (!when) - return(NULL); - - btime = localtime(&when); - if (btime->tm_hour < 12) + do { - if (btime->tm_hour == 0) - btime->tm_hour = 12; - ampm = 'a'; + option = format & 0x7; + format = format >> 4; + + f = "%02i:%02i:%02i"; + switch(option) + { + case 0: + *(dest++) = ' '; + break; + case 1:/* HH:mm */ + f += 5; + case 2:/* HH:mm:ss */ + dest += sprintf(dest,f,btime->tm_hour,btime->tm_min,btime->tm_sec); + break; + case 3:/* WeekDay */ + /* stringcpy return a pointer to the last char, not how many chars was copied */ + dest = stringcpy(dest,daylist[btime->tm_wday]); + break; + case 4:/* ascii-Month Day */ + dest += sprintf(dest,"%s %i",monlist[btime->tm_mon],btime->tm_mday); + break; + case 5:/* num-Month Day */ + dest += sprintf(dest,"%02i %02i",btime->tm_mon+1,btime->tm_mday); + break; + case 6:/* Year */ + dest += sprintf(dest,"%i",btime->tm_year+1900); + break; + case 7:/* am/pm */ + unsigned char a,b; + a = ((unsigned char)btime->tm_hour - 1); + a >>= 7; + b = ((unsigned char)btime->tm_hour - 12); + b >>= 7; + btime->tm_hour += (a * 12) - 12 * (b^1); + ampm = 'p' - (b * ('p' - 'a')); + dest += sprintf(dest,"%i:%02i%cm",btime->tm_hour,btime->tm_min,ampm); + break; + } } - else - { - if (btime->tm_hour != 12) - btime->tm_hour -= 12; - ampm = 'p'; - } - - sprintf(timebuf,"%i:%02i%cm %s %s %i", /* max format length: 18+1 */ - btime->tm_hour,btime->tm_min,ampm,daylist[btime->tm_wday], - monlist[btime->tm_mon],btime->tm_mday); - return(timebuf); -} - -char *time2medium(time_t when) -{ - struct tm *btime; - - btime = localtime(&when); - sprintf(timebuf,"%02i:%02i", /* max format length: 5+1 */ - btime->tm_hour,btime->tm_min); - return(timebuf); -} - -char *time2small(time_t when) -{ - struct tm *btime; - - btime = localtime(&when); - sprintf(timebuf,"%s %02i", /* max format length: 6+1 */ - monlist[btime->tm_mon],btime->tm_mday); + while(format); return(timebuf); } @@ -467,18 +405,31 @@ char *idle2str(time_t when, int small) char *dst; int n,z[4]; + when = cx.now - when; + z[0] = when / 86400; z[1] = (when -= z[0] * 86400) / 3600; z[2] = (when -= z[1] * 3600) / 60; z[3] = when % 60; +#ifdef DEBUG + { + struct tm *btime; + btime = localtime(&when); + debug("(idle2str) days %i, hours %i, minutes %i, seconds %i\n" + "(idle2str) d %i, h %i, m %i, s %i\n", + z[0],z[1],z[2],z[3], + btime->tm_yday,btime->tm_hour,btime->tm_min,btime->tm_sec); + } +#endif /* DEBUG*/ + /* 32 : "9999 days, 24 hours, 59 minutes" */ /* xx : "24 hours, 59 minutes" */ /* xx : "59 minutes, 59 seconds" */ /* xx : "59 seconds" */ if (small) { - char *f[] = {"day","hour","minute","second"}; + const char *f[] = {"day","hour","minute","second"}; *idlestr = 0; for(n=0;n<4;n++) @@ -496,6 +447,8 @@ char *idle2str(time_t when, int small) return(idlestr); } +#ifndef TEST + const char *get_channel(const char *to, char **rest) { const char *channel; @@ -608,7 +561,7 @@ char *format_uh(char *userhost, int type) char tmpmask[NUHLEN]; char *u,*h; - if (STRCHR(userhost,'*')) + if (stringchr(userhost,'*')) return(userhost); stringcpy(tmpmask,userhost); @@ -632,87 +585,6 @@ char *format_uh(char *userhost, int type) return(userhost); } -/* - * NOTE! beware of conflicts in the use of nuh_buf, its also used by find_nuh() - */ -char *nick2uh(char *from, char *userhost) -{ - if (STRCHR(userhost,'!') && STRCHR(userhost,'@')) - { - stringcpy(nuh_buf,userhost); - } - else - if (!STRCHR(userhost,'!') && !STRCHR(userhost,'@')) - { - /* find_nuh() stores nickuserhost in nuh_buf */ - if (find_nuh(userhost) == NULL) - { - if (from) - to_user(from,"No information found for %s",userhost); - return(NULL); - } - } - else - { - stringcpy(nuh_buf,"*!"); - if (!STRCHR(userhost,'@')) - stringcat(nuh_buf,"*@"); - stringcat(nuh_buf,userhost); - } - return(nuh_buf); -} - -void deop_ban(Chan *chan, ChanUser *victim, char *mask) -{ - if (!mask) - mask = format_uh(get_nuh(victim),FUH_USERHOST); - send_mode(chan,85,QM_CHANUSER,'-','o',victim); - send_mode(chan,90,QM_RAWMODE,'+','b',mask); -} - -void deop_siteban(Chan *chan, ChanUser *victim) -{ - char *mask; - - mask = format_uh(get_nuh(victim),FUH_HOST); - deop_ban(chan,victim,mask); -} - -void screwban_format(char *userhost) -{ - int sz,n,pos; - -#ifdef DEBUG - debug("(screwban_format) %s\n",userhost); -#endif /* DEBUG */ - - if ((sz = strlen(userhost)) < 8) - return; - - n = RANDOM(4,sz); - while(--n) - { - pos = RANDOM(0,(sz - 1)); - if (!STRCHR("?!@*",userhost[pos])) - { - userhost[pos] = (RANDOM(0,3) == 0) ? '*' : '?'; - } - } -} - -void deop_screwban(Chan *chan, ChanUser *victim) -{ - char *mask; - int i; - - for(i=2;--i;) - { - mask = format_uh(get_nuh(victim),FUH_USERHOST); - screwban_format(mask); - deop_ban(chan,victim,mask); - } -} - int is_nick(const char *nick) { uchar *p; @@ -729,6 +601,8 @@ int is_nick(const char *nick) return(TRUE); } +#endif /* ifndef TEST */ + /* asc2int requires the whole string *anum to be a valid numeric */ int asc2int(const char *anum) { @@ -770,6 +644,46 @@ int get_number(const char *rest) return(n); } +#define checkifdigit(xcx) (xcx >= '0' && xcx <= '9') + +void parse_range(char **s, int *a) +{ + int v; + + a[0] = -1; + a[1] = -1; + a[2] = 0; + + if (0 == checkifdigit(**s)) + return; + + v = 0; + while(checkifdigit(**s)) + { + v = (v * 10) + **s - '0'; + (*s)++; + } + a[0] = v; + + /* optional second number */ + if (**s == '-') + { + a[2] = 1; + (*s)++; + } + + if (0 == checkifdigit(**s)) + return; + + v = 0; + while(checkifdigit(**s)) + { + v = (v * 10) + **s - '0'; + (*s)++; + } + a[1] = v; +} + void fix_config_line(char *text) { char *s,*space; @@ -788,8 +702,6 @@ void fix_config_line(char *text) *space = 0; } -#endif /* ifndef TEST */ - /* * mask matching * returns 0 for match @@ -996,7 +908,9 @@ void teststring(void) int main(int argc, char **argv, char **envp) { + char mybuffer[64]; struct stat st; + time_t when; int r; dodebug = 1; @@ -1020,11 +934,25 @@ int main(int argc, char **argv, char **envp) testcase("../../nosuchfile",-5,FILE_MUST_NOTEXIST); testcase(P2,-6,FILE_MAY_EXIST); teststring(); - exit(0); } - r = is_safepath(argv[1],FILE_MAY_EXIST); - debug("testpath %s -> result %s\n",argv[1],(r) ? "TRUE" : "FALSE"); + if (argv[1]) + { + r = is_safepath(argv[1],FILE_MAY_EXIST); + debug("testpath %s -> result %s\n",argv[1],(r) ? "TRUE" : "FALSE"); + } + + time(&cx.now); + + for(r=0;r<10;r++) + { + when = cx.now - (int[]){100000,888,534569,999999,99,9000,84600,7777777,56565656+3600,78987654}[r]; + debug("\nmaketimestr %s\n",maketimestr(when,TFMT_LOG)); + debug("maketimestr %s\n",maketimestr(when,TFMT_FULL)); + debug("maketimestr %s\n",maketimestr(when,TFMT_AWAY)); + debug("maketimestr %s\n",maketimestr(when,TFMT_CLOCK)); + debug("maketimestr %s\n",maketimestr(when,TFMT_DATE)); + } } #endif /* TEST */ diff --git a/src/gencmd.c b/src/gencmd.c index b2dcb86..7f20e0d 100644 --- a/src/gencmd.c +++ b/src/gencmd.c @@ -26,347 +26,236 @@ char globaldata[MAXLEN]; #include "io.c" +#define HASHDATASZ 256 +#define HASHDATAMASK 255 + +uint8_t hash[512]; +uint8_t hashmap[512]; +uint8_t hashdata[HASHDATASZ]; + +#define HEATMAP 1 +#ifdef HEATMAP +uint8_t heatmap[HASHDATASZ]; +#endif + +int mx,collis,mincoll,randfd,heatmapon; + /* - - These are defined in config.h - - DCC 0x000100 requires DCC - CC 0x000200 requires commandchar - PASS 0x000400 requires password / authentication - CARGS 0x000800 requires args - NOPUB 0x001000 ignore in channel (for password commands) - NOCMD 0x002000 not allowed to be executed thru CMD - GAXS 0x004000 check global access - CAXS 0x008000 check channel access - REDIR 0x010000 may be redirected - LBUF 0x020000 can be linebuffered to server - CBANG 0x040000 command may be prefixed with a bang (!) - ACCHAN 0x080000 needs an active channel - SUPRES 0x100000 command is not suitable to run on many bots at once, try to suppress it - - CLEVEL 0x000ff - -*/ - -#define CCPW CC|PASS - -struct + * tolowertab blatantly ripped from ircu2.9.32 + */ +const uchar tolowertab[256] = { - int pass; - const char *name; - const char *func; - uint32_t flags; - char *cmdarg; - -} pre_mcmd[] = -{ - /* - * public access commands - */ - { 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 | SUPRES }, - { 0, "RAND", "do_rand", 0 | CBANG | SUPRES }, -#endif /* TOYBOX */ - { 0, "CV", "do_convert", 0 | CBANG | SUPRES }, - { 0, "CALC", "do_calc", 0 | CBANG | SUPRES }, - - /* - * Level 10 - */ - { 0, "ACCESS", "do_access", 10 | CCPW }, - { 0, "BYE", "do_bye", 10 | CC }, - { 0, "CHAT", "do_chat", 10 | CCPW | NOCMD }, -#ifdef RAWDNS - { 0, "DNS", "do_dns", 10 | CCPW | GAXS | CARGS | SUPRES }, -#endif /* RAWDNS */ - { 0, "DOWN", "do_opdeopme", 10 | CC | CAXS }, - { 0, "ECHO", "do_echo", 10 | CCPW | CARGS }, - { 0, "HELP", "do_help", 10 | CCPW | REDIR | LBUF | SUPRES }, - { 0, "PASSWD", "do_passwd", 10 | PASS | NOPUB | CARGS }, -#ifdef DCC_FILE - { 0, "SEND", "do_send", 10 | CC | NOCMD | CBANG | CARGS }, -#endif /* DCC_FILE */ - { 0, "USAGE", "do_usage", 10 | CCPW | REDIR | CARGS }, - - /* - * Level 20 - */ - { 0, "ONTIME", "do_upontime", 20 | CCPW , "Ontime: %s" }, - { 0, "UPTIME", "do_upontime", 20 | CCPW , "Uptime: %s" }, - { 0, "VER", "do_version", 20 | CCPW }, - { 0, "WHOM", "do_whom", 20 | CCPW | REDIR | LBUF }, -#ifdef SEEN - { 0, "SEEN", "do_seen", 20 | CCPW | CBANG }, -#endif /* SEEN */ -#ifdef URLCAPTURE - { 0, "URLHIST", "do_urlhist", 20 | CCPW | REDIR | LBUF }, -#endif /* ifdef URLCAPTURE */ - - /* - * Level 40 - */ - { 0, "BAN", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x00ban\\0bann" }, - { 0, "BANLIST", "do_banlist", 40 | CCPW | CAXS | DCC | REDIR | LBUF | ACCHAN }, - { 0, "CCHAN", "do_cchan", 40 | CCPW }, /* global_access ? */ - { 0, "CSERV", "do_cserv", 40 | CCPW }, - { 0, "CHANNELS", "do_channels", 40 | CCPW | DCC }, - { 0, "DEOP", "do_opvoice", 40 | CCPW | CAXS | CARGS , "o-" }, - { 0, "ESAY", "do_esay", 40 | CCPW | CAXS | CARGS }, - { 0, "IDLE", "do_idle", 40 | CCPW | CARGS }, - { 0, "INVITE", "do_invite", 40 | CCPW | CAXS | ACCHAN }, - { 0, "KB", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x04kickban\\0kickbann" }, - { 0, "KICK", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x07kick\\0kick" }, - { 0, "LUSERS", "do_irclusers", 40 | CCPW | DCC | REDIR | LBUF }, - { 0, "ME", "do_sayme", 40 | CCPW | CARGS }, - { 0, "MODE", "do_mode", 40 | CCPW | CARGS }, - { 0, "NAMES", "do_names", 40 | CCPW }, - { 0, "OP", "do_opvoice", 40 | CCPW | CAXS , "o+" }, - { 0, "SAY", "do_sayme", 40 | CCPW | CARGS }, - { 0, "SCREW", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x02screwban\\0screwbann" }, - { 0, "SET", "do_set", 40 | CCPW }, - { 0, "SITEBAN", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x01siteban\\0sitebann" }, - { 0, "SITEKB", "do_kickban", 40 | CCPW | CAXS | CARGS | ACCHAN , "\\x05sitekickban\\0sitekickbann" }, - { 0, "TIME", "do_time", 40 | CCPW }, - { 0, "TOPIC", "do_topic", 40 | CCPW | CAXS | CARGS | ACCHAN | SUPRES }, - { 0, "UNBAN", "do_unban", 40 | CCPW | CAXS }, - { 0, "UNVOICE", "do_opvoice", 40 | CCPW | CAXS | CARGS , "v-" }, - { 0, "UP", "do_opdeopme", 40 | CCPW | CAXS }, - { 0, "USER", "do_user", 40 | CCPW | CARGS }, - { 0, "USERHOST", "do_ircwhois", 40 | CCPW | CARGS }, - { 0, "VOICE", "do_opvoice", 40 | CCPW | CAXS , "v+" }, - { 0, "WALL", "do_wall", 40 | CCPW | CAXS | CARGS | ACCHAN }, - { 0, "WHO", "do_who", 40 | CCPW | CAXS | DCC }, - { 0, "WHOIS", "do_ircwhois", 40 | CCPW | CARGS | DCC | REDIR | LBUF }, -#ifdef NOTE - { 0, "NOTE", "do_note", 40 | CCPW | CARGS }, - { 0, "READ", "do_read", 40 | CCPW }, -#endif /* NOTE */ -#ifdef STATS - { 0, "INFO", "do_info", 40 | CCPW | REDIR | CAXS | DCC }, -#endif /* STATS */ - - /* - * Level 50 - */ - { 0, "QSHIT", "do_shit", 50 | CCPW | CARGS }, - { 0, "RSHIT", "do_rshit", 50 | CCPW | CARGS }, - { 0, "SHIT", "do_shit", 50 | CCPW | CARGS }, - { 0, "SHITLIST", "do_shitlist", 50 | CCPW | DCC | REDIR | LBUF }, -#ifdef GREET - { 0, "GREET", "do_greet", 50 | CCPW | CARGS }, -#endif /* GREET */ -#ifdef TOYBOX - { 0, "INSULT", "do_random_msg", 50 | CCPW , RANDINSULTFILE }, - { 0, "PICKUP", "do_random_msg", 50 | CCPW , RANDPICKUPFILE }, - { 0, "RSAY", "do_random_msg", 50 | CCPW , RANDSAYFILE }, - { 0, "RT", "do_randtopic", 50 | CCPW | CAXS | ACCHAN }, - { 0, "ASCII", "do_ascii", 50 | CCPW | CAXS | CARGS | SUPRES }, -#endif /* TOYBOX */ -#ifdef TRIVIA - { 0, "TRIVIA", "do_trivia", 50 | CCPW | CAXS | CARGS | CBANG }, -#endif /* TRIVIA */ - - /* - * Level 60 - */ - { 0, "SHOWIDLE", "do_showidle", 60 | CCPW | CAXS | DCC | ACCHAN }, - { 0, "USERLIST", "do_userlist", 60 | CCPW | DCC }, -#ifdef CTCP - { 0, "CTCP", "do_ping_ctcp", 60 | CCPW | CARGS }, - { 0, "PING", "do_ping_ctcp", 60 | CCPW | CARGS }, -#endif /* CTCP */ - - /* - * Level 70 == JOINLEVEL - */ - { 0, "CYCLE", "do_cycle", 70 | CCPW | CAXS | ACCHAN }, - { 0, "FORGET", "do_forget", 70 | CCPW | CAXS }, - { 0, "JOIN", "do_join", 70 | CCPW | CARGS }, - { 0, "KS", "do_kicksay", 70 | CCPW | REDIR | LBUF }, - { 0, "PART", "do_part", 70 | CCPW | CAXS | ACCHAN }, - { 0, "RKS", "do_rkicksay", 70 | CCPW | CARGS }, - { 0, "SETPASS", "do_setpass", 70 | CCPW | NOPUB | CARGS }, -#ifdef NOTIFY - { 0, "NOTIFY", "do_notify", 70 | CCPW | DCC | GAXS | REDIR | LBUF }, -#endif /* NOTIFY */ - - /* - * Level 80 == ASSTLEVEL - */ - { 0, "AWAY", "do_away", 80 | CCPW | GAXS }, - { 0, "BOOT", "do_boot", 80 | CCPW | GAXS | CARGS }, -#if defined(BOTNET) && defined(REDIRECT) - { 0, "CMD", "do_cmd", 80 | CCPW | CARGS }, -#endif /* BOTNET && REDIRECT */ - { 0, "CQ", "do_clearqueue", 80 | CCPW | GAXS }, - { 0, "LAST", "do_last", 80 | CCPW | DCC }, - { 0, "LOAD", "do_load", 80 | CCPW | GAXS }, - { 0, "MSG", "do_msg", 80 | CCPW | CARGS }, - { 0, "NEXTSERVER", "do_server", 80 | CCPW | GAXS }, - { 0, "SAVE", "do_save", 80 | CCPW | GAXS }, - { 0, "SERVER", "do_server", 80 | CCPW | GAXS | REDIR | LBUF }, - { 0, "SERVERGROUP", "do_servergroup", 80 | CCPW | GAXS | REDIR | LBUF }, - { 0, "STATS", "do_ircstats", 80 | CCPW | DCC | CARGS }, -#ifdef ALIAS - { 0, "ALIAS", "do_alias", 80 | CCPW | GAXS }, - { 0, "UNALIAS", "do_unalias", 80 | CCPW | GAXS | CARGS }, -#endif /* ALIAS */ -#ifdef TOYBOX - { 0, "BIGSAY", "do_bigsay", 80 | CCPW | CAXS | CARGS | SUPRES }, -#endif /* TOYBOX */ - - /* - * Level 90 - */ - { 0, "CLEARSHIT", "do_clearshit", 90 | CCPW | GAXS }, - { 0, "DO", "do_do", 90 | CCPW | GAXS | CARGS }, - { 0, "NICK", "do_nick", 90 | CCPW | GAXS | CARGS }, - { 0, "RSPY", "do_rspy", 90 | CCPW | CARGS }, - { 0, "SPY", "do_spy", 90 | CCPW }, -#ifdef BOTNET - { 0, "LINK", "do_link", 90 | CCPW | GAXS }, -#endif /* BOTNET */ -#ifdef DYNCMD - { 0, "CHACCESS", "do_chaccess", 90 | CCPW | GAXS | CARGS }, -#endif /* DYNCMD */ -#ifdef UPTIME - { 0, "UPSEND", "do_upsend", 90 | CCPW | GAXS }, -#endif /* UPTIME */ - - /* - * Level 100 - */ -#ifdef HOSTINFO - { 0, "SYSINFO", "do_sysinfo", 100 | CCPW | GAXS }, - { 0, "MEMINFO", "do_meminfo", 100 | CCPW | GAXS }, - { 0, "CPUINFO", "do_cpuinfo", 100 | CCPW | GAXS }, - { 0, "FILEMON", "do_filemon", 100 | CCPW | GAXS | CARGS }, -#endif /* HOSTINFO */ -#ifdef RAWDNS - { 0, "DNSSERVER", "do_dnsserver", 100 | CCPW | GAXS }, - { 0, "DNSROOT", "do_dnsroot", 100 | CCPW | GAXS | CARGS }, -#endif /* RAWDNS */ - { 0, "CORE", "do_core", 100 | CCPW | REDIR | DCC }, - { 0, "DIE", "do_die", 100 | CCPW | GAXS }, - { 0, "RESET", "do_reset", 100 | CCPW | GAXS | NOCMD }, - { 0, "SHUTDOWN", "do_shutdown", 100 | CCPW | GAXS | NOPUB | NOCMD }, -#ifdef DEBUG - { 0, "DEBUG", "do_debug", 100 | CCPW | GAXS }, - { 0, "CRASH", "do_crash", 100 | CCPW | GAXS }, -#endif /* DEBUG */ -#ifdef PERL -#ifdef PLEASE_HACK_MY_SHELL - { 0, "PERL", "do_perl", 100 | CCPW | GAXS | CARGS }, -#endif /* PLEASE_HACK_MY_SHELL */ - { 0, "PERLSCRIPT", "do_perlscript", 100 | CCPW | GAXS | CARGS }, -#endif /* PERL */ -#ifdef PYTHON -#ifdef PLEASE_HACK_MY_SHELL - { 0, "PYTHON", "do_python", 100 | CCPW | GAXS | CARGS }, -#endif /* PLEASE_HACK_MY_SHELL */ - { 0, "PYTHONSCRIPT", "do_pythonscript", 100 | CCPW | GAXS | CARGS }, -#endif /* PYTHON */ -#ifdef TCL -#ifdef PLEASE_HACK_MY_SHELL - { 0, "TCL", "do_tcl", 100 | CCPW | GAXS | CARGS }, -#endif /* PLEASE_HACK_MY_SHELL */ - { 0, "TCLSCRIPT", "do_tcl", 100 | CCPW | GAXS | CARGS }, -#endif /* TCL */ - /*---*/ - { 0, NULL, NULL, 0 }, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + ' ', '!', '"', '#', '$', '%', '&', 0x27, + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; -#define __define_strng 4 -#define __define_print 3 -#define __struct_acces 2 -#define __struct_print 1 +#include "onhash.h" -void make_mcmd(void) +#include "commands.h" + +#define __command_hash_9 9 +#define __print_hashta_7 7 +#define __define_strng_5 5 +#define __define_print_3 3 +#define __struct_acces_2 2 +#define __struct_print_1 1 + +static const char *getsortedcommand(int pass, int *idxout) { - const char *pt; - char tmp[100],*tabs; - int i,j,wh,pass,ct,sl,fd; + const char *chosen; + int j,index; + + chosen = NULL; + index = -1; + for(j=0;pre_mcmd[j].name;j++) + { + if (pre_mcmd[j].pass == pass) + continue; + if (chosen == NULL) + { + chosen = pre_mcmd[j].name; + index = j; + continue; + } + if (strcmp(chosen,pre_mcmd[j].name) > 0) + { + chosen = pre_mcmd[j].name; + index = j; + } + } + *idxout = index; + return(chosen); +} + +void make_mcmd(int mode) +{ + const char *cmdstr; + char tmp[257]; + int i,j,cmdidx,pass,fd,h; + int cmdcount; OnMsg v; - unlink("mcmd.h"); - fd = open("mcmd.h",O_WRONLY|O_CREAT|O_TRUNC,0644); + if (mode == 0) + { + unlink("mcmd.h"); + fd = open("mcmd.h",O_WRONLY|O_CREAT|O_TRUNC,0644); + } + if (mode == 1) + { + fd = 1; + } - pass = __define_strng; - ct = 0; + collis = 0; + pass = __command_hash_9; + cmdcount = 0; to_file(fd,"/""* This file is automatically generated from gencmd.c *""/\n"); to_file(fd,"#ifndef TEST\n#ifndef MCMD_H\n#define MCMD_H 1\n\n"); while(pass) { - if (pass == __struct_print) + if (pass == __command_hash_9) { - to_file(fd,"LS const OnMsg mcmd[] =\n{\n"); + memset(hash,0,sizeof(hash)); + memset(hashmap,255,sizeof(hashmap)); + j = 0; + if (randfd < 0) + { + randfd = open("hashdata.cache",O_RDONLY); + if (randfd > 0) + { + j = read(randfd,hashdata,sizeof(hashdata)); + close(randfd); + if (j == sizeof(hashdata)) + to_file(2,"gencmd: hashdata recovered from hashdata.cache\n"); + } + randfd = open("/dev/urandom",O_RDONLY); + if (randfd < 0) + { + to_file(2,"gencmd: Fatal error: unable to create random hashdata from /dev/urandom!\n"); + exit(50); + } + } + if (j < sizeof(hashdata)) + { + j = read(randfd,hashdata,sizeof(hashdata)); + } } - if (pass == __struct_acces) + if (pass == __print_hashta_7) { - to_file(fd,"LS OnMsg_access acmd[] =\n{\n"); } + if (pass == __struct_acces_2) + { + to_file(fd,"OnMsg_access acmd[] =\n{\n"); + } + if (pass == __struct_print_1) + { + to_file(fd,"const OnMsg mcmd[] =\n{\n"); + } + +#ifdef HEATMAP + memset(heatmap,0,sizeof(heatmap)); +#endif for(i=0;pre_mcmd[i].name;i++) { - pt = 0; - wh = 0; - for(j=0;pre_mcmd[j].name;j++) + const char *tabs,*tabx; + int adj; + + if (pass == __command_hash_9) { - if (pre_mcmd[j].pass != pass) + h = mkhash(pre_mcmd[i].name); +#ifdef HEATMAP + if (heatmapon > 0) { - pt = pre_mcmd[j].name; - wh = j; + for(j=0;j 0) ? (-1 + 'A' + heatmap[j]) : '.'); + } + to_file(2,"\nend of heatmap for %s\n",pre_mcmd[i].name); + } +#endif + if (collis > mincoll) break; - } + continue; } - for(j=0;pre_mcmd[j].name;j++) + cmdstr = getsortedcommand(pass,&cmdidx); + if (pass == __define_strng_5) { - if ((pre_mcmd[j].pass != pass) && (strcmp(pt,pre_mcmd[j].name) > 0)) + } + if (pass == __define_print_3) + { + if (cmdstr) { - pt = pre_mcmd[j].name; - wh = j; + adj = strlen(cmdstr); + tabs = ((adj) < 7) ? "\t\t" : "\t"; + to_file(fd,"BEG const char C_%s[]%s\tMDEF(\"%s\");%s/""* %3i *""/\n", + cmdstr,((adj + 3) < 8) ? "\t" : "",cmdstr,tabs,cmdcount); + cmdcount++; } } - if (pass == __define_strng) + if (pass == __struct_acces_2) { - //to_file(fd,"#define S_%s%s\t\"%s\"\n",pt,((strlen(pt) + 2) < 8) ? "\t" : "",pt); + to_file(fd,"\t%i,\t/""* %s *""/\n",pre_mcmd[cmdidx].flags & CLEVEL,cmdstr); } - if (pass == __define_print) - { - //to_file(fd,"#define C_%s%s\tmcmd[%i].name\n",pt,((strlen(pt) + 2) < 8) ? "\t" : "",ct); - to_file(fd,"BEG const char C_%s[]%s\tMDEF(\"%s\");\n",pt,((strlen(pt) + 3) < 8) ? "\t" : "",pt); - ct++; - } - if (pass == __struct_acces) - { - to_file(fd,"\t%i,\t/""* %s *""/\n", - pre_mcmd[wh].flags & CLEVEL, - pt); - } - if (pass == __struct_print) + if (pass == __struct_print_1) { + char noargfunc[64]; + h = mkhash(cmdstr); + hashmap[h] = i; + memset(&v,0,sizeof(v)); - v.defaultaccess = pre_mcmd[wh].flags & CLEVEL; + v.defaultaccess = pre_mcmd[cmdidx].flags & CLEVEL; /* + defaultaccess */ - v.dcc = (pre_mcmd[wh].flags & DCC) ? 1 : 0; - v.cc = (pre_mcmd[wh].flags & CC) ? 1 : 0; - v.pass = (pre_mcmd[wh].flags & PASS) ? 1 : 0; - v.args = (pre_mcmd[wh].flags & CARGS) ? 1 : 0; - v.nopub = (pre_mcmd[wh].flags & NOPUB) ? 1 : 0; - v.nocmd = (pre_mcmd[wh].flags & NOCMD) ? 1 : 0; - v.gaxs = (pre_mcmd[wh].flags & GAXS) ? 1 : 0; - v.caxs = (pre_mcmd[wh].flags & CAXS) ? 1 : 0; - v.redir = (pre_mcmd[wh].flags & REDIR) ? 1 : 0; - v.lbuf = (pre_mcmd[wh].flags & LBUF) ? 1 : 0; - v.cbang = (pre_mcmd[wh].flags & CBANG) ? 1 : 0; - v.acchan = (pre_mcmd[wh].flags & ACCHAN) ? 1 : 0; - v.supres = (pre_mcmd[wh].flags & SUPRES) ? 1 : 0; + if (v.defaultaccess >= 5) /* semi-public commands */ + v.cc = 1; + if (v.defaultaccess >= 10) /* normal commands */ + v.pass = 1; - sprintf(tmp,"%3i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i", + v.dcc = (pre_mcmd[cmdidx].flags & DCC) ? 1 : 0; + v.args = (pre_mcmd[cmdidx].flags & CARGS) ? 1 : 0; + v.nopub = (pre_mcmd[cmdidx].flags & NOPUB) ? 1 : 0; + v.nocmd = (pre_mcmd[cmdidx].flags & NOCMD) ? 1 : 0; + v.gaxs = (pre_mcmd[cmdidx].flags & GAXS) ? 1 : 0; + v.caxs = (pre_mcmd[cmdidx].flags & CAXS) ? 1 : 0; + v.redir = (pre_mcmd[cmdidx].flags & REDIR) ? 1 : 0; + v.lbuf = (pre_mcmd[cmdidx].flags & LBUF) ? 1 : 0; + v.cbang = (pre_mcmd[cmdidx].flags & CBANG) ? 1 : 0; + v.acchan = (pre_mcmd[cmdidx].flags & ACCHAN) ? 1 : 0; + v.supres = (pre_mcmd[cmdidx].flags & SUPRES) ? 1 : 0; + v.noargf = (pre_mcmd[cmdidx].flags & NOARGF) ? 1 : 0; + + sprintf(tmp,"%3i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i,%2i", v.defaultaccess, v.dcc, v.cc, @@ -380,42 +269,87 @@ void make_mcmd(void) v.lbuf, v.cbang, v.acchan, - v.supres + v.supres, + v.noargf ); - sl = strlen(pre_mcmd[wh].func) + 1; tabs = "\t\t\t"; - sl = (sl & ~7) / 8; - tabs += sl; + adj = strlen(cmdstr); + if (adj < 3) + tabx = tabs + 1; + else + if (adj < 11) + tabx = tabs + 2; + else + tabx = tabs + 3; - to_file(fd,(pre_mcmd[wh].cmdarg) ? "{ C_%s,%s\t%s,%s%s\t, \"%s\"\t},\n" : "{ C_%s,%s\t%s,%s%s\t},\n", - pt, - ((strlen(pt) + 5) < 8) ? "\t" : "", - pre_mcmd[wh].func, + if (v.noargf) + sprintf(noargfunc,"\n\t\t\t%s_noargs",pre_mcmd[cmdidx].func); + else + strcpy(noargfunc," 0"); + adj = strlen(pre_mcmd[cmdidx].func); + tabs += 1 + ((adj > 6)); + + //to_file(fd,"/""* %3i=%3i *""/",h,i); + to_file(fd,(pre_mcmd[cmdidx].cmdarg) ? + "{ C_%s,%s\t%s,%s,%s%s\t, \"%s\"\t},\n" : + "{ C_%s,%s\t%s,%s,%s%s\t},\n", + cmdstr, + tabx, + pre_mcmd[cmdidx].func, + noargfunc, tabs, tmp, - pre_mcmd[wh].cmdarg + pre_mcmd[cmdidx].cmdarg ); } - pre_mcmd[wh].pass = pass; + pre_mcmd[cmdidx].pass = pass; } - if (pass == __define_strng) + if (pass == __define_strng_5) { - /* nothing */ + /* nothing */; } - if (pass == __define_print) + if (pass == __define_print_3) { - to_file(fd,"\n#ifdef MAIN_C\n\n"); + to_file(fd,"\n/""* number of builtin commands: %i *""/\n\n",cmdcount); + if (cmdcount >= 255) + { + to_file(2,"gencmd: Hashmap overflow error\n"); + exit(66); + } + to_file(fd,"#ifdef MAIN_C\n\n"); } - if (pass == __struct_print) + if (pass == __struct_print_1) { to_file(fd,"{ NULL, }};\n\n"); } - if (pass == __struct_acces) + if (pass == __struct_acces_2) { to_file(fd,"};\n\n"); } + if (pass == __command_hash_9) + { + if (collis > 0) + pass = __command_hash_9 + 1; + if (collis < mincoll) + { + mincoll = collis; + to_file(fd,"\n"); + } + if (collis == 0) + { + int cachefd; + + cachefd = open("hashdata.cache",O_WRONLY|O_CREAT|O_TRUNC,0644); + write(cachefd,hashdata,sizeof(hashdata)); + close(cachefd); + } + to_file(2,"gencmd: Hash options tried: %8i, Collisions %4i, Best hash option so far %4i collisions%c", + mx,collis,mincoll,(collis == 0) ? '\n' : '\r'); + mx++; + collis = 0; + } pass--; } to_file(fd,"#define LOCALHOST_ULONG %lu\n",inet_addr("127.1")); @@ -423,8 +357,26 @@ void make_mcmd(void) to_file(fd,"extern OnMsg mcmd[];\n"); to_file(fd,"extern OnMsg_access acmd[];\n\n"); to_file(fd,"#endif /""* MAIN_C *""/\n\n"); - to_file(fd,"#endif /""* MCMD_H *""/\n\n"); - to_file(fd,"#endif /""* TEST *""/\n\n"); + + to_file(fd,"#if defined(COM_ONS_C) || defined(MEGA_C)\n\n"); + to_file(fd,"#define HASHDATAMASK\t\t%i\n",HASHDATAMASK); + to_file(fd,"#define HASHDATASZ\t\t%i\n\nconst uint8_t hashdata[HASHDATASZ] =\n{",HASHDATASZ); + for(i=0;i"); +#define EMPTYSTR (&NULLSTR[6]) +BEG const char DEFAULTSTR[] MDEF("default"); +BEG const char UNKNOWNATUNKNOWN[] MDEF("unknown@unknown"); +#define UNKNOWN (&UNKNOWNATUNKNOWN[8]) +BEG const char FMT_PLAIN[] MDEF("%s"); +BEG const char FMT_PLAINLINE[] MDEF("%s\n"); BEG const char ERR_CHAN[] MDEF("I'm not on %s"); BEG const char ERR_FILEOPEN[] MDEF("Couldn't open the file %s"); -BEG const char ERR_INIT[] MDEF("init: Warning:"); BEG const char ERR_NICK[] MDEF("Invalid nickname: %s"); BEG const char ERR_NOCHANNELS[] MDEF("I'm not active on any channels"); BEG const char ERR_NOTOPPED[] MDEF("I'm not opped on %s"); @@ -78,10 +106,8 @@ BEG const char STR_MECHRESET[] MDEF("MECHRESET="); BEG const char FMT_6XSTRTAB[] MDEF("%s\t%s\t%s\t%s\t%s\t%s"); #define FMT_4XSTRTAB &FMT_6XSTRTAB[6] #define FMT_3XSTRTAB &FMT_6XSTRTAB[9] -#define FMT_PLAIN &FMT_6XSTRTAB[15] BEG Mech *botlist MDEF(NULL); -BEG Mech *current; BEG char *executable; BEG char *configfile MDEF(CFGFILE); @@ -99,9 +125,6 @@ BEG ino_t parent_inode; BEG KillSock *killsocks MDEF(NULL); BEG Server *serverlist MDEF(NULL); -BEG ServerGroup *servergrouplist MDEF(NULL); -BEG ServerGroup *currentservergroup MDEF(NULL); -BEG int servergroupid MDEF(0); BEG int serverident MDEF(1); BEG char CurrentNick[NUHLEN]; @@ -113,9 +136,6 @@ 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]) -#define LocalBot (__internal_users[1]) /* * generic output buffer, can be used as buffer in any `leaf' function @@ -131,14 +151,6 @@ BEG char nuh_buf[NUHLEN]; BEG fd_set read_fds; BEG fd_set write_fds; -BEG int hisock; -BEG int short_tv; - -/* - * current UNIX timestamp - */ - -BEG time_t now; /* * defined features @@ -152,9 +164,6 @@ BEG Alias *aliaslist MDEF(NULL); #ifdef BOTNET -BEG const char UNKNOWNATUNKNOWN[] MDEF("unknown@unknown"); -#define UNKNOWN (&UNKNOWNATUNKNOWN[8]) - BEG BotNet *botnetlist MDEF(NULL); BEG NetCfg *netcfglist MDEF(NULL); BEG char *linkpass MDEF(NULL); /* proc var */ @@ -184,6 +193,7 @@ BEG time_t ctcp_slot[CTCP_SLOTS]; BEG char debugbuf[MAXLEN]; BEG char *debugfile MDEF(NULL); +BEG int debugfilemalloc MDEF(FALSE); BEG int dodebug MDEF(FALSE); BEG int debug_fd MDEF(-1); BEG int debug_on_exit MDEF(FALSE); @@ -204,6 +214,8 @@ BEG Note *notelist MDEF(NULL); #ifdef RAWDNS +BEG int dnssock MDEF(-1); +BEG int dnsserver MDEF(0); BEG dnsList *dnslist MDEF(NULL); BEG dnsAuthority *dnsroot MDEF(NULL); BEG struct in_addr ia_ns[MAX_NAMESERVERS]; @@ -241,12 +253,12 @@ BEG Seen *seenlist MDEF(NULL); #endif /* SEEN */ -BEG char *fontname MDEF(NULL); -BEG BigC *fontlist MDEF(NULL); -BEG int charlines; -BEG int charheight; -BEG int spacewidth; -BEG int kerning; +BEG char *fontname MDEF(NULL); +BEG BigC *fontlist MDEF(NULL); +BEG int charlines; +BEG int charheight; +BEG int spacewidth; +BEG int kerning; #ifdef TRIVIA @@ -254,6 +266,7 @@ BEG int triv_qdelay MDEF(30); /* proc var */ BEG char *triv_qfile MDEF(NULL); /* proc var */ BEG char triv_qchar MDEF('*'); /* proc var */ BEG TrivScore *scorelist MDEF(NULL); +BEG time_t triv_next_time MDEF(0); #endif /* TRIVIA */ @@ -264,7 +277,7 @@ BEG char *uptimehost MDEF(NULL); /* proc var */ BEG char *uptimenick MDEF(NULL); /* proc var */ BEG int uptimesock; BEG uint32_t uptimeip MDEF((uint32_t)-1); -BEG uint32_t uptimecookie; +BEG uint32_t uptimepackets MDEF(0); BEG uint32_t uptimeregnr MDEF(0); BEG time_t uptimelast MDEF(0); BEG const char *defaultuptimehost MDEF("uptime.eggheads.org"); @@ -300,14 +313,14 @@ BEG int spawning_lamer MDEF(0); #define CRLF 0x08 #define FNICK (NICK|FIRST) -#define NNICK (NICK|NUM) +#define NUMNI (NICK|NUM) #if defined(MAIN_C) || defined(MAKETABLES) /* * tolowertab blatantly ripped from ircu2.9.32 */ -LS const uchar tolowertab[256] = +const uchar tolowertab[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, @@ -346,7 +359,7 @@ LS const uchar tolowertab[256] = /* * be wary, this is not a normal upper-to-lower table... */ -LS const uchar nickcmptab[256] = +const uchar nickcmptab[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, @@ -382,7 +395,16 @@ LS const uchar nickcmptab[256] = 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; -LS const uchar attrtab[256] = +/* +#define NUM 0x01 +#define NICK 0x02 +#define FIRST 0x04 +#define CRLF 0x08 +#define FNICK (NICK|FIRST) +#define NUMNI (NICK|NUM) +*/ + +const uchar attrtab[256] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x07 */ 0, 0, CRLF, 0, 0, CRLF, 0, 0, /* 0x08 - 0x0F */ @@ -390,8 +412,10 @@ LS const uchar attrtab[256] = 0, 0, 0, 0, 0, 0, 0, 0, /* 0x18 - 0x1F */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x27 */ 0, 0, 0, 0, 0, NICK, 0, 0, /* 0x28 - 0x2F */ - NNICK, NNICK, NNICK, NNICK, NNICK, NNICK, NNICK, NNICK, /* 0x30 - 0x37 */ - NNICK, NNICK, 0, 0, 0, 0, 0, 0, /* 0x38 - 0x3F */ + + NUMNI, NUMNI, NUMNI, NUMNI, NUMNI, NUMNI, NUMNI, NUMNI, /* 0x30 - 0x37 */ + NUMNI, NUMNI, 0, 0, 0, 0, 0, 0, /* 0x38 - 0x3F */ + 0, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x40 - 0x47 */ FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x48 - 0x4F */ FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, FNICK, /* 0x50 - 0x57 */ @@ -425,7 +449,7 @@ LS const uchar attrtab[256] = /* * user struct for the core client */ -LS const Strp CMA = +const Strp CMA = { NULL, "*" @@ -434,37 +458,23 @@ LS const Strp CMA = /* * client struct for the core client */ -LS ShortClient CoreClient = +ShortClient CoreClient = { NULL, /* next */ - (User*)&CoreUser, /* user */ + (User*)&cx.CoreUser, /* user */ -1, /* socket */ 0, /* flags */ 0, /* inputcount */ 0 /* lasttime */ }; -LS ShortChan CoreChan = +ShortChan CoreChan = { NULL, NULL }; -typedef struct coreServerGroup -{ - ServerGroup *next; - int servergroup; - char name[8]; -} coreServerGroup; - -LS coreServerGroup defaultServerGroup = -{ - NULL, /* next */ - 0, /* servergroup */ - "default" /* name */ -}; - -LS struct +struct { const char *string; const int id; @@ -482,11 +492,8 @@ LS struct extern const uchar tolowertab[]; extern const uchar nickcmptab[]; extern const uchar attrtab[]; -extern const User xxCoreUser; -extern const User xxLocalBot; extern ShortClient CoreClient; extern ShortChan CoreChan; -extern ServerGroup defaultServerGroup; #endif /* MAIN_C */ diff --git a/src/h.h b/src/h.h index 9b2eaff..17cdd5a 100644 --- a/src/h.h +++ b/src/h.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2024 proton + Copyright (c) 1997-2025 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 @@ -21,17 +21,28 @@ #ifndef H_H #define H_H 1 +#if !defined(__STRICT_ANSI__) +#define __INLINE__ inline +#else +#define __INLINE__ +#endif + +#if defined(__GNUC__) +#define __notused__ __attribute__((unused)) +#else +#define __notused__ +#endif + #define ischannel(x) (*x == '#') -#define nullstr(x) ((x)) ? (x) : NULLSTR +#define nullstr(x) ((x) ? x : NULLSTR) #define nullbuf(x) (x && *x) ? x : NULLSTR -#define chkhigh(x) if (x > hisock) { hisock = x; } +#define chkhigh(x) if (x > cx.hisock) { cx.hisock = x; } #define COMMAND_ARGS char *from, const char *to, char *rest, const int cmdaccess -#define STRCHR stringchr -#define STREND(x) STRCHR(x,0) +#define STREND(x) stringchr(x,0) /* * some default code for socket flags @@ -67,14 +78,6 @@ #define __att2(x,y,z) /* nothing */ #endif -/* __x86_64__ automatically compiles for regparm optimization */ -#if !defined(__profiling__) && defined(__i386__) -# define __regparm(x) regparm(x) -#else -# define __regparm(x) -#endif - - #define CORE_SEG ".text.a" #define CFG1_SEG ".text.b" #define CMD1_SEG ".text.c" @@ -110,23 +113,24 @@ /* alias.c */ -LS void afmt(char *, const char *, const char *) __page(CORE_SEG); -LS void do_alias(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_unalias(COMMAND_ARGS) __page(CMD1_SEG); +void afmt(char *, const char *, const char *) __page(CORE_SEG); +void do_alias(COMMAND_ARGS) __page(CMD1_SEG); +void do_unalias(COMMAND_ARGS) __page(CMD1_SEG); /* auth.c */ -LS char *cipher(char *) __page(CMD1_SEG); -LS char *makepass(char *) __page(CMD1_SEG); -LS int passmatch(char *, char *) __page(CMD1_SEG); -LS void delete_auth(char *) __page(CMD1_SEG); -LS void remove_auth(Auth *) __page(CMD1_SEG); -LS void change_authnick(char *, char *) __page(CORE_SEG); -LS void aucheck(User *) __page(CORE_SEG); -LS User *get_authuser(const char *, const char *) __page(CORE_SEG); -LS int get_authaccess(const char *, const char *) __page(CORE_SEG); -LS int make_auth(const char *, const User *) __page(CMD1_SEG); -LS void do_auth(COMMAND_ARGS) __page(CMD1_SEG); +char *cipher(char *) __page(CMD1_SEG); +char *makepass(char *) __page(CMD1_SEG); +int passmatch(char *, char *) __page(CMD1_SEG); +void delete_auth(char *) __page(CMD1_SEG); +void remove_auth(Auth *) __page(CMD1_SEG); +void change_authnick(char *, char *) __page(CORE_SEG); +void aucheck(User *) __page(CORE_SEG); +User *get_authuser(const char *, const char *) __page(CORE_SEG); +int get_authaccess(const char *, const char *) __page(CORE_SEG); +int make_auth(const char *, const User *) __page(CMD1_SEG); +void do_auth_noargs(const char *) __page(CMD1_SEG); +void do_auth(COMMAND_ARGS) __page(CMD1_SEG); /* bounce.c */ @@ -138,62 +142,71 @@ void process_bounce(void) __page(CORE_SEG); /* calc.c */ -LS void do_convert(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_calc(COMMAND_ARGS) __page(CMD1_SEG); +void do_calc(COMMAND_ARGS) __page(CMD1_SEG); +void do_convert(COMMAND_ARGS) __page(CMD1_SEG); /* channel.c */ void check_idlekick(void); -LS Chan *find_channel(const char *, int) __attr(CORE_SEG, __regparm(2)); -LS Chan *find_channel_ac(const char *) __attr(CORE_SEG, __regparm(1)); -LS Chan *find_channel_ny(const char *) __attr(CORE_SEG, __regparm(1)); +Chan *find_channel(const char *, int) __page(CORE_SEG); +Chan *find_channel_ac(const char *) __page(CORE_SEG); +Chan *find_channel_ny(const char *) __page(CORE_SEG); void remove_chan(Chan *) __page(CMD1_SEG); void join_channel(char *, char *) __page(CFG1_SEG); void reverse_topic(Chan *, char *, char *) __page(CORE_SEG); void cycle_channel(Chan *) __page(CMD1_SEG); int reverse_mode(char *, Chan *, int, int) __page(CORE_SEG); void chan_modestr(Chan *, char *) __page(CORE_SEG); +char *get_nuh(const ChanUser *) __page(CORE_SEG); char *find_nuh(char *) __page(CORE_SEG); +char *nick2uh(char *, char *) __page(CORE_SEG); Ban *make_ban(Ban **, char *, char *, time_t); void delete_ban(Chan *, char *); void delete_modemask(Chan *, char *, int); void channel_massmode(const Chan *, char *, int, char, char); void channel_massunban(Chan *, char *, time_t); -LS ChanUser *find_chanuser(Chan *, const char *) __page(CORE_SEG); -LS ChanUser *find_chanbot(Chan *, const char *) __page(CORE_SEG); -LS void remove_chanuser(Chan *, const char *) __page(CORE_SEG); -LS void make_chanuser(char *, char *) __page(CORE_SEG); -LS void purge_chanusers(Chan *) __page(CMD1_SEG); -LS char *get_nuh(const ChanUser *) __page(CORE_SEG); -LS void do_join(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_part(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_cycle(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_forget(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_channels(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_wall(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_mode(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_names(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_cchan(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_invite(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_sayme(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_who(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_topic(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_showidle(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_idle(COMMAND_ARGS) __page(CMD1_SEG); +ChanUser *find_chanuser(Chan *, const char *) __page(CORE_SEG); +ChanUser *find_chanbot(Chan *, const char *) __page(CORE_SEG); +void remove_chanuser(Chan *, const char *) __page(CORE_SEG); +void make_chanuser(char *, char *) __page(CORE_SEG); +void purge_chanusers(Chan *) __page(CMD1_SEG); +void do_join(COMMAND_ARGS) __page(CMD1_SEG); +void do_part(COMMAND_ARGS) __page(CMD1_SEG); +void do_cycle(COMMAND_ARGS) __page(CMD1_SEG); +void do_forget(COMMAND_ARGS) __page(CMD1_SEG); +void do_channels(COMMAND_ARGS) __page(CMD1_SEG); +void do_wall(COMMAND_ARGS) __page(CMD1_SEG); +void do_mode(COMMAND_ARGS) __page(CMD1_SEG); +void do_names(COMMAND_ARGS) __page(CMD1_SEG); +void do_cchan(COMMAND_ARGS) __page(CMD1_SEG); +void do_invite(COMMAND_ARGS) __page(CMD1_SEG); +void do_sayme(COMMAND_ARGS) __page(CMD1_SEG); +void do_who(COMMAND_ARGS) __page(CMD1_SEG); +void do_topic(COMMAND_ARGS) __page(CMD1_SEG); +void do_showidle(COMMAND_ARGS) __page(CMD1_SEG); +void do_idle(COMMAND_ARGS) __page(CMD1_SEG); /* core.c */ -void unlink_identfile(void); +#define getbotnicklen(z) (z->nick.opt) +#define getbotnick(z) ((z->nick.opt < 16) ? z->nick.x.string : z->nick.x.ptr) +#define getbotwantnick(z) ((z->wantnick.opt < 16) ? z->wantnick.x.string : z->wantnick.x.ptr) +#define getbotuserhost(z) ((z->userhost.opt == 0) ? UNKNOWNATUNKNOWN : ((z->userhost.opt < 64) ? z->userhost.x.string : z->userhost.x.ptr)) + +#define setbotnick(z,y) set_mix16(&z->nick,y) +#define setbotwantnick(z,y) set_mix16(&z->wantnick,y) +#define setbotuserhost(z,y) set_mix64(&z->userhost,y) + +void set_mix16(Mix16 *, const char *) __page(CORE_SEG); +void set_mix64(Mix64 *, const char *) __page(CORE_SEG); + int conf_callback(char *line) __page(CFG1_SEG); -void readcfgfile(void) __page(CFG1_SEG); +void readcfgfile(void) __page(INIT_SEG); int write_session(void) __page(CORE_SEG); -void setbotnick(Mech *bot, char *nick) __page(CFG1_SEG); Mech *add_bot(int guid, char *nick) __page(CFG1_SEG); void signoff(char *from, char *reason) __page(RARE_SEG); void kill_all_bots(char *reason) __attr(RARE_SEG, __noreturn__);; -Server *add_server(char *host, int port, char *pass) __page(CFG1_SEG); -ServerGroup *getservergroup(const char *name); -ServerGroup *getservergroupid(int id); +Server *add_server(const char *host, const int port, const char *pass, const char *group) __page(CFG1_SEG); Server *find_server(int id) __page(CORE_SEG); int try_server(Server *sp, char *hostname) __page(CORE_SEG); void connect_to_server(void) __page(CORE_SEG); @@ -206,7 +219,7 @@ void do_version(COMMAND_ARGS) __page(CMD1_SEG); void do_core(COMMAND_ARGS) __page(CMD1_SEG); void do_die(COMMAND_ARGS) __page(RARE_SEG); void do_shutdown(COMMAND_ARGS) __page(RARE_SEG); -void do_servergroup(COMMAND_ARGS) __page(CMD1_SEG); +void do_server_noargs(const char *from) __page(CMD1_SEG); void do_server(COMMAND_ARGS) __page(CMD1_SEG); void do_cserv(COMMAND_ARGS) __page(CMD1_SEG); void do_away(COMMAND_ARGS) __page(CMD1_SEG); @@ -253,8 +266,9 @@ char *uint32tobin(int limit, uint32_t x); void debug_scripthook(void); void run_debug(void); int wrap_debug(void); -void do_debug(COMMAND_ARGS) __page(CMD1_SEG); void do_crash(COMMAND_ARGS) __page(RARE_SEG); +void do_debug(COMMAND_ARGS) __page(CMD1_SEG); +void do_inject(COMMAND_ARGS) __page(CMD1_SEG); void debug(char *format, ...) __page(CORE_SEG); /* dns.c */ @@ -277,43 +291,34 @@ void do_dnsserver(COMMAND_ARGS) __page(CMD1_SEG); void do_dns(COMMAND_ARGS) __page(CMD1_SEG); /* dynamode.c */ + /* function.c */ -LS void *Calloc(int) __attr(CORE_SEG, __regparm(1)); -LS void Free(char **) __attr(CORE_SEG, __regparm(1)); -LS Strp *make_strp(Strp **, const char *) __attr(CORE_SEG, __regparm(2)); -LS Strp *append_strp(Strp **, const char *) __attr(CORE_SEG, __regparm(2)); -LS Strp *prepend_strp(Strp **, const char *) __attr(CORE_SEG, __regparm(2)); -LS void purge_linklist(void **) __attr(CORE_SEG, __regparm(1)); -LS void dupe_strp(Strp *, Strp **) __attr(CORE_SEG, __regparm(2)); -LS const int StrlenX(const char *, ...) __attr(CORE_SEG, __regparm(1)); -LS const int Strlen2(const char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS char *getuh(char *) __page(CORE_SEG); -LS char *get_token(char **, const char *) __page(CORE_SEG); -LS char *logtime(time_t) __page(CORE_SEG); -LS char *time2str(time_t) __page(CORE_SEG); -LS char *time2away(time_t) __page(CORE_SEG); -LS char *time2medium(time_t) __page(CORE_SEG); -LS char *time2small(time_t) __page(CORE_SEG); -LS char *idle2str(time_t, int) __page(CORE_SEG); -LS const char *get_channel(const char *, char **) __page(CORE_SEG); -LS const char *get_channel2(const char *, char **) __page(CORE_SEG); -LS char *cluster(char *) __page(CORE_SEG); -LS char *format_uh(char *, int) __page(CORE_SEG); -LS char *nick2uh(char *, char *) __page(CORE_SEG); -LS void deop_ban(Chan *, ChanUser *, char *) __page(CORE_SEG); -LS void deop_siteban(Chan *, ChanUser *) __page(CORE_SEG); -LS void screwban_format(char *) __page(CORE_SEG); -LS void deop_screwban(Chan *, ChanUser *) __page(CORE_SEG); -LS int is_nick(const char *) __attr(CORE_SEG, __regparm(1)); -LS int asc2int(const char *) __attr(CORE_SEG, __regparm(1)); -LS int get_number(const char *) __attr(CORE_SEG, __regparm(1)); -LS void fix_config_line(char *) __page(CFG1_SEG); -LS int matches(const char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS int num_matches(const char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS void table_buffer(const char *, ...) __page(CMD1_SEG); -LS void table_send(const char *, const int) __page(CMD1_SEG); -LS int is_safepath(const char *, int) __attr(CORE_SEG, __regparm(2)); +void *Calloc(int) __page(CORE_SEG); +void Free(char **) __page(CORE_SEG); +Strp *make_strp(Strp **, const char *) __page(CORE_SEG); +Strp *append_strp(Strp **, const char *) __page(CORE_SEG); +Strp *prepend_strp(Strp **, const char *) __page(CORE_SEG); +void purge_linklist(void **) __page(CORE_SEG); +void dupe_strp(Strp *, Strp **) __page(CORE_SEG); +const int StrlenX(const char *, ...) __page(CORE_SEG); +const int Strlen2(const char *, const char *) __page(CORE_SEG); +char *getuh(char *) __page(CORE_SEG); +char *get_token(char **, const char *) __page(CORE_SEG); +char *maketimestr(time_t, int) __page(CORE_SEG); +char *idle2str(time_t, int) __page(CORE_SEG); +const char *get_channel(const char *, char **) __page(CORE_SEG); +const char *get_channel2(const char *, char **) __page(CORE_SEG); +char *cluster(char *) __page(CORE_SEG); +char *format_uh(char *, int) __page(CORE_SEG); +int is_nick(const char *) __page(CORE_SEG); +int asc2int(const char *) __page(CORE_SEG); +int get_number(const char *) __page(CORE_SEG); +void parse_range(char **, int *) __page(CORE_SEG); +void fix_config_line(char *) __page(CFG1_SEG); +int matches(const char *, const char *) __page(CORE_SEG); +int num_matches(const char *, const char *) __page(CORE_SEG); +int is_safepath(const char *, int) __page(CORE_SEG); /* greet.c */ @@ -343,25 +348,27 @@ void do_filemon(COMMAND_ARGS) __page(CMD1_SEG); /* io.c */ -LS uint32_t get_ip(const char *) __page(CORE_SEG); -LS void SockFlags(int) __page(CORE_SEG); -LS int SockOpts(void) __page(CORE_SEG); -LS int SockListener(int) __page(CORE_SEG); -LS int SockConnect(char *, int, int) __page(CORE_SEG); -LS int SockAccept(int) __page(CORE_SEG); +uint32_t get_ip(const char *) __page(CORE_SEG); +void SockFlags(int) __page(CORE_SEG); +int SockOpts(void) __page(CORE_SEG); +int SockListener(int) __page(CORE_SEG); +int SockConnect(char *, int, int) __page(CORE_SEG); +int SockAccept(int) __page(CORE_SEG); int to_file(const int sock, const char *format, ...) __page(CORE_SEG); -void to_server(char *format, ...) __page(CORE_SEG); +void to_server(const char *format, ...) __page(CORE_SEG); void to_user_q(const char *, const char *, ...) __page(CMD1_SEG); void to_user(const char *, const char *, ...) __page(CORE_SEG); +void table_buffer(const char *, ...) __page(CMD1_SEG); +void table_send(const char *, const int) __page(CMD1_SEG); char *sockread(int, char *, char *) __page(CORE_SEG); void readline(int, int (*)(char *)) __page(CMD1_SEG); void remove_ks(KillSock *); int killsock(int); -LS void do_clearqueue(COMMAND_ARGS) __page(CMD1_SEG); +void do_clearqueue(COMMAND_ARGS) __page(CMD1_SEG); /* irc.c */ -LS void make_ireq(int, const char *, const char *) __page(CMD1_SEG); +void make_ireq(int, const char *, const char *) __page(CMD1_SEG); void send_pa(int type, const char *nick, const char *format, ...); void do_irclusers(COMMAND_ARGS) __page(CMD1_SEG); void do_ircstats(COMMAND_ARGS) __page(CMD1_SEG); @@ -376,50 +383,51 @@ void purge_kicklist(void); void do_kicksay(COMMAND_ARGS) __page(CMD1_SEG); void do_rkicksay(COMMAND_ARGS) __page(CMD1_SEG); -/* lib/string.c */ +/* string.c */ -LS char *chop(char **) __attr(CORE_SEG, __regparm(1)); -LS void unchop(char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS int stringcasecmp(const char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS int stringcmp(const char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS int nickcmp(const char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS char *nickcpy(char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS void stringcpy_n(char *, const char *, int) __attr(CORE_SEG, __regparm(3)); -LS char *stringcpy(char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS char *stringchr(const char *, int) __attr(CORE_SEG, __regparm(2)); -LS char *stringdup(const char *) __attr(CORE_SEG, __regparm(1)); -LS char *stringcat(char *, const char *) __attr(CORE_SEG, __regparm(2)); -LS char *tolowercat(char *, const char *) __attr(CORE_SEG, __regparm(2)); +char *chop(char **) __page(CORE_SEG); +void unchop(char *, const char *) __page(CORE_SEG); +int stringcasecmp(const char *, const char *) __page(CORE_SEG); +int stringcmp(const char *, const char *) __page(CORE_SEG); +int nickcmp(const char *, const char *) __page(CORE_SEG); +char *nickcpy(char *, const char *) __page(CORE_SEG); +void stringcpy_n(char *, const char *, int) __page(CORE_SEG); +char *stringcpy(char *, const char *) __page(CORE_SEG); +char *stringchr(const char *, int) __page(CORE_SEG); +char *stringdup(const char *) __page(CORE_SEG); +char *stringcat(char *, const char *) __page(CORE_SEG); +char *tolowercat(char *, const char *) __page(CORE_SEG); /* main.c */ void mech_exec(void) __page(RARE_SEG); int randstring_count(char *line) __page(CMD1_SEG); int randstring_getline(char *line) __page(CMD1_SEG); -LS char *randstring(const char *) __page(CORE_SEG); -LS int sig_hup_callback(char *) __page(RARE_SEG); /* rare */ -LS void do_sighup(void) __page(CMD1_SEG); -LS void sig_hup(int) __page(RARE_SEG); /* rare */ -LS void sig_child(int) __page(RARE_SEG); /* rare */ -LS void sig_alrm(int) __page(RARE_SEG); /* rare */ -LS void sig_pipe(int) __page(CORE_SEG); -LS void do_sigusr1(void) __page(CMD1_SEG); -LS void sig_usr1(int) __page(CMD1_SEG); -LS void sig_usr2(int) __page(DBUG_SEG); /* DEBUG */ -LS void sig_suicide() __attr(RARE_SEG, __noreturn__); /* rare */ -LS void do_sigint(void) __page(RARE_SEG); /* rare */ -LS void sig_int(int) __page(RARE_SEG); /* rare */ -LS void sig_ill(int) __page(RARE_SEG); -LS void sig_abrt(int) __page(RARE_SEG); -LS void sig_bus(int) __page(CMD1_SEG); +char *randstring(const char *) __page(CORE_SEG); +int sig_hup_callback(char *) __page(RARE_SEG); /* rare */ +void do_sighup(void) __page(CMD1_SEG); +void sig_hup(int) __page(RARE_SEG); /* rare */ +void sig_child(int) __page(RARE_SEG); /* rare */ +void sig_alrm(int) __page(RARE_SEG); /* rare */ +void sig_pipe(int) __page(CORE_SEG); +void do_sigusr1(void) __page(CMD1_SEG); +void sig_usr1(int) __page(CMD1_SEG); +void sig_usr2(int) __page(DBUG_SEG); /* DEBUG */ +void sig_suicide() __attr(RARE_SEG, __noreturn__); /* rare */ +void do_sigint(void) __attr(RARE_SEG, __noreturn__); /* rare */ +void sig_int(int) __page(RARE_SEG); /* rare */ +void sig_ill(int) __page(RARE_SEG); +void sig_abrt(int) __page(RARE_SEG); +void sig_bus(int) __attr(RARE_SEG, __noreturn__); #if defined(__linux__) && defined(__x86_64__) && defined(DEBUG) && !defined(__STRICT_ANSI__) -LS void sig_segv(int, siginfo_t *, void *) __attr(RARE_SEG, __noreturn__); +void sig_segv(int, siginfo_t *, void *) __attr(RARE_SEG, __noreturn__); #else -LS void sig_segv(int) __attr(RARE_SEG, __noreturn__); +void sig_segv(int) __attr(RARE_SEG, __noreturn__); #endif -LS void sig_term(int) __attr(RARE_SEG, __noreturn__); /* rare */ -LS void doit(void) __page(CORE_SEG); -LS int main(int argc, char **argv, char **envp) __page(INIT_SEG); +void sig_term(int) __attr(RARE_SEG, __noreturn__); /* rare */ +int main(int argc, char **argv, char **envp) __page(INIT_SEG); +void parse_commandline(int argc, char **argv, char **envp) __page(INIT_SEG); +void mainloop(void) __attr(CORE_SEG, __noreturn__); /* net.c */ @@ -434,15 +442,15 @@ void botnet_binfo_relay(BotNet *source, BotInfo *binfo); void botnet_binfo_tofile(int sock, BotInfo *binfo); void botnet_dumplinklist(BotNet *bn); int connect_to_bot(NetCfg *cfg); -LS void check_botjoin(Chan *chan, ChanUser *cu); -LS void check_botinfo(BotInfo *binfo, const char *channel); +void check_botjoin(Chan *chan, ChanUser *cu); +void check_botinfo(BotInfo *binfo, const char *channel); void basicAuth(BotNet *bn, char *rest); void basicAuthOK(BotNet *bn, char *rest); void basicBanner(BotNet *bn, char *rest); void basicLink(BotNet *bn, char *version); void basicQuit(BotNet *bn, char *rest); -LS void netchanNeedop(BotNet *source, char *rest); -LS void netchanSuppress(BotNet *, char *) __page(CORE_SEG); +void netchanNeedop(BotNet *source, char *rest); +void netchanSuppress(BotNet *, char *) __page(CORE_SEG); void partyAuth(BotNet *bn, char *rest); int commandlocal(int dg, int sg, char *from, char *command); void partyCommand(BotNet *bn, char *rest); @@ -454,12 +462,13 @@ void parse_botnet(BotNet *bn, char *rest); void botnet_newsock(void); void select_botnet(void) __page(CORE_SEG); void process_botnet(void) __page(CORE_SEG); +void do_link_noargs(const char *) __page(CMD1_SEG); void do_link(COMMAND_ARGS) __page(CMD1_SEG); void do_cmd(COMMAND_ARGS) __page(CMD1_SEG); /* note.c */ -int catch_note(char *from, char *to, char *rest); +int catch_note(char *from, char *to, char *rest) __page(CMD1_SEG); void do_note(COMMAND_ARGS) __page(CMD1_SEG); void do_read(COMMAND_ARGS) __page(CMD1_SEG); @@ -482,104 +491,108 @@ void do_notify(COMMAND_ARGS) __page(CMD1_SEG); /* ons.c */ -LS uint32_t makecrc(const char *) __page(CORE_SEG); -LS void send_suppress(const char *, const char *) __page(CORE_SEG); -LS void on_kick(char *from, char *rest) __page(CORE_SEG); -LS void on_join(Chan *chan, char *from) __page(CORE_SEG); -LS void on_nick(char *from, char *newnick) __page(CORE_SEG); -LS void on_msg(char *from, char *to, char *rest) __page(CORE_SEG); -LS void on_mode(char *from, char *channel, char *rest) __page(CORE_SEG); -LS void common_public(Chan *chan, char *from, char *spyformat, char *rest) __page(CORE_SEG); -LS void on_action(char *from, char *to, char *rest) __page(CORE_SEG); -LS int access_needed(char *name) __page(CORE_SEG); -LS void do_chaccess(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_last(COMMAND_ARGS) __page(CMD1_SEG); +uint32_t makecrc(const char *) __page(CORE_SEG); +void send_suppress(const char *, const char *) __page(CORE_SEG); +void on_kick(char *from, char *rest) __page(CORE_SEG); +void on_join(Chan *chan, char *from) __page(CORE_SEG); +void on_nick(char *from, char *newnick) __page(CORE_SEG); +int mkhash(const char *) __page(CORE_SEG); +void on_msg(char *from, char *to, char *rest) __page(CORE_SEG); +void on_mode(char *from, char *channel, char *rest) __page(CORE_SEG); +void common_public(Chan *chan, char *from, char *spyformat, char *rest) __page(CORE_SEG); +void on_action(char *from, char *to, char *rest) __page(CORE_SEG); +int access_needed(char *name) __page(CORE_SEG); +void do_chaccess(COMMAND_ARGS) __page(CMD1_SEG); +void do_last(COMMAND_ARGS) __page(CMD1_SEG); /* parse.c */ -LS void parse_error(char *from, char *rest) __page(CORE_SEG); -LS void parse_invite(char *from, char *rest) __page(CMD1_SEG); -LS void parse_join(char *from, char *rest) __page(CORE_SEG); -LS void parse_mode(char *from, char *rest) __page(CORE_SEG); -LS void parse_notice(char *from, char *rest) __page(CORE_SEG); -LS void parse_part(char *from, char *rest) __page(CORE_SEG); -LS void parse_ping(char *from, char *rest) __page(CORE_SEG); -LS void parse_pong(char *from, char *rest) __page(CORE_SEG); -LS void parse_privmsg(char *from, char *rest) __page(CORE_SEG); -LS void parse_quit(char *from, char *rest) __page(CORE_SEG); -LS void parse_topic(char *from, char *rest) __page(CORE_SEG); -LS void parse_wallops(char *from, char *rest) __page(CORE_SEG); -LS void parse_213(char *from, char *rest); -LS void parse_219(char *from, char *rest); -LS void parse_251(char *from, char *rest); -LS void parse_252(char *from, char *rest); -LS void parse_253(char *from, char *rest); -LS void parse_254(char *from, char *rest); -LS void parse_255(char *from, char *rest); -LS void parse_301(char *from, char *rest); -LS void parse_303(char *from, char *rest); -LS void parse_311(char *from, char *rest); -LS void parse_312(char *from, char *rest); -LS void parse_313(char *from, char *rest); -LS void parse_315(char *from, char *rest); -LS void parse_317(char *from, char *rest); -LS void parse_318(char *from, char *rest); -LS void parse_319(char *from, char *rest); -LS void parse_324(char *from, char *rest); -LS void parse_352(char *from, char *rest); -LS void parse_367(char *from, char *rest); -LS void parse_376(char *from, char *rest); -LS void parse_401(char *from, char *rest); -LS void parse_433(char *from, char *rest); -LS void parse_451(char *from, char *rest); -LS void parse_471(char *from, char *rest); -LS void parse_473(char *from, char *rest); -LS void parse_346(char *from, char *rest); -LS void parse_348(char *from, char *rest); -LS void parse_368(char *from, char *rest); -LS void parse_005(char *from, char *rest); -LS uint32_t stringhash(char *s) __page(CORE_SEG); -LS void parse_server_input(char *rest) __page(CORE_SEG); +void parse_error(char *from, char *rest) __page(CORE_SEG); +void parse_invite(char *from, char *rest) __page(CMD1_SEG); +void parse_join(char *from, char *rest) __page(CORE_SEG); +void parse_mode(char *from, char *rest) __page(CORE_SEG); +void parse_notice(char *from, char *rest) __page(CORE_SEG); +void parse_part(char *from, char *rest) __page(CORE_SEG); +void parse_ping(char *from, char *rest) __page(CORE_SEG); +void parse_pong(char *from, char *rest) __page(CORE_SEG); +void parse_privmsg(char *from, char *rest) __page(CORE_SEG); +void parse_quit(char *from, char *rest) __page(CORE_SEG); +void parse_topic(char *from, char *rest) __page(CORE_SEG); +void parse_wallops(char *from, char *rest) __page(CORE_SEG); +void parse_213(char *from, char *rest) __page(CORE_SEG); +void parse_219(char *from, char *rest) __page(CORE_SEG); +void parse_251(char *from, char *rest) __page(CORE_SEG); +void parse_252(char *from, char *rest) __page(CORE_SEG); +void parse_253(char *from, char *rest) __page(CORE_SEG); +void parse_254(char *from, char *rest) __page(CORE_SEG); +void parse_255(char *from, char *rest) __page(CORE_SEG); +void parse_301(char *from, char *rest) __page(CORE_SEG); +void parse_303(char *from, char *rest) __page(CORE_SEG); +void parse_311(char *from, char *rest) __page(CORE_SEG); +void parse_312(char *from, char *rest) __page(CORE_SEG); +void parse_313(char *from, char *rest) __page(CORE_SEG); +void parse_315(char *from, char *rest) __page(CORE_SEG); +void parse_317(char *from, char *rest) __page(CORE_SEG); +void parse_318(char *from, char *rest) __page(CORE_SEG); +void parse_319(char *from, char *rest) __page(CORE_SEG); +void parse_324(char *from, char *rest) __page(CORE_SEG); +void parse_352(char *from, char *rest) __page(CORE_SEG); +void parse_367(char *from, char *rest) __page(CORE_SEG); +void parse_376(char *from, char *rest) __page(CORE_SEG); +void parse_401(char *from, char *rest) __page(CORE_SEG); +void parse_433(char *from, char *rest) __page(CORE_SEG); +void parse_451(char *from, char *rest) __page(CORE_SEG); +void parse_471(char *from, char *rest) __page(CORE_SEG); +void parse_473(char *from, char *rest) __page(CORE_SEG); +void parse_346(char *from, char *rest) __page(CORE_SEG); +void parse_348(char *from, char *rest) __page(CORE_SEG); +void parse_368(char *from, char *rest) __page(CORE_SEG); +void parse_005(char *from, char *rest) __page(CORE_SEG); +void parse_server_input(char *) __page(CORE_SEG); /* partyline.c */ -LS int check_telnet(int, char *) __page(CMD1_SEG); -LS void check_telnet_pass(Client *, char *) __page(CMD1_SEG); -LS int partyline_only_command(const char *) __page(CMD1_SEG); -LS void partyline_broadcast(const Client *, const char *, const char *) __page(CMD1_SEG); -LS void partyline_banner(Client *) __page(CMD1_SEG); -LS void dcc_chat(char *) __page(CMD1_SEG); -LS void whom_printbot(char *, BotInfo *, char *) __page(CMD1_SEG); -LS void do_whom(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_chat(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_bye(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_boot(COMMAND_ARGS) __page(CMD1_SEG); +int check_telnet(int, char *) __page(CMD1_SEG); +void check_telnet_pass(Client *, char *) __page(CMD1_SEG); +int partyline_only_command(const char *) __page(CMD1_SEG); +void partyline_broadcast(const Client *, const char *, const char *) __page(CMD1_SEG); +void partyline_banner(Client *) __page(CMD1_SEG); +void dcc_chat(char *) __page(CMD1_SEG); +void whom_printbot(char *, BotInfo *, char *) __page(CMD1_SEG); +void do_whom(COMMAND_ARGS) __page(CMD1_SEG); +void do_chat(COMMAND_ARGS) __page(CMD1_SEG); +void do_bye(COMMAND_ARGS) __page(CMD1_SEG); +void do_boot(COMMAND_ARGS) __page(CMD1_SEG); /* perl.c */ -LS void do_perl(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_perlscript(COMMAND_ARGS) __page(CMD1_SEG); +void do_perl(COMMAND_ARGS) __page(CMD1_SEG); +void do_perlscript(COMMAND_ARGS) __page(CMD1_SEG); /* prot.c */ -LS void send_kick(Chan *chan, const char *nick, const char *format, ...); -LS void push_kicks(Chan *chan); -LS void unmode_chanuser(Chan *chan, ChanUser *cu); -LS void send_mode(Chan *chan, int pri, int type, char plusminus, char modeflag, void *data); -LS int mode_effect(Chan *chan, qMode *mode); -LS void push_modes(Chan *chan, int lowpri); -LS void update_modes(Chan *chan); -LS int check_mass(Chan *chan, ChanUser *doer, int type); -LS void mass_action(Chan *chan, ChanUser *doer); -LS void prot_action(Chan *chan, char *from, ChanUser *doer, char *target, ChanUser *victim); -LS void process_chanbans(void); -LS void chanban_action(char *, char *, Shit *); -LS void check_dynamode(Chan *) __page(CORE_SEG); -LS void do_opdeopme(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_opvoice(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_kickban(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_unban(COMMAND_ARGS) __page(CMD1_SEG); -LS void do_banlist(COMMAND_ARGS) __page(CMD1_SEG); +void screwban_format(char *) __page(CORE_SEG); +void deop_ban(Chan *, ChanUser *, char *) __page(CORE_SEG); +void deop_siteban(Chan *, ChanUser *) __page(CORE_SEG); +void deop_screwban(Chan *, ChanUser *) __page(CORE_SEG); +void send_kick(Chan *chan, const char *nick, const char *format, ...); +void push_kicks(Chan *chan); +void unmode_chanuser(Chan *chan, ChanUser *cu); +void send_mode(Chan *chan, int pri, int type, char plusminus, char modeflag, void *data); +int mode_effect(Chan *chan, qMode *mode); +void push_modes(Chan *chan, int lowpri); +void update_modes(Chan *chan); +int check_mass(Chan *chan, ChanUser *doer, int type); +void mass_action(Chan *chan, ChanUser *doer); +void prot_action(Chan *chan, char *from, ChanUser *doer, char *target, ChanUser *victim); +void process_chanbans(void); +void chanban_action(char *, char *, Shit *); +void check_dynamode(Chan *) __page(CORE_SEG); +void do_opdeopme(COMMAND_ARGS) __page(CMD1_SEG); +void do_opvoice(COMMAND_ARGS) __page(CMD1_SEG); +void do_kickban(COMMAND_ARGS) __page(CMD1_SEG); +void do_unban(COMMAND_ARGS) __page(CMD1_SEG); +void do_banlist(COMMAND_ARGS) __page(CMD1_SEG); /* python.c */ @@ -646,8 +659,8 @@ void send_spy(const char *src, const char *format, ...) __page(CORE_SEG); void send_global(const char *src, const char *format, ...) __page(CORE_SEG); void spy_typecount(Mech *bot) __page(CORE_SEG); int spy_source(char *from, int *t_src, const char **src) __page(CORE_SEG); -char *urlhost(const char *) __page(CORE_SEG); -LS void urlcapture(const char *) __page(CORE_SEG); +void urlhost(const char *) __page(CORE_SEG); +void urlcapture(const char *) __page(CORE_SEG); int begin_redirect(char *, char *) __page(CORE_SEG); void send_redirect(char *) __page(CORE_SEG); void end_redirect(void) __page(CORE_SEG); @@ -656,61 +669,61 @@ void stats_plusminususer(Chan *chan, int plusminus) __page(CORE_SEG); 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); +void do_urlhist(COMMAND_ARGS) __page(CMD1_SEG); /* tcl.c */ #ifdef TCL /* -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); +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); */ -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); +int tcl_timer_jump(Hook *hook); +int tcl_parse_jump(char *from, char *rest, Hook *hook); +void tcl_dcc_complete(Client *client, int cps); #if defined(DEBUG_C) || defined(MEGA_C) -LS int tcl_hook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); +int tcl_hook(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]); #endif /* -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[]); +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[]); */ -LS void init_tcl(void); -LS void do_tcl(COMMAND_ARGS) __page(CMD1_SEG); +void init_tcl(void); +void do_tcl(COMMAND_ARGS) __page(CMD1_SEG); #endif /* TCL */ /* toybox.c */ -LS int read_charset_callback(char *) __page(CMD1_SEG); -LS int read_bigcharset(char *) __page(CMD1_SEG); -LS int read_ascii(char *) __page(CMD1_SEG); -LS void trivia_week_toppers(void) __page(CMD1_SEG); -LS void hint_one(void) __page(CMD1_SEG); -LS void hint_two(void) __page(CMD1_SEG); -LS void hint_three(void) __page(CMD1_SEG); -LS void trivia_cleanup(void) __page(CMD1_SEG); -LS void trivia_check(Chan *, char *) __page(CMD1_SEG); -LS void trivia_no_answer(void) __page(CMD1_SEG); -LS char *random_question(char *) __page(CMD1_SEG); -LS void trivia_question(void) __page(CMD1_SEG); -LS void trivia_tick(void) __page(CMD1_SEG); -LS void write_triviascore(void) __page(CMD1_SEG); -LS int trivia_score_callback(char *) __page(CMD1_SEG); -LS void read_triviascore(void) __page(CMD1_SEG); -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); -LS void do_trivia(COMMAND_ARGS) __page(CMD1_SEG); +int read_charset_callback(char *) __page(CMD1_SEG); +int read_bigcharset(char *) __page(CMD1_SEG); +int read_ascii(char *) __page(CMD1_SEG); +void trivia_week_toppers(void) __page(CMD1_SEG); +void hint_one(void) __page(CMD1_SEG); +void hint_two(void) __page(CMD1_SEG); +void hint_three(void) __page(CMD1_SEG); +void trivia_cleanup(void) __page(CMD1_SEG); +void trivia_check(Chan *, char *) __page(CMD1_SEG); +void trivia_no_answer(void) __page(CMD1_SEG); +char *random_question(char *) __page(CMD1_SEG); +void trivia_question(void) __page(CMD1_SEG); +void trivia_tick(void) __page(CMD1_SEG); +void write_triviascore(void) __page(CMD1_SEG); +int trivia_score_callback(char *) __page(CMD1_SEG); +void read_triviascore(void) __page(CMD1_SEG); +void do_bigsay(COMMAND_ARGS) __page(CMD1_SEG); +void do_randmsg(COMMAND_ARGS) __page(CMD1_SEG); +void do_randtopic(COMMAND_ARGS) __page(CMD1_SEG); +void do_8ball(COMMAND_ARGS) __page(CMD1_SEG); +void do_ascii(COMMAND_ARGS) __page(CMD1_SEG); +void do_rand(COMMAND_ARGS) __page(CMD1_SEG); +void do_trivia(COMMAND_ARGS) __page(CMD1_SEG); /* uptime.c */ @@ -723,36 +736,36 @@ void do_upsend(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); -LS void cfg_mask(char *) __page(CFG1_SEG); -LS void cfg_chan(char *) __page(CFG1_SEG); -LS void cfg_opt(char *) __page(CFG1_SEG); -LS void cfg_shit(char *) __page(CFG1_SEG); -void cfg_kicksay(char *); -LS void cfg_greet(char *) __page(CFG1_SEG); -LS void cfg_note(char *) __page(CFG1_SEG); -void user_sync(void); -int read_userlist_callback(char *); -int read_userlist(char *); -int write_userlist(char *); -void rehash_chanusers(void); -LS void addtouser(Strp **, const char *, int) __attr(CORE_SEG, __regparm(3)); -LS int remfromuser(Strp **, const char *) __attr(CORE_SEG, __regparm(2)); +void cfg_user(char *) __page(CFG1_SEG); +void cfg_modcount(char *) __page(CFG1_SEG); +void cfg_pass(char *) __page(CFG1_SEG); +void cfg_mask(char *) __page(CFG1_SEG); +void cfg_chan(char *) __page(CFG1_SEG); +void cfg_opt(char *) __page(CFG1_SEG); +void cfg_shit(char *) __page(CFG1_SEG); +void cfg_kicksay(char *) __page(CFG1_SEG); +void cfg_greet(char *) __page(CFG1_SEG); +void cfg_note(char *) __page(CFG1_SEG); +void user_sync(void) __page(CFG1_SEG); +int read_userlist_callback(char *) __page(CFG1_SEG); +int read_userlist(char *) __page(CFG1_SEG); +int write_userlist(char *) __page(CMD1_SEG); +void rehash_chanusers(void) __page(CORE_SEG); +void addtouser(Strp **, const char *, int) __page(CORE_SEG); +int remfromuser(Strp **, const char *) __page(CORE_SEG); void mirror_user(User *) __page(CORE_SEG); void mirror_userlist(void) __page(CORE_SEG); -void reset_userlink(User *, User *); -void remove_user(User *); -User *add_user(char *, char *, int); -User *find_handle(const char *); -int userhaschannel(const User *, const char *); +void reset_userlink(User *, User *) __page(CORE_SEG); +void remove_user(User *) __page(CFG1_SEG); +User *add_user(char *, char *, int) __page(CFG1_SEG); +User *find_handle(const char *) __page(CORE_SEG); +int userhaschannel(const User *, const char *) __page(CORE_SEG); User *get_user(const char *, const char *) __page(CORE_SEG); int get_useraccess(const char *, const char *) __page(CORE_SEG); int get_maxaccess(const char *) __page(CORE_SEG); int is_bot(const char *) __page(CORE_SEG); int get_protaction(Chan *, char *) __page(CORE_SEG); -int usercanmodify(const char *, const User *); +int usercanmodify(const char *, const User *) __page(CMD1_SEG); void change_pass(User *, char *) __page(CMD1_SEG); void do_access(COMMAND_ARGS) __page(CMD1_SEG); void do_userlist(COMMAND_ARGS) __page(CMD1_SEG); @@ -770,7 +783,7 @@ int find_setting(const char *) __page(CORE_SEG); void copy_vars(UniVar *, UniVar *) __page(CFG1_SEG); void set_binarydefault(UniVar *) __page(CFG1_SEG); void delete_vars(UniVar *, int) __page(CMD1_SEG); -void var_resolve_host(const struct Setting *); +void var_resolve_host(const struct Setting *) __page(CMD1_SEG); void nobo_strcpy(const char *) __page(CMD1_SEG); void ec_access(char *, const char *) __page(CMD1_SEG); void ec_capabilities(char *, const char *) __page(CMD1_SEG); diff --git a/src/help.c b/src/help.c index dec1f20..f1ac0e9 100644 --- a/src/help.c +++ b/src/help.c @@ -145,7 +145,7 @@ help_loop: return; } - if (STRCHR(rest,'*')) + if (stringchr(rest,'*')) { line[0] = 0; ci = 0; @@ -229,6 +229,8 @@ void usage_command(char *to, const char *arg) char *pt; int i; + if (to == cx.CoreUser.name) /* dont send usage notices to config file */ + return; for(i=0;ulist[i].command;i++) { if (!stringcasecmp(arg,ulist[i].command)) diff --git a/src/hostinfo.c b/src/hostinfo.c index 5ffe051..5f49cec 100644 --- a/src/hostinfo.c +++ b/src/hostinfo.c @@ -53,7 +53,7 @@ struct /* statusvalues */ const int klen; char *valbuf; -} sv[] = +} statusvalues[] = { { "VmPeak:", 7, vmpeak }, { "VmSize:", 7, vmsize }, @@ -65,55 +65,9 @@ struct /* statusvalues */ { NULL, 0, NULL } }; -#ifdef DEBUG - -struct -{ - int value; - char *str; - -} in2str[] = -{ -{ IN_ACCESS, "IN_ACCESS" }, /* File was accessed (read) */ -{ IN_ATTRIB, "IN_ATTRIB" }, /* Metadata changed, e.g., permissions, timestamps, extended attributes, link count, UID, GID, etc. */ -{ IN_CLOSE_WRITE, "IN_CLOSE_WRITE" }, /* File opened for writing was closed */ -{ IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE" }, /* File not opened for writing was closed */ -{ IN_CREATE, "IN_CREATE" }, /* File/directory created in watched directory */ -{ IN_DELETE, "IN_DELETE" }, /* File/directory deleted from watched directory */ -{ IN_DELETE_SELF, "IN_DELETE_SELF" }, /* Watched file/directory was itself deleted */ -{ IN_MODIFY, "IN_MODIFY" }, /* File was modified */ -{ IN_MOVE_SELF, "IN_MOVE_SELF" }, /* Watched file/directory was itself moved */ -{ IN_MOVED_FROM, "IN_MOVED_FROM" }, /* Generated for the directory containing the old filename when a file is renamed */ -{ IN_MOVED_TO, "IN_MOVED_TO" }, /* Generated for the directory containing the new filename when a file is renamed */ -{ IN_OPEN, "IN_OPEN" }, /* File was opened */ -{ 0, NULL } -}; - -char *inomask2str(uint32_t mask, char *dst) -{ - const char *src; - int i,n = 0; - - for(i=0;in2str[i].str;i++) - { - if ((mask & in2str[i].value) == in2str[i].value) - { - if (n) - dst[n++] = '|'; - src = in2str[i].str; - for(;src[n];n++) - dst[n] = src[n]; - } - } - dst[n] = 0; - return(dst); -} - -#endif /* DEBUG */ - int monitor_fs(const char *file) { - FileMon *fmon,*fnew; + FileMon *fnew; int ino; if ((ino = inotify_init()) < 0) @@ -125,7 +79,7 @@ int monitor_fs(const char *file) set_mallocdoer(monitor_fs); fnew = Calloc(sizeof(FileMon) + strlen(file)); fnew->fd = ino; - fnew->nospam = now; + fnew->nospam = cx.now; stringcpy(fnew->filename,file); fnew->next = filemonlist; @@ -145,15 +99,15 @@ int parse_proc_status(char *line) #endif if (key == NULL) return(FALSE); - for(i=0;sv[i].key;i++) + for(i=0;statusvalues[i].key;i++) { - if (strncmp(key,sv[i].key,sv[i].klen) == 0) + if (strncmp(key,statusvalues[i].key,statusvalues[i].klen) == 0) { #ifdef DEBUG debug("(parse_proc_status) key %s -> %s\n",key,line); #endif /* DEBUG */ - dest = sv[i].valbuf; - limit = sv[i].valbuf + 31; + dest = statusvalues[i].valbuf; + limit = statusvalues[i].valbuf + 31; while(*line == ' ') line++; while(*line && dest <= limit) @@ -250,52 +204,60 @@ int parse_proc_cpuinfo(char *line) return(FALSE); /* return false to continue reading lines */ } -void select_monitor() +void select_monitor(void) { FileMon *fmon; for(fmon=filemonlist;fmon;fmon=fmon->next) + { if (fmon->fd >= 0) { FD_SET(fmon->fd,&read_fds); chkhigh(fmon->fd); } + } } -void process_monitor() +#ifdef DEBUG +extern const DEFstruct inomasks[]; +#endif /* DEBUG */ + +void process_monitor(void) { FileMon *fmon; struct inotify_event *ivent; +#ifdef DEBUG char tmp[256]; - int n,m; + int n; +#else + int n __notused__; +#endif /* DEBUG */ + int m __notused__; for(fmon=filemonlist;fmon;fmon=fmon->next) { - if (fmon->fd >= 0 && FD_ISSET(fmon->fd,&read_fds)) - { - ivent = (struct inotify_event *)&globaldata; + if (fmon->fd < 0 || 0 == FD_ISSET(fmon->fd,&read_fds)) + continue; - n = read(fmon->fd,globaldata,sizeof(struct inotify_event)); - if (ivent->len > 0) - m = read(fmon->fd,ivent->name,ivent->len); - else - *ivent->name = 0; + ivent = (struct inotify_event *)&globaldata; + + n = read(fmon->fd,globaldata,sizeof(struct inotify_event)); + if (ivent->len > 0) + m = read(fmon->fd,ivent->name,ivent->len); + else + *ivent->name = 0; #ifdef DEBUG - debug("(process_monitor) ino %i, n %i, sz %i\n",fmon->fd,n,sizeof(in2str)); - debug("(process_monitor) wd %i, mask %lu, cookie %lu, len %lu, name %s\n", - ivent->wd,ivent->mask,ivent->cookie,ivent->len,ivent->name); - debug("(process_monitor) %s\n",inomask2str(ivent->mask,tmp)); - debug("(process_monitor) ino %i bytes read, int wd = %i, uint32_t mask = %s (%lu), " - "uint32_t cookie = %lu, uint32_t len = %lu, char name = %s\n", - n,ivent->wd,inomask2str(ivent->mask,tmp),ivent->mask,ivent->cookie,ivent->len,ivent->name); -#endif - if ((ivent->mask & IN_CLOSE_WRITE) == IN_CLOSE_WRITE) - return; - if (fmon->nospam > now-30) - return; - fmon->nospam = now; - send_global(SPYSTR_SYSMON,"Alert: file ``%s'' was touched",fmon->filename); - } + strflags(tmp,inomasks,ivent->mask); + + debug("(process_monitor) ino {%i} %i bytes, wd = %i, mask = %s (%lu), cookie = %lu, len = %lu, name = %s\n", + fmon->fd,n,ivent->wd,tmp,ivent->mask,ivent->cookie,ivent->len,ivent->name); +#endif /* DEBUG */ + if ((ivent->mask & IN_CLOSE_WRITE) == IN_CLOSE_WRITE) + return; + if (fmon->nospam > (cx.now - 30)) + return; + fmon->nospam = cx.now; + send_global(SPYSTR_SYSMON,"Alert: file ``%s'' was touched",fmon->filename); } } @@ -346,8 +308,8 @@ void do_meminfo(COMMAND_ARGS) p = getpid(); snprintf(fn,sizeof(fn),"/proc/%i/status",p); - for(i=0;sv[i].key;i++) - *(sv[i].valbuf) = 0; + for(i=0;statusvalues[i].key;i++) + *(statusvalues[i].valbuf) = 0; if ((fd = open(fn,O_RDONLY)) < 0) return; readline(fd,&parse_proc_status); /* readline closes fd */ @@ -364,18 +326,9 @@ See also: hostinfo, meminfo void do_cpuinfo(COMMAND_ARGS) { char bogostr[256],cpustr[64]; - char *a1,*a2,*a3,*dst; - int fd,n; + int fd; double loads[3]; -#ifdef DEVELOPING - a1 = chop(&rest); - if (a1) - sprintf(bogostr,"/home/git/cpuinfo/%s",a1); - else - stringcpy(bogostr,"/proc/cpuinfo"); - if ((fd = open(bogostr,O_RDONLY)) < 0) -#endif if ((fd = open("/proc/cpuinfo",O_RDONLY)) < 0) #ifdef DEBUG { diff --git a/src/io.c b/src/io.c index c4b686a..32db75e 100644 --- a/src/io.c +++ b/src/io.c @@ -115,10 +115,6 @@ int SockConnect(char *host, int port, int use_vhost) { struct sockaddr_in sai; int s; -#ifdef IDWRAP - char *id,identfile[64]; - int t = FALSE; -#endif /* IDWRAP */ #ifdef DEBUG debug("(SockConnect) %s %i%s\n",nullstr(host),port,(use_vhost) ? " [VHOST]" : ""); @@ -130,16 +126,7 @@ int SockConnect(char *host, int port, int use_vhost) memset((char*)&sai,0,sizeof(sai)); sai.sin_family = AF_INET; - /* - * special case, BOUNCE feature may call SockConnect() - * to create the IDWRAP symlink, using special use_vhost value == 2 - */ -#if defined(BOUNCE) && defined(IDWRAP) - if ((use_vhost == TRUE) -#else /* not ... */ - if (use_vhost -#endif /* ... */ - && ((current->vhost_type & VH_IPALIAS_FAIL) == 0) + if (use_vhost && ((current->vhost_type & VH_IPALIAS_FAIL) == 0) && current->setting[STR_VIRTUAL].str_var) { current->vhost_type |= VH_IPALIAS_BOTH; @@ -151,25 +138,12 @@ int SockConnect(char *host, int port, int use_vhost) #ifdef WINGATE use_vhost++; #endif /* WINGATE */ -#ifdef IDWRAP - t = TRUE; -#endif /* IDWRAP */ #ifdef DEBUG debug("(SockConnect) IP Alias virtual host bound OK\n"); #endif /* DEBUG */ } } } -#ifdef IDWRAP - /* - * do a blank bind to get a port number - */ - if (!t) - { - sai.sin_addr.s_addr = INADDR_ANY; - bind(s,(struct sockaddr *)&sai,sizeof(sai)); - } -#endif /* IDWRAP */ memset((char*)&sai,0,sizeof(sai)); sai.sin_family = AF_INET; @@ -204,29 +178,6 @@ int SockConnect(char *host, int port, int use_vhost) /* * Normal connect, no bounces... */ -#ifdef IDWRAP - if (use_vhost) - { - t = sizeof(sai); - if (getsockname(s,(struct sockaddr*)&sai,&t) == 0) - { - if (current->identfile) - Free((char**)¤t->identfile); - sprintf(identfile,IDWRAP_PATH "%i.%i",ntohs(sai.sin_port),port); - id = current->setting[STR_IDENT].str_var; - if (symlink((id) ? id : BOTLOGIN,identfile) == 0) - { - set_mallocdoer(SockConnect); - current->identfile = Strdup(identfile); -#ifdef DEBUG - debug("(SockConnect) symlink: %s -> %s\n",identfile,(id) ? id : BOTLOGIN); -#endif /* DEBUG */ - } - } - memset((char*)&sai,0,sizeof(sai)); - sai.sin_family = AF_INET; - } -#endif /* IDWRAP */ sai.sin_port = htons(port); if ((sai.sin_addr.s_addr = get_ip(host)) == -1) { @@ -253,7 +204,8 @@ int SockConnect(char *host, int port, int use_vhost) int SockAccept(int sock) { struct sockaddr_in sai; - int s,sz; + unsigned int sz; + int s; sz = sizeof(sai); s = accept(sock,(struct sockaddr*)&sai,&sz); @@ -303,18 +255,19 @@ int to_file(const int sock, const char *format, ...) * Format a message and send it to the current bots server * to_server needs a newline (\n) it wont manufacture it itself. */ -void to_server(char *format, ...) +void to_server(const char *format, ...) { va_list msg; #ifdef DEBUG char *line,*rest; #endif /* DEBUG */ + int sz; if (current->sock == -1) return; va_start(msg,format); - vsprintf(globaldata,format,msg); + sz = vsprintf(globaldata,format,msg); va_end(msg); /* @@ -323,7 +276,7 @@ void to_server(char *format, ...) */ current->sendq_time += 2; - if (write(current->sock,globaldata,strlen(globaldata)) < 0) + if (write(current->sock,globaldata,sz) < 0) { #ifdef DEBUG debug("[StS] {%i} errno = %i\n",current->sock,errno); @@ -357,7 +310,7 @@ void to_user_q(const char *target, const char *format, ...) if (STARTUP_ECHOTOCONSOLE) { - int n; + int n __notused__; n = write(1,message,strlen(message)); return; } @@ -497,6 +450,91 @@ void to_user(const char *target, const char *format, ...) #endif /* DEBUG */ } +Strp *output_table = NULL; + +void table_buffer(const char *format, ...) +{ + va_list msg; + + va_start(msg,format); + vsprintf(globaldata,format,msg); + va_end(msg); + + set_mallocdoer(table_buffer); + append_strp(&output_table,globaldata); +} + +void table_send(const char *from, const int space) +{ + char message[MAXLEN]; + Strp *sp,*next; + char *src,*o,*end; + int i,u,g,x,columns[16]; + + memset(columns,0,sizeof(columns)); + + for(sp=output_table;sp;sp=sp->next) + { + u = i = 0; + src = o = sp->p; + while(*src) + { + /* Dont count control codes */ + if (*src == '\037' || *src == '\002') + u++; + if (*src == '\t' || *src == '\r') + { + x = (src - o) - u; + if (x > columns[i]) + columns[i] = x; + i++; + o = src+1; + u = 0; + } + src++; + } + } + + for(sp=output_table;sp;sp=next) + { + next = sp->next; + + o = message; + src = sp->p; + g = x = i = 0; + while(*src) + { + if (g) + { + end = src; + while(*end && *end != '\t' && *end != '\r') + end++; + g -= (end - src); + while(g-- > 0) + *(o++) = ' '; + } + if (*src == '\037' || *src == '\002') + x++; + if (*src == '\t' || *src == '\r') + { + if (*src == '\r') + g = columns[i+1]; + src++; + x += (columns[i++] + space); + while(o < (message + x)) + *(o++) = ' '; + } + else + *(o++) = *(src++); + } + *o = 0; + to_user(from,FMT_PLAIN,message); + + Free((char**)&sp); + } + output_table = NULL; +} + #endif /* ifndef GENCMD_C */ /* @@ -507,7 +545,7 @@ void to_user(const char *target, const char *format, ...) * 2: If data is insufficient, try to read in more * 3: Try again to make a whole line */ -char *sockread(int s, char *rest, char *line) +char *sockread(int socket, char *rest, char *output) { char *src,*dst,*rdst; int n; @@ -515,7 +553,7 @@ char *sockread(int s, char *rest, char *line) errno = EAGAIN; src = rest; - dst = line; + dst = output; while(*src) { @@ -525,20 +563,26 @@ char *sockread(int s, char *rest, char *line) while(*src == '\n' || *src == '\r') src++; *dst = 0; +#if !defined(GENCMD_C) + cx.rest_end = dst; +#endif /* !defined(GENCMD_C) */ + + /* move remainder of rest to the beginning of the buffer */ + /* src can be end of rest or globaldata */ dst = rest; while(*src) *(dst++) = *(src++); *dst = 0; + #if defined(DEBUG) && !defined(GENCMD_C) - debug("(in) {%i} %s\n",s,line); + debug("(in) {%i} %s\n",socket,output); #endif /* DEBUG */ - return((*line) ? line : NULL); + return((*output) ? output : NULL); } *(dst++) = *(src++); } - rdst = src; - n = read(s,globaldata,MSGLEN-2); + n = read(socket,globaldata,MSGLEN-2); switch(n) { case 0: @@ -547,14 +591,15 @@ char *sockread(int s, char *rest, char *line) return(NULL); } + rdst = src; globaldata[n] = 0; src = globaldata; while(*src) { if (*src == '\r' || *src == '\n') - goto gotline; - if ((dst - line) >= (MSGLEN-2)) + goto gotline; /* gotline will move the rest of globaldata to rest */ + if ((dst - output) >= (MSGLEN-2)) { /* * line is longer than buffer, let the wheel spin @@ -634,7 +679,7 @@ int killsock(int sock) { set_mallocdoer(killsock); ks = (KillSock*)Calloc(sizeof(KillSock)); - ks->time = now; + ks->time = cx.now; ks->sock = sock; ks->next = killsocks; killsocks = ks; @@ -686,7 +731,7 @@ int killsock(int sock) if ((n == 0) || ((n == -1) && (errno != EAGAIN))) remove_ks(ks); } - if ((now - ks->time) > KILLSOCKTIMEOUT) + if ((cx.now - ks->time) > KILLSOCK_TIMEOUT) remove_ks(ks); ks = ksnext; } diff --git a/src/irc.c b/src/irc.c index 14681af..fe413c4 100644 --- a/src/irc.c +++ b/src/irc.c @@ -40,7 +40,7 @@ void make_ireq(int t, const char *from, const char *nick) ir = (IReq*)Calloc(sizeof(IReq) + StrlenX(from,nick,NULL)); /* can not use Strlen2() if 2nd arg might be NULL, StrlenX() handles NULLs. */ ir->t = t; - ir->when = now; + ir->when = cx.now; pt = stringcat(ir->from,from) + 1; if (nick) diff --git a/src/lib/sha1.c b/src/lib/sha1.c index de7ee3e..edea45d 100644 --- a/src/lib/sha1.c +++ b/src/lib/sha1.c @@ -294,4 +294,4 @@ int main(int argc, char **argv) return(0); } -#endif TEST +#endif /* TEST */ diff --git a/src/lib/sha512.c b/src/lib/sha512.c new file mode 100644 index 0000000..2fd9c16 --- /dev/null +++ b/src/lib/sha512.c @@ -0,0 +1,370 @@ +/* + * public domain sha512 crypt implementation + * + * original sha crypt design: http://people.redhat.com/drepper/SHA-crypt.txt + * in this implementation at least 32bit int is assumed, + * key length is limited, the $6$ prefix is mandatory, '\n' and ':' is rejected + * in the salt and rounds= setting must contain a valid iteration count, + * on error "*" is returned. + */ +#include +#include +#include +#include +#include + +/* public domain sha512 implementation based on fips180-3 */ +/* >=2^64 bits messages are not supported (about 2000 peta bytes) */ + +struct sha512 +{ + uint64_t len; /* processed message length */ + uint64_t h[8]; /* hash state */ + uint8_t buf[128]; /* message block buffer */ +}; + +static uint64_t ror(uint64_t n, int k) { return (n >> k) | (n << (64-k)); } + +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) +#define S0(x) (ror(x,28) ^ ror(x,34) ^ ror(x,39)) +#define S1(x) (ror(x,14) ^ ror(x,18) ^ ror(x,41)) +#define R0(x) (ror(x,1) ^ ror(x,8) ^ (x>>7)) +#define R1(x) (ror(x,19) ^ ror(x,61) ^ (x>>6)) + +static const uint64_t K[80] = +{ +0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, +0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, +0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, +0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, +0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, +0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, +0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, +0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, +0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, +0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, +0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, +0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, +0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, +0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, +0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, +0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, +0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, +0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, +0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, +0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +static void processblock(struct sha512 *s, const uint8_t *buf) +{ + uint64_t W[80], t1, t2, a, b, c, d, e, f, g, h; + int i; + + for (i = 0; i < 16; i++) + { + W[i] = (uint64_t)buf[8*i]<<56; + W[i] |= (uint64_t)buf[8*i+1]<<48; + W[i] |= (uint64_t)buf[8*i+2]<<40; + W[i] |= (uint64_t)buf[8*i+3]<<32; + W[i] |= (uint64_t)buf[8*i+4]<<24; + W[i] |= (uint64_t)buf[8*i+5]<<16; + W[i] |= (uint64_t)buf[8*i+6]<<8; + W[i] |= buf[8*i+7]; + } + for (; i < 80; i++) + W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; + a = s->h[0]; + b = s->h[1]; + c = s->h[2]; + d = s->h[3]; + e = s->h[4]; + f = s->h[5]; + g = s->h[6]; + h = s->h[7]; + for (i = 0; i < 80; i++) + { + t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; + t2 = S0(a) + Maj(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + s->h[0] += a; + s->h[1] += b; + s->h[2] += c; + s->h[3] += d; + s->h[4] += e; + s->h[5] += f; + s->h[6] += g; + s->h[7] += h; +} + +static void pad(struct sha512 *s) +{ + unsigned r = s->len % 128; + + s->buf[r++] = 0x80; + if (r > 112) + { + memset(s->buf + r, 0, 128 - r); + r = 0; + processblock(s, s->buf); + } + memset(s->buf + r, 0, 120 - r); + s->len *= 8; + s->buf[120] = s->len >> 56; + s->buf[121] = s->len >> 48; + s->buf[122] = s->len >> 40; + s->buf[123] = s->len >> 32; + s->buf[124] = s->len >> 24; + s->buf[125] = s->len >> 16; + s->buf[126] = s->len >> 8; + s->buf[127] = s->len; + processblock(s, s->buf); +} + +static void sha512_init(struct sha512 *s) +{ + s->len = 0; + s->h[0] = 0x6a09e667f3bcc908ULL; + s->h[1] = 0xbb67ae8584caa73bULL; + s->h[2] = 0x3c6ef372fe94f82bULL; + s->h[3] = 0xa54ff53a5f1d36f1ULL; + s->h[4] = 0x510e527fade682d1ULL; + s->h[5] = 0x9b05688c2b3e6c1fULL; + s->h[6] = 0x1f83d9abfb41bd6bULL; + s->h[7] = 0x5be0cd19137e2179ULL; +} + +static void sha512_sum(struct sha512 *s, uint8_t *md) +{ + int i; + + pad(s); + for (i = 0; i < 8; i++) + { + md[8*i] = s->h[i] >> 56; + md[8*i+1] = s->h[i] >> 48; + md[8*i+2] = s->h[i] >> 40; + md[8*i+3] = s->h[i] >> 32; + md[8*i+4] = s->h[i] >> 24; + md[8*i+5] = s->h[i] >> 16; + md[8*i+6] = s->h[i] >> 8; + md[8*i+7] = s->h[i]; + } +} + +static void sha512_update(struct sha512 *s, const void *m, unsigned long len) +{ + const uint8_t *p = m; + unsigned r = s->len % 128; + + s->len += len; + if (r) + { + if (len < 128 - r) + { + memcpy(s->buf + r, p, len); + return; + } + memcpy(s->buf + r, p, 128 - r); + len -= 128 - r; + p += 128 - r; + processblock(s, s->buf); + } + for (; len >= 128; len -= 128, p += 128) + processblock(s, p); + memcpy(s->buf, p, len); +} + +static const unsigned char b64[] = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static char *to64(char *s, unsigned int u, int n) +{ + while (--n >= 0) + { + *s++ = b64[u % 64]; + u /= 64; + } + return s; +} + +/* key limit is not part of the original design, added for DoS protection. + * rounds limit has been lowered (versus the reference/spec), also for DoS + * protection. runtime is O(klen^2 + klen*rounds) */ +#define KEY_MAX 256 +#define SALT_MAX 16 +#define ROUNDS_DEFAULT 5000 +#define ROUNDS_MIN 1000 +#define ROUNDS_MAX 9999999 + +/* hash n bytes of the repeated md message digest */ +static void hashmd(struct sha512 *s, unsigned int n, const void *md) +{ + unsigned int i; + + for (i = n; i > 64; i -= 64) + sha512_update(s, md, 64); + sha512_update(s, md, i); +} + +static char *sha512crypt(const char *key, const char *setting, char *output) +{ + struct sha512 ctx; + unsigned char md[64], kmd[64], smd[64]; + unsigned int i, r, klen, slen; + const char *salt; + char *p; + + /* reject large keys */ + for (i = 0; i <= KEY_MAX && key[i]; i++); + if (i > KEY_MAX) + return 0; + klen = i; + + /* setting: $6$rounds=n$salt$ (rounds=n$ and closing $ are optional) */ + if (strncmp(setting, "$6$", 3) != 0) + return 0; + salt = setting + 3; + + r = ROUNDS_DEFAULT; + + for (i = 0; i < SALT_MAX && salt[i] && salt[i] != '$'; i++) + /* reject characters that interfere with /etc/shadow parsing */ + if (salt[i] == '\n' || salt[i] == ':') + return 0; + slen = i; + + /* B = sha(key salt key) */ + sha512_init(&ctx); + sha512_update(&ctx, key, klen); + sha512_update(&ctx, salt, slen); + sha512_update(&ctx, key, klen); + sha512_sum(&ctx, md); + + /* A = sha(key salt repeat-B alternate-B-key) */ + sha512_init(&ctx); + sha512_update(&ctx, key, klen); + sha512_update(&ctx, salt, slen); + hashmd(&ctx, klen, md); + for (i = klen; i > 0; i >>= 1) + if (i & 1) + sha512_update(&ctx, md, sizeof md); + else + sha512_update(&ctx, key, klen); + sha512_sum(&ctx, md); + + /* DP = sha(repeat-key), this step takes O(klen^2) time */ + sha512_init(&ctx); + for (i = 0; i < klen; i++) + sha512_update(&ctx, key, klen); + sha512_sum(&ctx, kmd); + + /* DS = sha(repeat-salt) */ + sha512_init(&ctx); + for (i = 0; i < 16 + md[0]; i++) + sha512_update(&ctx, salt, slen); + sha512_sum(&ctx, smd); + + /* iterate A = f(A,DP,DS), this step takes O(rounds*klen) time */ + for (i = 0; i < r; i++) + { + sha512_init(&ctx); + if (i % 2) + hashmd(&ctx, klen, kmd); + else + sha512_update(&ctx, md, sizeof md); + + if (i % 3) + sha512_update(&ctx, smd, slen); + if (i % 7) + hashmd(&ctx, klen, kmd); + + if (i % 2) + sha512_update(&ctx, md, sizeof md); + else + hashmd(&ctx, klen, kmd); + + sha512_sum(&ctx, md); + } + + /* output is $6$salt$hash */ + p = output; + p += sprintf(p, "$6$%.*s$", slen, salt); +#if 0 + static const unsigned char perm[][3] = { + 0,21,42,22,43,1,44,2,23,3,24,45,25,46,4, + 47,5,26,6,27,48,28,49,7,50,8,29,9,30,51, + 31,52,10,53,11,32,12,33,54,34,55,13,56,14,35, + 15,36,57,37,58,16,59,17,38,18,39,60,40,61,19, + 62,20,41 }; + for (i=0; i<21; i++) p = to64(p, + (md[perm[i][0]]<<16)|(md[perm[i][1]]<<8)|md[perm[i][2]], 4); +#else + p = to64(p, (md[0]<<16)|(md[21]<<8)|md[42], 4); + p = to64(p, (md[22]<<16)|(md[43]<<8)|md[1], 4); + p = to64(p, (md[44]<<16)|(md[2]<<8)|md[23], 4); + p = to64(p, (md[3]<<16)|(md[24]<<8)|md[45], 4); + p = to64(p, (md[25]<<16)|(md[46]<<8)|md[4], 4); + p = to64(p, (md[47]<<16)|(md[5]<<8)|md[26], 4); + p = to64(p, (md[6]<<16)|(md[27]<<8)|md[48], 4); + p = to64(p, (md[28]<<16)|(md[49]<<8)|md[7], 4); + p = to64(p, (md[50]<<16)|(md[8]<<8)|md[29], 4); + p = to64(p, (md[9]<<16)|(md[30]<<8)|md[51], 4); + p = to64(p, (md[31]<<16)|(md[52]<<8)|md[10], 4); + p = to64(p, (md[53]<<16)|(md[11]<<8)|md[32], 4); + p = to64(p, (md[12]<<16)|(md[33]<<8)|md[54], 4); + p = to64(p, (md[34]<<16)|(md[55]<<8)|md[13], 4); + p = to64(p, (md[56]<<16)|(md[14]<<8)|md[35], 4); + p = to64(p, (md[15]<<16)|(md[36]<<8)|md[57], 4); + p = to64(p, (md[37]<<16)|(md[58]<<8)|md[16], 4); + p = to64(p, (md[59]<<16)|(md[17]<<8)|md[38], 4); + p = to64(p, (md[18]<<16)|(md[39]<<8)|md[60], 4); + p = to64(p, (md[40]<<16)|(md[61]<<8)|md[19], 4); + p = to64(p, (md[62]<<16)|(md[20]<<8)|md[41], 4); +#endif + p = to64(p, md[63], 2); + *p = 0; + return output; +} + +char sha512_buffer[128]; + +char *crypt_sha512(const char *key, const char *salt) +{ + return(sha512crypt(key,salt,sha512_buffer)); +} + +#ifdef TEST + +const char thash1[] = "$6$5c05$WlQbKv/GYeXzSPNsn9bzpfqlDjOCbt8JlhSa2uALujoq6tWn3utZ3jE428lxBAfcJYHfecF59s6Dxg0fLIX7a/"; + +int main(int argc, char **argv, char **envp) +{ + const char mytest[] = "mytestpassword"; + const char mysalt[] = "$6$5c05$"; + char *s; + int r; + + s = crypt_sha512(mytest,mysalt); + r = strcmp(thash1,s); + + if (r == 0) + { + printf("SHA512\n"); + } + else + { + printf("FAIL\n"); + printf("%i\n%s\%s\n",r,thash1,s); + } +} + +#endif /* TEST */ diff --git a/src/main.c b/src/main.c index e242532..d321b68 100755 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2018 proton + Parts Copyright (c) 1997-2025 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 @@ -51,7 +51,6 @@ #include "hostinfo.c" #include "io.c" #include "irc.c" -#include "lib/string.c" #include "net.c" #include "note.c" #include "ons.c" @@ -67,6 +66,7 @@ #include "seen.c" #include "shit.c" #include "spy.c" +#include "string.c" #include "tcl.c" #include "toybox.c" #include "uptime.c" @@ -144,8 +144,8 @@ void mech_exec(void) exit(1); } -LS int r_ct; -LS char r_str[MSGLEN]; +int r_ct; +char r_str[MSGLEN]; int randstring_count(char *line) { @@ -199,7 +199,7 @@ char *randstring(const char *file) * SIGUSR2 Call run_debug() (dump `everything' to a debug file) */ -LS struct +struct { uint32_t sighup:1, sigint:1, @@ -209,7 +209,7 @@ LS struct int sig_hup_callback(char *line) { - on_msg((char*)CoreUser.name,current->nick,line); + on_msg((char*)cx.CoreUser.name,getbotnick(current),line); return(FALSE); } @@ -221,7 +221,7 @@ void do_sighup(void) CurrentShit = NULL; CurrentChan = NULL; - CurrentUser = (User*)&CoreUser; + CurrentUser = (User*)&cx.CoreUser; CurrentDCC = (Client*)&CoreClient; *CurrentNick = 0; @@ -295,9 +295,6 @@ void do_sigusr1(void) { if (current->sock != -1) { -#ifdef IDWRAP - unlink_identfile(); -#endif /* IDWRAP */ close(current->sock); } current->sock = -1; @@ -324,7 +321,7 @@ void sig_usr1(int crap) */ void sig_usr2(int crap) { - time(&now); + time(&cx.now); debug("(sigusr2)\n"); signal(SIGUSR2,sig_usr2); @@ -402,20 +399,20 @@ void sig_int(int signum) * SIGILL, Illegal instruction */ #ifdef DEBUG + void sig_ill(int crap) { debug("(sigill)\n"); } -#endif /* DEBUG */ /* * SIGABRT, abort(3) */ -#ifdef DEBUG void sig_abrt(int crap) { debug("(sigabrt)\n"); } + #endif /* DEBUG */ /* @@ -423,7 +420,7 @@ void sig_abrt(int crap) */ void sig_bus(int crap) { - time(&now); + time(&cx.now); respawn++; if (respawn > 10) @@ -441,27 +438,42 @@ void sig_bus(int crap) /* * SIGSEGV shows no mercy, cant schedule it. */ -#if defined(__linux__) && defined(__x86_64__) && defined(DEBUG) && !defined(__STRICT_ANSI__) +#if defined(__linux__) && defined(DEBUG) && !defined(__STRICT_ANSI__) #include -void sig_segv(int crap, siginfo_t *si, void *uap) +void sig_segv(int sig, siginfo_t *si, void *context) { - mcontext_t *mctx; - greg_t *rsp,*rip; /* general registers */ + ucontext_t *crashcontext = (ucontext_t*)context; + char *sp,*ip; /* general registers */ - time(&now); startup = STARTUP_SIGSEGV; - debug("(sigsegv) trying to access "mx_pfmt"\n",(mx_ptr)si->si_addr); - mctx = &((ucontext_t *)uap)->uc_mcontext; - rsp = &mctx->gregs[15]; /* RSP, 64-bit stack pointer */ - rip = &mctx->gregs[16]; /* RIP, 64-bit instruction pointer */ +#if defined(__x86_64__) + ip = (char*)crashcontext->uc_mcontext.gregs[16]; + sp = (char*)crashcontext->uc_mcontext.gregs[15]; +#elif defined(__i386__) + void *ip = (void*)crashcontext->uc_mcontext.gregs[REG_EIP]; + void *sp = (void*)crashcontext->uc_mcontext.gregs[REG_ESP]; +#elif defined(__aarch64__) + void *ip = (void*)uc->uc_mcontext.pc; + void *sp = (void*)uc->uc_mcontext.sp; +#elif defined(__arm__) + void *pc = (void*)uc->uc_mcontext.arm_pc; + void *sp = (void*)uc->uc_mcontext.arm_sp; +#elif defined(__mips__) + void *pc = (void*)uc->uc_mcontext.pc; + void *sp = (void*)uc->uc_mcontext.gregs[29]; +#else +#error "sig_segv(): Unsupported architecture" +#endif - debug("(sigsegv) Stack pointer: "mx_pfmt", Instruction pointer: "mx_pfmt"\n",(mx_ptr)*rsp,(mx_ptr)*rip); + debug("(sigsegv) trying to access "mx_pfmt"\n",(mx_ptr)si->si_addr); + debug("(sigsegv) Stack pointer: "mx_pfmt", Instruction pointer: "mx_pfmt"\n",(mx_ptr)sp,(mx_ptr)ip); debug("(sigsegv) sig_segv() = "mx_pfmt"\n",(mx_ptr)sig_segv); debug("(sigsegv) do_crash() = "mx_pfmt"\n",(mx_ptr)do_crash); if (debug_on_exit) { + time(&cx.now); run_debug(); debug_on_exit = FALSE; } @@ -475,11 +487,11 @@ void sig_segv(int crap, siginfo_t *si, void *uap) /* NOT REACHED */ } -#else /* defined(__linux__) && defined(__x86_64__) && defined(DEBUG) && !defined(__STRICT_ANSI__) */ +#else /* defined(__linux__) && defined(DEBUG) && !defined(__STRICT_ANSI__) */ void sig_segv(int signum) { - time(&now); + startup = STARTUP_SIGSEGV; #ifdef DEBUG if (debug_on_exit) @@ -498,7 +510,7 @@ void sig_segv(int signum) /* NOT REACHED */ } -#endif /* else defined(__linux__) && defined(__x86_64__) && defined(DEBUG) && !defined(__STRICT_ANSI__) */ +#endif /* else defined(__linux__) && defined(DEBUG) && !defined(__STRICT_ANSI__) */ /* * SIGTERM @@ -509,8 +521,6 @@ void sig_term(int signum) exit(0); #endif /* __profiling__ */ - time(&now); - #ifdef DEBUG debug("(sigterm)\n"); #endif /* DEBUG */ @@ -525,25 +535,23 @@ void sig_term(int signum) * */ -#ifdef __GNUC__ -LS void doit(void) __attribute__ ((__noreturn__, __sect(CORE_SEG))); -#endif -void doit(void) +void mainloop(void) { - struct timeval tv; + SequenceTime this; Chan *chan; Client *client; - SequenceTime this; Strp *qm; + struct timeval tv; time_t last_update; - last_update = now; + + last_update = cx.now; /* * init update times so that they dont all run right away */ - this.tenminute = now / 600; - this.hour = now / 3600; + this.tenminute = cx.now / 600; + this.hour = cx.now / 3600; /* * The Main Loop @@ -569,15 +577,15 @@ mainloop: /* * check for regular updates */ - if (last_update != now) + if (last_update != cx.now) { - last_update = now; + last_update = cx.now; update(&this); } FD_ZERO(&read_fds); FD_ZERO(&write_fds); - hisock = -1; + cx.hisock = -1; #ifdef BOTNET select_botnet(); @@ -602,7 +610,7 @@ mainloop: /* * unset here, reset if needed in bot loop */ - short_tv &= ~(TV_SERVCONNECT|TV_LINEBUF); + cx.short_tv &= ~(TV_SERVCONNECT|TV_LINEBUF); for(current=botlist;current;current=current->next) { if (current->sock == -1) @@ -615,7 +623,7 @@ mainloop: if ((sp = find_server(current->server))) { - if ((now - current->conntry) > ctimeout) + if ((cx.now - current->conntry) > ctimeout) { #ifdef DEBUG debug("(doit) RAWDNS timed out (%s)\n",sp->name); @@ -641,27 +649,27 @@ mainloop: { if (current->connect == CN_SPINNING) { - if ((now - current->conntry) >= 60) + if ((cx.now - current->conntry) >= 60) connect_to_server(); } else { doit_jumptonext: - short_tv |= TV_SERVCONNECT; - if ((now - current->conntry) >= 2) + cx.short_tv |= TV_SERVCONNECT; + if ((cx.now - current->conntry) >= 2) connect_to_server(); } } #else /* ! RAWDNS */ if (current->connect == CN_SPINNING) { - if ((now - current->conntry) >= 60) + if ((cx.now - current->conntry) >= 60) connect_to_server(); } else { - short_tv |= TV_SERVCONNECT; - if ((now - current->conntry) >= 2) + cx.short_tv |= TV_SERVCONNECT; + if ((cx.now - current->conntry) >= 2) connect_to_server(); } #endif /* RAWDNS */ @@ -672,7 +680,7 @@ doit_jumptonext: if (current->ip.s_addr == 0) { struct sockaddr_in sai; - int sz; + unsigned int sz; sz = sizeof(sai); if (getsockname(current->sock,(struct sockaddr *)&sai,&sz) == 0) @@ -680,15 +688,12 @@ doit_jumptonext: } if ((current->connect == CN_TRYING) || (current->connect == CN_CONNECTED)) { - short_tv |= TV_SERVCONNECT; - if ((now - current->conntry) > ctimeout) + cx.short_tv |= TV_SERVCONNECT; + if ((cx.now - current->conntry) > ctimeout) { #ifdef DEBUG debug("(doit) {%i} Connection timed out\n",current->sock); #endif /* DEBUG */ -#ifdef IDWRAP - unlink_identfile(); -#endif /* IDWRAP */ close(current->sock); current->sock = -1; goto restart_dcc; @@ -698,7 +703,7 @@ doit_jumptonext: } if (current->sendq) { - short_tv |= TV_LINEBUF; + cx.short_tv |= TV_LINEBUF; } else { @@ -706,7 +711,7 @@ doit_jumptonext: { if (chan->kicklist || chan->modelist) { - short_tv |= TV_LINEBUF; + cx.short_tv |= TV_LINEBUF; break; } } @@ -752,19 +757,19 @@ restart_dcc: * Longer delay saves CPU but some features require shorter delays */ #ifdef NOTIFY - tv.tv_sec = (short_tv) ? 1 : 5; + tv.tv_sec = (cx.short_tv) ? 1 : 5; #else /* NOTIFY */ - tv.tv_sec = (short_tv) ? 1 : 30; + tv.tv_sec = (cx.short_tv) ? 1 : 30; #endif /* NOTIFY */ tv.tv_usec = 0; - if ((select(hisock+1,&read_fds,&write_fds,0,&tv) == -1) && (errno == EINTR)) + if ((select(cx.hisock+1,&read_fds,&write_fds,0,&tv) == -1) && (errno == EINTR)) goto mainloop; /* * Update current time */ - time(&now); + time(&cx.now); for(current=botlist;current;current=current->next) { @@ -773,8 +778,8 @@ restart_dcc: * it is important that the check is done before anything * else that could potentially send output to the server! */ - if (current->sendq_time < now) - current->sendq_time = now; + if (current->sendq_time < cx.now) + current->sendq_time = cx.now; } for(current=botlist;current;current=current->next) @@ -785,6 +790,18 @@ restart_dcc: if (current->sock != -1) process_server_input(); +#ifdef DEBUG + if (current->inject) + { + char injection[MSGLEN]; + + stringcpy(injection,current->inject); + Free((char**)¤t->inject); + debug("(*inject) %s\n"); + parse_server_input(injection); + } +#endif /* DEBUG */ + if (current->connect == CN_ONLINE) { /* @@ -792,10 +809,10 @@ restart_dcc: */ if (current->setting[TOG_NOIDLE].int_var) { - if ((now - current->lastantiidle) > PINGSENDINTERVAL) + if ((cx.now - current->lastantiidle) > PINGSENDINTERVAL) { to_server("PRIVMSG * :0\n"); - current->lastantiidle = now; + current->lastantiidle = cx.now; } } /* @@ -825,7 +842,7 @@ restart_dcc: /* * the un-important sendq only sends when sendq_time <= now */ - if ((current->sendq) && (current->sendq_time <= now)) + if ((current->sendq) && (current->sendq_time <= cx.now)) { qm = current->sendq; to_server(FMT_PLAINLINE,qm->p); @@ -857,7 +874,8 @@ restart_die: #endif /* BOTNET */ #ifdef BOUNCE - process_bounce(); + if (bounce_sock != -1 || bnclist) + process_bounce(); #endif /* BOUNCE */ #ifdef CHANBAN @@ -865,7 +883,11 @@ restart_die: #endif /* CHANBAN */ #ifdef RAWDNS - process_rawdns(); + /* + * Only a single socket to check. + */ + if (dnssock != -1 && FD_ISSET(dnssock,&read_fds)) + process_rawdns(); #endif /* RAWDNS */ #ifdef UPTIME @@ -881,7 +903,8 @@ restart_die: #endif #ifdef TRIVIA - trivia_tick(); + if (triv_next_time && (cx.now >= triv_next_time)) + trivia_tick(); #endif /* TRIVIA */ /* @@ -894,15 +917,12 @@ restart_die: } /* - * main(), we love it and cant live without it + * parse commandline */ -LS char *bad_exe = "init: Error: Improper executable name\n"; +const char *bad_exe = "init: Error: Improper executable name\n"; -#ifdef __GNUC__ -int main(int argc, char **argv, char **envp) __attribute__ ((__sect(INIT_SEG))); -#endif -int main(int argc, char **argv, char **envp) +void parse_commandline(int argc, char **argv, char **envp) { struct stat st; char *opt; @@ -911,8 +931,9 @@ int main(int argc, char **argv, char **envp) #ifdef NEWBIE int n = 0; #endif + memset(&cx,0,sizeof(cx)); - uptime = time(&now); + uptime = time(&cx.now); startup = STARTUP_NORMALSTART; if ((getuid() == 0) || (geteuid() == 0)) @@ -924,7 +945,12 @@ int main(int argc, char **argv, char **envp) stat("..",&st); parent_inode = st.st_ino; /* used for is_safepath() */ - srand(now+getpid()); + if (stat("/proc",&st) >= 0) + { + cx.system_uptime = st.st_ctime; + } + + srand(cx.now + getpid()); /* * Code to detect and recover after a RESET @@ -961,6 +987,7 @@ int main(int argc, char **argv, char **envp) } #ifdef DEBUG + /* memory tracking */ mrrec = calloc(sizeof(aMEA),1); #endif /* DEBUG */ @@ -969,7 +996,7 @@ int main(int argc, char **argv, char **envp) to_file(1,bad_exe); _exit(1); } - if ((opt = STRCHR(*argv,' ')) != NULL) + if ((opt = stringchr(*argv,' ')) != NULL) { *(opt++) = 0; respawn = asc2int(opt); @@ -989,66 +1016,26 @@ int main(int argc, char **argv, char **envp) opt = *argv; switch(opt[1]) { - case 'v': - versiononly = TRUE; - break; - case 'h': - to_file(1,TEXT_USAGE,executable); - to_file(1, - TEXT_CSWITCH -#ifdef DEBUG - TEXT_DSWITCH -#endif /* DEBUG */ - TEXT_ESWITCH - TEXT_FSWITCH - TEXT_HSWITCH -#ifdef DEBUG - TEXT_OSWITCH - TEXT_PSWITCH1 - TEXT_PSWITCH2 -#endif /* DEBUG */ - TEXT_TSWITCH - TEXT_VSWITCH -#ifdef DEBUG - TEXT_XSWITCH -#endif /* DEBUG */ - ); - _exit(0); case 'c': makecore = TRUE; break; #ifdef DEBUG case 'd': dodebug = TRUE; - do_fork = FALSE; - break; - case 'o': - if (opt[2] != 0) + do_fork = TRUE; + if (opt[2] != 0) /* -d[file] */ { debugfile = &opt[2]; } else + if (argv[1] && argv[1][0] != '-') /* -d [file] */ { ++argv; - if (!*argv) - { - to_file(1,"init: No debugfile specified\n"); - _exit(0); - } debugfile = *argv; argc--; } - do_fork = TRUE; - break; - case 'p': - ++argv; - if (*argv) - to_file(1,"%s\n",makepass(*argv)); else - to_file(1,"error: Missing argument for -p \n"); - _exit(0); - case 'X': - debug_on_exit = TRUE; + do_fork = FALSE; break; #endif /* DEBUG */ case 'e': /* run a single command before exiting */ @@ -1062,9 +1049,6 @@ int main(int argc, char **argv, char **envp) else to_file(1,"error: Missing argument for -e \n"); _exit(0); - case 't': - startup = STARTUP_TESTRUN; - break; case 'f': if (opt[2] != 0) { @@ -1083,15 +1067,49 @@ int main(int argc, char **argv, char **envp) } to_file(1,INFO_USINGCONF,configfile); break; + case 'h': + to_file(1,TEXT_USAGE,executable); + to_file(1, + TEXT_CSWITCH +#ifdef DEBUG + TEXT_DSWITCH +#endif /* DEBUG */ + TEXT_ESWITCH + TEXT_FSWITCH + TEXT_HSWITCH + TEXT_PSWITCH1 + TEXT_PSWITCH2 + TEXT_TSWITCH + TEXT_VSWITCH +#ifdef DEBUG + TEXT_XSWITCH +#endif /* DEBUG */ + ); + _exit(0); + case 'p': + ++argv; + if (*argv) + to_file(1,"%s\n",makepass(*argv)); + else + to_file(1,"error: Missing argument for -p \n"); + _exit(0); + case 't': + startup = STARTUP_TESTRUN; + break; + case 'v': + versiononly = TRUE; + break; +#ifdef DEBUG + case 'x': + debug_on_exit = TRUE; + break; +#endif /* DEBUG */ default: to_file(1,ERR_UNKNOWNOPT,opt); _exit(1); } } - servergrouplist = (ServerGroup*)&defaultServerGroup; - currentservergroup = (ServerGroup*)&defaultServerGroup; - if (!mechresetenv) { to_file(1,TEXT_HDR_VERS,VERSION,SRCDATE); @@ -1106,7 +1124,7 @@ int main(int argc, char **argv, char **envp) to_file(1,"warning: current configuration file overrides session file\n"); } #endif /* SESSION */ - if (stat(configfile,&st)); + if (stat(configfile,&st)) { if ((st.st_mode & (S_IWGRP|S_IWOTH)) != 0) { @@ -1116,7 +1134,7 @@ int main(int argc, char **argv, char **envp) if ((st.st_mode & (S_IRGRP|S_IROTH)) != 0) to_file(1,"warning: configfile is readable by others\n"); } - if (stat(".",&st)); + if (stat(".",&st)) { if ((st.st_mode & (S_IWGRP|S_IWOTH)) != 0) { @@ -1154,11 +1172,10 @@ int main(int argc, char **argv, char **envp) ia_default.s_addr = LOCALHOST_ULONG; #endif /* RAWDNS */ - memset(&__internal_users,0,sizeof(User)*2); - CoreUser.x.x.access = 100; - LocalBot.x.x.access = 200; - LocalBot.x.x.aop = 1; - LocalBot.chan = CoreUser.chan = (Strp*)&CMA; + cx.CoreUser.x.x.access = 100; + cx.LocalBot.x.x.access = 200; + cx.LocalBot.x.x.aop = 1; + cx.LocalBot.chan = cx.CoreUser.chan = (Strp*)&CMA; readcfgfile(); @@ -1182,7 +1199,7 @@ int main(int argc, char **argv, char **envp) } #else { - if (stat(opt,&st)); + if (stat(opt,&st)) { if ((st.st_mode & (S_IWGRP|S_IWOTH)) != 0) { @@ -1196,7 +1213,10 @@ int main(int argc, char **argv, char **envp) } if (current->userlist == NULL) { - to_file(1,"init: No userlist loaded for %s\n",nullstr(current->nick)); + char *nick; + + nick = getbotnick(current); + to_file(1,"init: No userlist loaded for %s\n",nullstr(nick)); n++; } } @@ -1252,7 +1272,7 @@ int main(int argc, char **argv, char **envp) #endif /* CTCP */ #ifdef BOTNET - last_autolink = now + 30 + (rand() >> 27); /* + 0-31 seconds */ + last_autolink = cx.now + 30 + (rand() >> 27); /* + 0-31 seconds */ #endif /* BOTNET */ if (mechresetenv) @@ -1296,7 +1316,16 @@ int main(int argc, char **argv, char **envp) } startup = STARTUP_RUNNING; #ifdef DEBUG - debug("(main) entering doit()...\n"); + debug("(main) entering main loop...\n"); #endif - doit(); +} + +/* + * Make main short and sweet, reduce stack data + * Main(), we love it and cant live without it + */ +int main(int argc, char **argv, char **envp) +{ + parse_commandline(argc, argv, envp); + mainloop(); } diff --git a/src/net.c b/src/net.c index 95133c1..4de0973 100644 --- a/src/net.c +++ b/src/net.c @@ -46,10 +46,11 @@ const char banneropt[] = "BB%i %i PTA" #ifdef TELNET char *telnetprompt = TEXT_ENTERNICKNAME; #endif /* TELNET */ + /* * this is a partial copy of the BotNet struct */ -LS struct +struct { struct BotNet *next; @@ -73,7 +74,7 @@ typedef struct LinkCmd #define RELAY_YES 1 #define RELAY_NO 0 -LS const LinkCmd basicProto[] = +const LinkCmd basicProto[] = { { "BA", basicAuth, RELAY_NO }, { "BB", basicBanner, RELAY_NO }, @@ -95,7 +96,7 @@ LS const LinkCmd basicProto[] = { "\0\0", NULL, RELAY_NO }, }; -LS int deadlinks = FALSE; +int deadlinks = FALSE; /* * @@ -159,21 +160,24 @@ NetCfg *find_netcfg(int guid) BotInfo *make_botinfo(int guid, int hops, char *nuh, char *server, char *version) { - BotInfo *new; + BotInfo *newbinfo; set_mallocdoer(make_botinfo); - new = (BotInfo*)Calloc(sizeof(BotInfo) + StrlenX(nuh,server,version,NULL)); + newbinfo = (BotInfo*)Calloc(sizeof(BotInfo) + StrlenX(nuh,server,version,NULL)); - new->guid = guid; - new->hops = hops; + newbinfo->guid = guid; + newbinfo->hops = hops; - new->server = stringcat(new->nuh,nuh) + 1; - new->version = stringcat(new->server,server) + 1; - stringcpy(new->version,version); + newbinfo->server = stringcat(newbinfo->nuh,nuh) + 1; + newbinfo->version = stringcat(newbinfo->server,server) + 1; + stringcpy(newbinfo->version,version); - return(new); + return(newbinfo); } +/* + * broadcast data to all except the source + */ void botnet_relay(BotNet *source, char *format, ...) { BotNet *bn; @@ -188,9 +192,8 @@ void botnet_relay(BotNet *source, char *format, ...) if (!sz) { va_start(msg,format); - vsprintf(globaldata,format,msg); + sz = vsprintf(globaldata,format,msg); va_end(msg); - sz = strlen(globaldata); } if (write(bn->sock,globaldata,sz) < 0) @@ -201,23 +204,10 @@ void botnet_relay(BotNet *source, char *format, ...) } } -void botnet_refreshbotinfo(void) -{ - Server *sv; - - sv = find_server(current->server); - botnet_relay(NULL,"BL%i 0 %s!%s %s:%i %s %s\n", current->guid,current->nick, - (current->userhost) ? current->userhost : UNKNOWNATUNKNOWN, - (sv) ? ((*sv->realname) ? sv->realname : sv->name) : UNKNOWN, - (sv) ? sv->port : 0,BOTCLASS,VERSION); -#ifdef DEBUG - debug("(botnet_refreshbotinfo) sent refreshed information to botnet\n"); -#endif /* DEBUG */ -} - void botnet_binfo_relay(BotNet *source, BotInfo *binfo) { - botnet_relay(source,"BL%i %i %s %s %s\n",binfo->guid,(binfo->hops + 1), + botnet_relay(source, + "BL%i %i %s %s %s\n",binfo->guid,(binfo->hops + 1), (binfo->nuh) ? binfo->nuh : UNKNOWNATUNKNOWN, (binfo->server) ? binfo->server : UNKNOWN, (binfo->version) ? binfo->version : "-"); @@ -225,12 +215,27 @@ void botnet_binfo_relay(BotNet *source, BotInfo *binfo) void botnet_binfo_tofile(int sock, BotInfo *binfo) { - to_file(sock,"BL%i %i %s %s %s\n",binfo->guid,(binfo->hops + 1), + to_file(sock, + "BL%i %i %s %s %s\n",binfo->guid,(binfo->hops + 1), (binfo->nuh) ? binfo->nuh : UNKNOWNATUNKNOWN, (binfo->server) ? binfo->server : UNKNOWN, (binfo->version) ? binfo->version : "-"); } +void botnet_refreshbotinfo(void) +{ + Server *sv; + + sv = find_server(current->server); + botnet_relay(NULL,"BL%i 0 %s!%s %s:%i %s %s\n", current->guid,getbotnick(current), + getbotuserhost(current), + (sv) ? ((*sv->realname) ? sv->realname : sv->name) : UNKNOWN, + (sv) ? sv->port : 0,BOTCLASS,VERSION); +#ifdef DEBUG + debug("(botnet_refreshbotinfo) sent refreshed information to botnet\n"); +#endif /* DEBUG */ +} + void botnet_dumplinklist(BotNet *bn) { BotInfo *binfo; @@ -248,14 +253,14 @@ void botnet_dumplinklist(BotNet *bn) */ sv = find_server(bot->server); to_file(bn->sock,"BL%i %c %s!%s %s:%i %s %s\n",bot->guid, - (bot == bn->controller) ? '0' : '1',bot->nick, - (bot->userhost) ? bot->userhost : UNKNOWNATUNKNOWN, + (bot == bn->controller) ? '0' : '1',getbotnick(bot), + getbotuserhost(bot), (sv) ? ((*sv->realname) ? sv->realname : sv->name) : UNKNOWN, (sv) ? sv->port : 0,BOTCLASS,VERSION); } for(bn2=botnetlist;bn2;bn2=bn2->next) { - if ((bn2 == bn) || (bn2->status != BN_LINKED) || !(bn2->list_complete)) + if ((bn2 == bn) || (bn2->status != BN_LINKED) || (bn2->opt.links_complete == 0)) continue; for(binfo=bn2->botinfo;binfo;binfo=binfo->next) botnet_binfo_tofile(bn->sock,binfo); @@ -289,7 +294,7 @@ int connect_to_bot(NetCfg *cfg) bn->sock = s; bn->status = BN_CONNECT; - bn->when = now; + bn->when = cx.now; bn->guid = cfg->guid; bn->next = botnetlist; @@ -409,7 +414,7 @@ void basicAuth(BotNet *bn, char *rest) { case BNAUTH_PLAINTEXT: /* ->> plain text given: "DomoOmiGato" stored "kooplook0988" +>> plain text given: "DomoOmiGato" stored "........." (reset_linkable) guid 1337 reset to linkable (basicAuth) bad password [ guid = 1337 ] */ @@ -420,6 +425,12 @@ void basicAuth(BotNet *bn, char *rest) goto badpass; break; #ifdef SHACRYPT +/* +(in) {6} BB1881 634704033 PTA SHA +(out) {6} BB9344 1233037145 PTA SHA +>> sha pass exchange: "........ ......... 634704033 1233037145" +(out) {2} BASHA $6$5525$mZLr762...... +*/ case BNAUTH_SHA: { char *enc,temppass[24 + Strlen2(pass,linkpass)]; /* linkpass is never NULL */ @@ -476,7 +487,7 @@ void basicAuth(BotNet *bn, char *rest) debug("(basicAuth) bn->tick = 0\n"); #endif /* DEBUG */ bn->tick = 0; - bn->tick_last = now - 580; /* 10 minutes (10*60) - 20 seconds */ + bn->tick_last = cx.now - 580; /* 10 minutes (10*60) - 20 seconds */ } void basicAuthOK(BotNet *bn, char *rest) @@ -490,7 +501,7 @@ void basicAuthOK(BotNet *bn, char *rest) debug("(basicAuthOK) bn->tick = 0\n"); #endif /* DEBUG */ bn->tick = 0; - bn->tick_last = now - 580; /* 10 minutes (10*60) - 20 seconds */ + bn->tick_last = cx.now - 580; /* 10 minutes (10*60) - 20 seconds */ } void basicBanner(BotNet *bn, char *rest) @@ -608,7 +619,7 @@ void basicBanner(BotNet *bn, char *rest) /* * update timestamp */ - bn->when = now; + bn->when = cx.now; /* * if the remote bot initiated the connection we need a valid pass from them @@ -701,7 +712,7 @@ void basicBanner(BotNet *bn, char *rest) void basicLink(BotNet *bn, char *version) { - BotInfo *binfo,*delete,**pp; + BotInfo *binfo,**pp; NetCfg *cfg; char *nuh,*server; int guid,hops; @@ -748,7 +759,7 @@ void basicLink(BotNet *bn, char *version) continue; cfg->linked = TRUE; } - bn->list_complete = TRUE; + bn->opt.links_complete = TRUE; return; } @@ -774,23 +785,25 @@ void basicLink(BotNet *bn, char *version) binfo = make_botinfo(guid,hops,nuh,server,version); if (bn->botinfo == NULL) - send_global(SPYSTR_BOTNET,"connecting to %s [guid %i]",nickcpy(NULL,nuh),bn->guid); + send_global(SPYSTR_STATUS,"Connected to %s [guid %i]",nickcpy(NULL,nuh),bn->guid); + pp = &bn->botinfo; while(*pp) { - delete = *pp; - if (guid == delete->guid) + BotInfo *trash; + if (guid == (*pp)->guid) { - *pp = delete->next; - Free((char**)&delete); + trash = *pp; + *pp = trash->next; + Free((char**)&trash); break; } - pp = &delete->next; + pp = &(*pp)->next; } binfo->next = *pp; *pp = binfo; - if (bn->list_complete) + if (bn->opt.links_complete) { if ((cfg = find_netcfg(guid))) cfg->linked = TRUE; @@ -904,10 +917,10 @@ void partyAuth(BotNet *bn, char *rest) { User *user; Strp *ump; - char *name,*userhost,*checksum; + char *userhost,*checksum; int m; - name = chop(&rest); + chop(&rest); userhost = chop(&rest); if ((checksum = chop(&rest)) == NULL) checksum = ""; @@ -987,7 +1000,7 @@ int commandlocal(int dg, int sg, char *from, char *command) *p2 = current->setting[CHR_CMDCHAR].char_var; stringcpy((*p2 == *command) ? p2 : p2+1,command); - on_msg(p1,current->nick,p2); + on_msg(p1,getbotnick(current),p2); CurrentDCC = NULL; } if (dg == -1) @@ -1198,7 +1211,7 @@ void ushareUser(BotNet *bn, char *rest) bn->addsession = 0; bn->tick++; to_file(bn->sock,"UT%i\n",bn->tick); - bn->tick_last = now; + bn->tick_last = cx.now; break; case '*': case '#': @@ -1319,10 +1332,8 @@ void ushareTick(BotNet *bn, char *rest) void ushareDelete(BotNet *bn, char *rest) { User *user; - char *orig; int modcount; - orig = rest; modcount = asc2int(chop(&rest)); if (errno) return; @@ -1417,7 +1428,7 @@ void botnet_newsock(void) bn->sock = s; bn->status = BN_UNKNOWN; bn->lsid = rand(); - bn->when = now; + bn->when = cx.now; bn->next = botnetlist; botnetlist = bn; @@ -1425,7 +1436,7 @@ void botnet_newsock(void) /* * crude... but, should work */ - last_autolink = now + AUTOLINK_DELAY; + last_autolink = cx.now + AUTOLINK_DELAY; } /* @@ -1455,9 +1466,9 @@ void select_botnet(void) /* * autolink */ - if (autolink && (now > last_autolink)) + if (autolink && (cx.now > last_autolink)) { - last_autolink = now + AUTOLINK_DELAY; + last_autolink = cx.now + AUTOLINK_DELAY; if (autolink_cfg) autolink_cfg = autolink_cfg->next; @@ -1474,14 +1485,14 @@ void select_botnet(void) } } - short_tv &= ~TV_BOTNET; + cx.short_tv &= ~TV_BOTNET; for(bn=botnetlist;bn;bn=bn->next) { chkhigh(bn->sock); if (bn->status == BN_CONNECT) { FD_SET(bn->sock,&write_fds); - short_tv |= TV_BOTNET; + cx.short_tv |= TV_BOTNET; } else { @@ -1502,12 +1513,12 @@ void process_botnet(void) /* * usersharing tick, 10 minute period */ - if (bn->status == BN_LINKED && (bn->tick_last + 600) < now) + if (bn->status == BN_LINKED && (bn->tick_last + 600) < cx.now) { #ifdef DEBUG debug("(process_botnet) {%i} periodic ushare tick\n",bn->sock); #endif /* DEBUG */ - bn->tick_last = now; + bn->tick_last = cx.now; to_file(bn->sock,"UT%i\n",bn->tick); } @@ -1531,7 +1542,7 @@ void process_botnet(void) else { bn->status = BN_BANNERSENT; - bn->when = now; + bn->when = cx.now; } /* write_fds is only set for sockets where reading is not needed */ continue; @@ -1577,7 +1588,7 @@ void process_botnet(void) } } - if ((bn->status == BN_CONNECT) && ((now - bn->when) > LINKTIME)) + if ((bn->status == BN_CONNECT) && ((cx.now - bn->when) > LINKTIME)) { #ifdef DEBUG debug("(process_botnet) {%i} Life is good; but not for this guy (guid == %i). Timeout!\n", @@ -1611,7 +1622,7 @@ clean: debug("(process_botnet) botnet quit: guid %i child of %i on socket %i\n", binfo->guid,bn->guid,bn->sock); #endif /* DEBUG */ - if (bn->list_complete) + if (bn->opt.links_complete) { send_global(SPYSTR_BOTNET,"quit: guid %i (child of %i)", binfo->guid,bn->guid); @@ -1620,7 +1631,7 @@ clean: } Free((char**)&binfo); } - if (bn->list_complete) + if (bn->opt.links_complete) { botnet_relay(bn,"BQ%i\n",bn->guid); } @@ -1639,6 +1650,22 @@ clean: * */ +void do_link_noargs(const char *from) +{ + NetCfg *cfg; + + /* + * list all the known links + */ + table_buffer("guid\tpass\thost\tport"); + for(cfg=netcfglist;cfg;cfg=cfg->next) + { + table_buffer("%i\t%s\t%s\t%i",cfg->guid,(cfg->pass) ? cfg->pass : EMPTYSTR, + (cfg->host) ? cfg->host : EMPTYSTR,cfg->port); + } + table_send(from,2); +} + void do_link(COMMAND_ARGS) { /* @@ -1649,21 +1676,6 @@ void do_link(COMMAND_ARGS) int iguid,iport; int mode; - /* - * list all the known links - */ - if (!*rest) - { - table_buffer("guid\tpass\thost\tport"); - for(cfg=netcfglist;cfg;cfg=cfg->next) - { - table_buffer("%i\t%s\t%s\t%i",cfg->guid,(cfg->pass) ? cfg->pass : "", - (cfg->host) ? cfg->host : "",cfg->port); - } - table_send(from,2); - return; - } - guid = chop(&rest); if (*guid == '+' || *guid == '-') mode = *guid++; @@ -1686,7 +1698,7 @@ usage: pp = &cfg->next; } - if (CurrentUser == &CoreUser || mode == '+') + if (CurrentUser == &cx.CoreUser || mode == '+') { if (cfg) { @@ -1726,6 +1738,7 @@ usage: if (mode == '-') { + to_user(from,"removing link guid: %i",iguid); *pp = cfg->next; Free((char**)&cfg); return; @@ -1759,10 +1772,9 @@ void do_cmd(COMMAND_ARGS) Mech *backup; char tempdata[MAXLEN]; char *target,*orig = rest; - int guid; target = chop(&rest); - guid = asc2int(target); + asc2int(target); if (errno) { unchop(orig,rest); @@ -1776,7 +1788,7 @@ void do_cmd(COMMAND_ARGS) return; } - if (STRCHR(from,'!')) + if (stringchr(from,'!')) sprintf(tempdata,"%s %i %s %s",target,current->guid,from,rest); else sprintf(tempdata,"%s %i %s!%s %s",target,current->guid,from,CurrentUser->mask->p,rest); diff --git a/src/note.c b/src/note.c index 9db0507..7fd0bd0 100644 --- a/src/note.c +++ b/src/note.c @@ -34,7 +34,6 @@ int catch_note(char *from, char *to, char *rest) { User *u; Note *n,**pp; - Strp *sp,**np; #ifdef DEBUG debug("(catch_note) from = %s, to = %s, rest = %s\n",from,to,rest); @@ -64,7 +63,7 @@ int catch_note(char *from, char *to, char *rest) append_strp(&u->note,rest); return(TRUE); } - if ((now - n->start) > 120) + if ((cx.now - n->start) > 120) { *pp = n->next; Free((char**)&n); @@ -85,7 +84,6 @@ void do_note(COMMAND_ARGS) { User *u; Note *n; - Strp *sp,**np; char header[MSGLEN]; /* @@ -101,7 +99,7 @@ void do_note(COMMAND_ARGS) set_mallocdoer(do_note); n = Calloc(sizeof(Note) + StrlenX(from,to,u->name,NULL)); - n->start = now; + n->start = cx.now; n->next = notelist; notelist = n; @@ -112,7 +110,7 @@ void do_note(COMMAND_ARGS) /* * add a note header */ - sprintf(header,"\001%s %s",from,time2str(now)); + sprintf(header,"\001%s %s",from,maketimestr(cx.now,TFMT_FULL)); append_strp(&u->note,header); } diff --git a/src/onhash.h b/src/onhash.h new file mode 100644 index 0000000..47c057c --- /dev/null +++ b/src/onhash.h @@ -0,0 +1,40 @@ +/* + * + * This file is included in ons.c right before on_msg + * It is also used in gencmd.c where its used with different + * random hashdata in order to find a hashmap with no + * collisions. Unfortunatly there is no way of handling + * hasmaps with collisions currently so if it gets stuck + * trying hashdata forever you are out of luck. + * + */ +int mkhash(const char *cmd) +{ + const char *s; + int h,t,ki,kk; + uint8_t a,b; + + s = cmd; + ki = 15 * strlen(cmd); + kk = hashdata[ki & HASHDATAMASK]; + while(*s) + { + a = tolowertab[(uchar)s[0]]; + b = tolowertab[(uchar)s[1]]; + h = (a - b) & HASHDATAMASK; + ki += a + hashdata[h]; +#ifdef HEATMAP + /* used when refining the algorithm */ + heatmap[ki & HASHDATAMASK] += 1; +#endif + kk ^= hashdata[ki & HASHDATAMASK] ^ (hashdata[(h + ki) & HASHDATAMASK] << 8); + s++; + } + t = kk & 511; +#ifndef COM_ONS_C + if (hash[t] > 0) + collis += 1; + hash[t] += 1; +#endif + return(t); +} diff --git a/src/ons.c b/src/ons.c index 7d5cac8..d8f8b86 100644 --- a/src/ons.c +++ b/src/ons.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2024 proton + Parts Copyright (c) 1997-2025 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 @@ -82,7 +82,7 @@ void on_kick(char *from, char *rest) if (current->spy & SPYF_CHANNEL) send_spy(chan->name,"*** %s was kicked by %s (%s)",nick,CurrentNick,rest); - if (!nickcmp(current->nick,nick)) + if (!nickcmp(getbotnick(current),nick)) { #ifdef DEBUG debug("(on_kick) I was kicked from %s\n",chan->name); @@ -168,7 +168,7 @@ void on_kick(char *from, char *rest) if (victim) { #ifdef SEEN - make_seen(nick,victim->userhost,from,rest,now,SEEN_KICKED); + make_seen(nick,victim->userhost,from,rest,cx.now,SEEN_KICKED); #endif /* SEEN */ /* @@ -231,7 +231,7 @@ void on_join(Chan *chan, char *from) */ if (chan->setting[TOG_CTL].int_var) { - if (STRCHR(from,'\031') || STRCHR(from,'\002') || STRCHR(from,'\022') || STRCHR(from,'\026')) + if (stringchr(from,'\031') || stringchr(from,'\002') || stringchr(from,'\022') || stringchr(from,'\026')) { deop_siteban(chan,cu); send_kick(chan,CurrentNick,KICK_BAD_IDENT); @@ -290,8 +290,8 @@ void on_nick(char *from, char *newnick) * grab the nick *RIGHT NOW* * this is a setting because this is risky, you might get collided as a result */ - if (!nickcmp(CurrentNick,current->wantnick)) - to_server("NICK %s\n",current->wantnick); + if (!nickcmp(CurrentNick,getbotwantnick(current))) + to_server("NICK %s\n",getbotwantnick(current)); #endif /* FASTNICK */ /* @@ -300,7 +300,7 @@ void on_nick(char *from, char *newnick) sprintf(newnuh,"%s!%s",newnick,getuh(from)); #ifdef SEEN - make_seen(CurrentNick,from,newnick,NULL,now,SEEN_NEWNICK); + make_seen(CurrentNick,from,newnick,NULL,cx.now,SEEN_NEWNICK); #endif /* SEEN */ /* @@ -311,9 +311,12 @@ void on_nick(char *from, char *newnick) change_authnick(from,newnuh); - if ((isbot = !nickcmp(current->nick,CurrentNick))) + if ((isbot = !nickcmp(getbotnick(current),CurrentNick))) { setbotnick(current,newnick); +#ifdef BOTNET + botnet_refreshbotinfo(); +#endif /* BOTNET */ } for(chan=current->chanlist;chan;chan=chan->next) @@ -355,9 +358,9 @@ void on_nick(char *from, char *newnick) if ((maxcount = chan->setting[INT_NCL].int_var) < 2) continue; - if ((now - cu->action_time[INDEX_NICK]) > NICKFLOODTIME) + if ((cx.now - cu->action_time[INDEX_NICK]) > NICKFLOODTIME) { - cu->action_time[INDEX_NICK] = now + (NICKFLOODTIME / (maxcount - 1)); + cu->action_time[INDEX_NICK] = cx.now + (NICKFLOODTIME / (maxcount - 1)); cu->action_num[INDEX_NICK] = 1; } else @@ -372,6 +375,8 @@ void on_nick(char *from, char *newnick) } } +#include "onhash.h" + void on_msg(char *from, char *to, char *rest) { #ifdef SCRIPTING @@ -389,7 +394,7 @@ void on_msg(char *from, char *to, char *rest) uchar *p1,*p2; int has_cc,has_bang; int uaccess; - int i,j; + int i,j,command_hash; /* * No line sent to this routine should be longer than MSGLEN @@ -397,6 +402,14 @@ void on_msg(char *from, char *to, char *rest) * non-NULL and non-zerolength */ + /* + * remember where the string started + */ + origstart = rest; + + /* + * Are we recording a note? + */ #ifdef NOTE if (notelist && catch_note(from,to,rest)) return; @@ -407,10 +420,7 @@ void on_msg(char *from, char *to, char *rest) * public commands, we can go directly to common_public() */ if (CurrentChan && !CurrentChan->setting[TOG_PUB].int_var) - { - common_public(CurrentChan,from,"<%s> %s",rest); - return; - } + goto public_msg_unchopped; if (CurrentDCC) { @@ -425,12 +435,8 @@ void on_msg(char *from, char *to, char *rest) return; } - /* - * remember where the string started - */ - origstart = rest; - if (from == CoreUser.name) + if (from == cx.CoreUser.name) { has_cc = TRUE; } @@ -445,7 +451,7 @@ void on_msg(char *from, char *to, char *rest) if ((p2 = (uchar*)(command = chop(&rest))) == NULL) return; - p1 = (uchar*)current->nick; + p1 = (uchar*)getbotnick(current); while(!(i = tolowertab[*(p1++)] - tolowertab[*p2]) && *(p2++)) ; @@ -469,15 +475,15 @@ void on_msg(char *from, char *to, char *rest) command++; } + command_hash = mkhash(command); + #ifdef ALIAS arec = 0; recheck_alias: -#endif /* ALIAS */ -#ifdef ALIAS for(alias=aliaslist;alias;alias=alias->next) { - if (!stringcasecmp(alias->alias,command)) + if (command_hash == alias->hash && stringcasecmp(alias->alias,command) == 0) { unchop(command,rest); afmt(amem,alias->format,command); @@ -521,177 +527,186 @@ recheck_alias: if (i) return; #endif /* SCRIPTING */ + command_hash = mkhash(command); + i = hashmap[command_hash]; +#ifdef DEBUG + debug("(on_msg) %s = hash %i, mapped to %i %s\n",command,command_hash,i,(i==255)?"(no match)":mcmd[i].name); +#endif /* DEBUG */ + if (i == 255) + goto public_msg; + + if (!has_cc && mcmd[i].cc && !(has_bang && mcmd[i].cbang)) + goto public_msg; + if (uaccess < acmd[i]) + goto public_msg; /* - * match "command" against internal command list + * The string hash matches a command, but is it a false positive? */ - for(;mcmd[i].name;i++) - { - if (!has_cc && mcmd[i].cc && !(has_bang && mcmd[i].cbang)) - continue; - if (uaccess < acmd[i]) - continue; - j = stringcasecmp(mcmd[i].name,command); - if (j < 0) - continue; - if (j > 0) - break; + if (stringcasecmp(mcmd[i].name,command) != 0) + goto public_msg; #if defined(BOTNET) && defined(REDIRECT) - if (mcmd[i].nocmd && redirect.to) - return; + if (mcmd[i].nocmd && redirect.to) + return; #endif /* BOTNET && REDIRECT */ - if (mcmd[i].nopub && CurrentChan) - { + if (mcmd[i].nopub && CurrentChan) + { #ifdef DEBUG - debug("(on_msg) Public command (%s) ignored\n",command); + debug("(on_msg) Public command (%s) ignored\n",command); #endif /* DEBUG */ - return; - } - - CurrentCmd = &mcmd[i]; - -#ifdef SUPPRESS -#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 (mcmd[i].supres && CurrentChan) - { - send_suppress(CurrentCmd->name,rest); - } -#endif -#endif /* SUPPRESS */ - /* - * convert the command to uppercase - */ - stringcpy(command,mcmd[i].name); - - /* - * send statmsg with info on the command executed - */ - if (current->setting[TOG_SPY].int_var) - { - send_spy(SPYSTR_STATUS,":%s[%i]: Executing %s[%i]", - CurrentNick,uaccess,command,(int)acmd[i]); - } - - /* - * CAXS check: first argument might be a channel - * check user access on target channel - */ - if (mcmd[i].caxs) - { - /* get channel name; 1: msg, 2: to, 3: active channel */ - to = (char*)get_channel(to,&rest); - if (!ischannel(to)) - return; - uaccess = get_authaccess(from,to); - if (uaccess < acmd[i]) - return; - CurrentChan = find_channel_ny(to); - if (mcmd[i].acchan && (CurrentChan == NULL || CurrentChan->active == 0)) - { - to_user(from,ERR_CHAN,to); - return; - } - } - else - /* - * GAXS check: user needs global access - */ - if (mcmd[i].gaxs) - { - uaccess = get_authaccess(from,MATCH_ALL); - if (uaccess < acmd[i]) - return; - } - - /* - * list of last LASTCMDSIZE commands - */ - if (from != CoreUser.name) - { - Free(¤t->lastcmds[LASTCMDSIZE-1]); - for(j=LASTCMDSIZE-2;j>=0;j--) - current->lastcmds[j+1] = current->lastcmds[j]; - if ((pt = STRCHR(from,'@')) == NULL) - pt = from; - set_mallocdoer(on_msg); - current->lastcmds[0] = (char*)Calloc(strlen(pt) + 45); - if (CurrentUser) - { - sprintf(current->lastcmds[0],"[%s] %s\r%s[%-3i]\t(*%s)", - time2medium(now),command,CurrentUser->name, - (CurrentUser->x.x.access),pt); - } - else - { - sprintf(current->lastcmds[0],"[%s] %s\r%s[---]\t(*%s)", - time2medium(now),command,CurrentNick,pt); - } - } - - /* - * CARGS check: at least one argument is required - */ - if (mcmd[i].args && !*rest) - { - if (uaccess) usage_command(from,command); - return; - } - -#ifdef REDIRECT - /* - * can this command be redirected? - */ - if (!redirect.to && mcmd[i].redir) - { - if (mcmd[i].lbuf && ischannel(orig_to)) - { - set_mallocdoer(on_msg); - redirect.to = stringdup(to); - redirect.method = R_PRIVMSG; - } - else - if (begin_redirect(from,rest) < 0) - return; - } -#endif /* REDIRECT */ - - if (mcmd[i].dcc && partyline_only_command(from)) - return; - - mcmd[i].func(from,to,rest,acmd[i]); - -#ifdef DEBUG - CurrentCmd = NULL; -#endif /* DEBUG */ -#ifdef REDIRECT - end_redirect(); -#endif /* REDIRECT */ - - /* - * be quick to exit afterwards, there are "dangerous" commands like DIE and DEL (user) - */ return; } + CurrentCmd = &mcmd[i]; + +#ifdef SUPPRESS +#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 (mcmd[i].supres && CurrentChan) + { + send_suppress(CurrentCmd->name,rest); + } +#endif +#endif /* SUPPRESS */ + /* + * convert the command to uppercase + */ + stringcpy(command,mcmd[i].name); + + /* + * send statmsg with info on the command executed + */ + if (current->setting[TOG_SPY].int_var) + { + send_spy(SPYSTR_STATUS,":%s[%i]: Executing %s[%i]", + CurrentNick,uaccess,command,(int)acmd[i]); + } + + /* + * CAXS check: first argument might be a channel + * check user access on target channel + */ + if (mcmd[i].caxs) + { + /* get channel name; 1: msg, 2: to, 3: active channel */ + to = (char*)get_channel(to,&rest); + if (!ischannel(to)) + return; + uaccess = get_authaccess(from,to); + if (uaccess < acmd[i]) + return; + CurrentChan = find_channel_ny(to); + if (mcmd[i].acchan && (CurrentChan == NULL || CurrentChan->active == 0)) + { + to_user(from,ERR_CHAN,to); + return; + } + } + else + /* + * GAXS check: user needs global access + */ + if (mcmd[i].gaxs) + { + uaccess = get_authaccess(from,MATCH_ALL); + if (uaccess < acmd[i]) + return; + } + + /* + * list of last LASTCMDSIZE commands + */ + if (from != cx.CoreUser.name) + { + Free(¤t->lastcmds[LASTCMDSIZE-1]); + for(j=LASTCMDSIZE-2;j>=0;j--) + current->lastcmds[j+1] = current->lastcmds[j]; + if ((pt = stringchr(from,'@')) == NULL) + pt = from; + set_mallocdoer(on_msg); + current->lastcmds[0] = (char*)Calloc(strlen(pt) + 45); + if (CurrentUser) + { + sprintf(current->lastcmds[0],"[%s] %s\r%s[%-3i]\t(*%s)", + maketimestr(cx.now,TFMT_CLOCK),command,CurrentUser->name, + (CurrentUser->x.x.access),pt); + } + else + { + sprintf(current->lastcmds[0],"[%s] %s\r%s[---]\t(*%s)", + maketimestr(cx.now,TFMT_CLOCK),command,CurrentNick,pt); + } + } + + /* + * CARGS check: at least one argument is required + */ + if (mcmd[i].args && !*rest) + { + if (uaccess) usage_command(from,command); + return; + } + +#ifdef REDIRECT + /* + * can this command be redirected? + */ + if (!redirect.to && mcmd[i].redir) + { + if (mcmd[i].lbuf && ischannel(orig_to)) + { + set_mallocdoer(on_msg); + redirect.to = stringdup(to); + redirect.method = R_PRIVMSG; + } + else + if (begin_redirect(from,rest) < 0) + return; + } +#endif /* REDIRECT */ + + if (mcmd[i].dcc && partyline_only_command(from)) + return; + + /* + * Run command function + */ + if (mcmd[i].noargfunc && *rest == 0) + mcmd[i].noargfunc(from); + else + mcmd[i].func(from,to,rest,acmd[i]); + +#ifdef REDIRECT + end_redirect(); +#endif /* REDIRECT */ + + /* + * be quick to exit afterwards, there are "dangerous" commands like DIE and USER -... + */ + return; + + /* + * If the input isnt a command or the sender lacks access + */ +public_msg: /* * un-chop() the message string */ @@ -699,6 +714,7 @@ recheck_alias: if (CurrentChan) { +public_msg_unchopped: common_public(CurrentChan,from,"<%s> %s",origstart); } else @@ -711,7 +727,7 @@ recheck_alias: { partyline_broadcast(CurrentDCC,"<%s> %s\n",origstart); #ifdef BOTNET - botnet_relay(NULL,"PM* * %s@%s %s\n",CurrentNick,current->nick,origstart); + botnet_relay(NULL,"PM* * %s@%s %s\n",CurrentNick,getbotnick(current),origstart); #endif /* BOTNET */ } else @@ -729,8 +745,11 @@ void on_mode(char *from, char *channel, char *rest) char templimit[20]; char *nick; char *parm,*nickuh,*mode; - int i,sign,enfm,maxprot; + int i,sign,rev,enfm,flag,maxprot,isself; +#ifdef DEBUG + debug("(on_mode) %s --> %s: %s\n",from,channel,rest); +#endif /* DEBUG */ if ((chan = find_channel_ac(channel)) == NULL) return; channel = chan->name; @@ -749,16 +768,6 @@ void on_mode(char *from, char *channel, char *rest) doer = find_chanuser(chan,from); modeloop: - if (*mode == 'o' || *mode == 'v') - { - nick = chop(&rest); - if ((victim = find_chanuser(chan,nick)) == NULL) - { - mode++; - goto modeloop; - } - } - switch(*mode) { case '+': @@ -767,25 +776,50 @@ modeloop: break; /* * + * MODE +/-v * MODE +/-o * */ + case 'v': case 'o': + nick = chop(&rest); + victim = find_chanuser(chan,nick); + if (victim == NULL) /* Cant take action against an unknown entity */ + { + mode++; + goto modeloop; + } + + rev = 0; i = (victim->user) ? victim->user->x.x.access : 0; + + /* + * Can only be 'o' or 'v' + * Sign can only be '+' or '-' + * #define CU_VOICE 0x0001 + * #define CU_CHANOP 0x0002 + */ + flag = CU_VOICE + (*mode == 'o'); + victim->flags &= ~flag; + victim->flags |= (flag & (-(sign == '+'))); + + if (*mode == 'v') + break; + + victim->flags &= ~CU_DEOPPED; + + isself = (0 == nickcmp(getbotnick(current),nick)) ? TRUE : FALSE; + /* +o */ if (sign == '+') { - victim->flags |= CU_CHANOP; - victim->flags &= ~CU_DEOPPED; - if (!i) + if (0 == i) { - if (victim->shit || (chan->setting[TOG_SD].int_var && !doer) || - chan->setting[TOG_SO].int_var) + if (victim->shit || (chan->setting[TOG_SO].int_var) || (chan->setting[TOG_SD].int_var && !doer)) { - send_mode(chan,60,QM_CHANUSER,'-','o',victim); + rev = '-'; } } - else - if (!nickcmp(current->nick,nick)) + if (isself) { /* * wooohoooo! they gave me ops!!! @@ -799,35 +833,30 @@ modeloop: } check_shit(); update_modes(chan); + if (current->spy & SPYF_STATUS && doer) + send_spy(SPYSTR_STATUS,"Given op on %s, set by %s",chan->name,doer->nick); } -#ifdef DEBUG - debug("(on_mode) %s!%s --> %i\n",victim->nick,victim->userhost,i); -#endif /* DEBUG */ } /* -o */ else { - victim->flags &= ~(CU_CHANOP|CU_DEOPPED); - if (i == BOTLEVEL) + if (isself) { - if (!nickcmp(current->nick,nick)) - { - /* - * they dont love me!!! :~( - */ - chan->bot_is_op = FALSE; - } + /* + * they dont love me!!! :~( + */ + chan->bot_is_op = FALSE; + if (current->spy & SPYF_STATUS) + send_spy(SPYSTR_STATUS,"Lost op on %s, removed by %s",chan->name,nick); } /* * idiots deopping themselves */ - if (!nickcmp(from,nick)) +#ifdef DEBUG + debug("(on_mode) doer == victim: %s\n",(doer == victim) ? "TRUE" : "FALSE"); +#endif /* DEBUG */ + if (doer == victim) break; - /* - * 1. Use enfm var to temporarily store users access - * 2. get_userlevel also checks is_localbot()... - */ - enfm = (doer && doer->user) ? doer->user->x.x.access : 0; - if (enfm == BOTLEVEL) + if (doer && doer->user && doer->user->x.x.access >= OWNERLEVEL) break; if (check_mass(chan,doer,INT_MDL)) mass_action(chan,doer); @@ -839,29 +868,14 @@ modeloop: nickuh = get_nuh(victim); if (get_authaccess(nickuh,channel)) { - send_mode(chan,60,QM_CHANUSER,'+','o',victim); + rev = '+'; prot_action(chan,from,doer,NULL,victim); } } } + if (rev) + send_mode(chan,60,QM_CHANUSER,rev,'o',victim); break; - /* - * - * MODE +/-v - * - */ - case 'v': - if (sign == '+') - victim->flags |= CU_VOICE; - else - victim->flags &= ~CU_VOICE; - break; -#ifdef IRCD_EXTENSIONS -/* -:joonicks!*@* MODE #emech +I *king*!*@* -:joonicks!*@* MODE #emech +e *kong*!*@* -*/ -#endif /* IRCD_EXTENSIONS */ /* * * MODE +/-b @@ -870,6 +884,8 @@ modeloop: #ifdef IRCD_EXTENSIONS /* * ircnet braindamage modes + * :joonicks!*@* MODE #emech +I *king*!*@* + * :joonicks!*@* MODE #emech +e *kong*!*@* */ case 'I': case 'e': @@ -881,7 +897,7 @@ modeloop: #ifdef IRCD_EXTENSIONS Ban *newban; - newban = make_ban(&chan->banlist,from,parm,now); + newban = make_ban(&chan->banlist,from,parm,cx.now); if (*mode == 'I') newban->imode = TRUE; if (*mode == 'e') newban->emode = TRUE; /* @@ -889,7 +905,7 @@ modeloop: */ break; #else /* IRCD_EXTENSIONS */ - make_ban(&chan->banlist,from,parm,now); + make_ban(&chan->banlist,from,parm,cx.now); #endif /* IRCD_EXTENSIONS */ /* * skip protection checks if the doer is myself or another known bot @@ -1090,7 +1106,7 @@ void on_action(char *from, char *to, char *rest) { partyline_broadcast(CurrentDCC,"* %s %s\n",rest); #ifdef BOTNET - botnet_relay(NULL,"PM* * %s@%s \001%s\n",CurrentNick,current->nick,rest); + botnet_relay(NULL,"PM* * %s@%s \001%s\n",CurrentNick,getbotnick(current),rest); #endif /* BOTNET */ return; } diff --git a/src/parse.c b/src/parse.c index a4d658c..5f3311c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2021 proton + Parts Copyright (c) 1997-2025 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 @@ -67,7 +67,7 @@ void parse_invite(char *from, char *rest) if ((i >= JOINLEVEL) && (i < BOTLEVEL)) { join_channel(chan,NULL); - current->lastrejoin = now; + current->lastrejoin = cx.now; } } @@ -84,7 +84,7 @@ void parse_join(char *from, char *rest) if ((CurrentChan = chan = find_channel_ny(rest)) == NULL) return; - if (!nickcmp(current->nick,from)) + if (!nickcmp(getbotnick(current),from)) { #ifdef DEBUG debug("(parse_join) Im joining %s\n",chan->name); @@ -122,7 +122,7 @@ void parse_join(char *from, char *rest) stats = chan->stats; stats->userseconds = 0; stats->users = 0; - stats->lastuser = now; + stats->lastuser = cx.now; stats->flags |= CSTAT_PARTIAL; } #endif /* STATS */ @@ -151,7 +151,7 @@ void parse_join(char *from, char *rest) */ if (is_bot(from)) { - CurrentUser = (User*)&LocalBot; + CurrentUser = (User*)&cx.LocalBot; CurrentShit = NULL; } else @@ -202,7 +202,7 @@ void parse_mode(char *from, char *rest) on_mode(from,to,rest); } else - if (!stringcasecmp(current->nick,to)) + if (!stringcasecmp(getbotnick(current),to)) /* todo: nickcmp? */ { char *dst; char sign; @@ -259,7 +259,7 @@ void parse_notice(char *from, char *rest) if (!stringcasecmp(ctcp,"PING") && ((pingtime = get_number(rest)) != -1)) { send_spy(SPYSTR_STATUS,"[CTCP PING Reply From %s] %i second(s)", - CurrentNick,(int)(now - pingtime)); + CurrentNick,(int)(cx.now - pingtime)); } else { @@ -311,7 +311,7 @@ void parse_part(char *from, char *rest) if (current->spy & SPYF_CHANNEL) send_spy(channel,"*** Parts: %s (%s)",nick,from); - if (!nickcmp(current->nick,nick)) + if (!nickcmp(getbotnick(current),nick)) { #ifdef DEBUG debug("(parse_part) Im parting %s\n",chan->name); @@ -333,7 +333,7 @@ void parse_part(char *from, char *rest) #endif /* STATS */ #ifdef SEEN - make_seen(nick,from,channel,NULL,now,SEEN_PARTED); + make_seen(nick,from,channel,NULL,cx.now,SEEN_PARTED); #endif /* SEEN */ remove_chanuser(chan,nick); @@ -367,7 +367,7 @@ void parse_pong(char *from, char *rest) ot = (ot * 10) + (*src++ - '0'); current->ontime = ot; #ifdef DEBUG - debug("(parse_pong) recovering ontime = %lu (%s)\n",ot,idle2str(now - ot,TRUE)); + debug("(parse_pong) recovering ontime = %lu (%s)\n",ot,idle2str(ot,TRUE)); #endif } } @@ -377,7 +377,7 @@ void parse_privmsg(char *from, char *rest) ChanUser *cu; char *to,*channel; #ifdef URLCAPTURE - const char *src; + unsigned char *src; #endif /* URLCAPTURE */ to = chop(&rest); @@ -391,7 +391,7 @@ void parse_privmsg(char *from, char *rest) { if ((cu = find_chanuser(CurrentChan,from))) { - cu->idletime = now; + cu->idletime = cx.now; if (cu->shit) return; CurrentUser = cu->user; @@ -430,7 +430,7 @@ void parse_privmsg(char *from, char *rest) CurrentChan->stats->privmsg++; #endif /* STATS */ #ifdef URLCAPTURE - src = rest; + src = (unsigned char *)rest; while(*src) { if (tolowertab[*src] == 'h') @@ -440,7 +440,7 @@ void parse_privmsg(char *from, char *rest) if ((src[4] == ':') || /* "http:" */ (tolowertab[src[4]] == 's' && src[5] == ':')) /* "https:" */ { - urlcapture(src); + urlcapture((const char *)src); } } } @@ -457,7 +457,7 @@ void parse_quit(char *from, char *rest) nickcpy(CurrentNick,from); #ifdef SEEN - make_seen(CurrentNick,from,rest,NULL,now,SEEN_QUIT); + make_seen(CurrentNick,from,rest,NULL,cx.now,SEEN_QUIT); #endif /* SEEN */ #ifdef FASTNICK @@ -505,6 +505,9 @@ void parse_topic(char *from, char *rest) reverse_topic(chan,from,rest); } +/* +(in) {5} :She!haveident@libera/staff/she/her WALLOPS :Services stuff done. PSA for channel founders: Single-# channels that do NOT belong +*/ void parse_wallops(char *from, char *rest) { nickcpy(CurrentNick,from); @@ -547,12 +550,15 @@ void parse_251(char *from, char *rest) { nick = chop(&rest); setbotnick(current,nick); +#ifdef BOTNET + botnet_refreshbotinfo(); +#endif /* BOTNET */ for(sp=serverlist;sp;sp=sp->next) { if (!stringcasecmp(sp->name,from) || !stringcasecmp(sp->realname,from)) { - sp->lastconnect = now; - current->ontime = now; + sp->lastconnect = cx.now; + current->ontime = cx.now; current->server = sp->ident; } } @@ -702,11 +708,9 @@ void parse_311(char *from, char *rest) if (host) host[-1] = '@'; - if (!nickcmp(nick,current->nick)) + if (!nickcmp(getbotnick(current),nick)) { - Free((char**)¤t->userhost); - set_mallocdoer(parse_311); - current->userhost = stringdup(user); + setbotuserhost(current,user); #ifdef BOTNET botnet_refreshbotinfo(); #endif /* BOTNET */ @@ -812,7 +816,7 @@ void parse_317(char *from, char *rest) } if (when != -1) - send_pa(PA_WHOIS,nick,"Signed On: %s",time2away(when)); + send_pa(PA_WHOIS,nick,"Signed On: %s",maketimestr(when,TFMT_AWAY)); send_pa(PA_WHOIS,nick, (sec) ? "Idle: %i minute%s, %i second%s" : "Idle: %i minute%s", @@ -855,7 +859,7 @@ void parse_319(char *from, char *rest) send_pa(PA_WHOIS,nick,"Channels: %s",rest); /* if nick is myself (the bot), check for reset recovery */ - if (!nickcmp(nick,current->nick)) + if (!nickcmp(getbotnick(current),nick)) { if (current->reset) { @@ -871,7 +875,7 @@ loop: */ while(*channel && *channel != '#') /* this is a recipe for disaster with other valid channels than '#' */ channel++; - sprintf(nuh,"%s!%s",current->nick,current->userhost); + sprintf(nuh,"%s!%s",getbotnick(current),getbotuserhost(current)); #ifdef DEBUG debug("(parse_319) :%s JOIN :%s\n",nuh,channel); #endif /* DEBUG */ @@ -961,6 +965,10 @@ void parse_352(char *from, char *rest) if (chan->wholist == TRUE) return; +#ifdef STATS + if (chan->stats) + chan->stats->users++; +#endif /* STATS */ userhost = chop(&rest); rest[-1] = '@'; /* glue: "user\0host" --> "user@host" */ @@ -977,7 +985,7 @@ void parse_352(char *from, char *rest) #ifdef DEBUG debug("(parse_352) setting as local bot: %s (%s)\n",nuh,channel); #endif /* DEBUG */ - chan->users->user = (User*)&LocalBot; + chan->users->user = (User*)&cx.LocalBot; chan->users->shit = NULL; } else @@ -996,7 +1004,7 @@ void parse_352(char *from, char *rest) if (*rest == '@') { chan->users->flags = CU_CHANOP; - if (!nickcmp(current->nick,nick)) + if (!nickcmp(getbotnick(current),nick)) { #ifdef DEBUG debug("(parse_352) According to wholist I have ops\n"); @@ -1040,7 +1048,7 @@ void parse_367(char *from, char *rest) banfrom = "?"; if ((bantime = get_number(rest)) == -1) - bantime = now; + bantime = cx.now; make_ban(&chan->banlist,banfrom,banmask,bantime); } @@ -1060,19 +1068,16 @@ void parse_376(char *from, char *rest) { if (*sp->realname == 0) stringcpy_n(sp->realname,from,NAMELEN); - sp->lastconnect = now; + sp->lastconnect = cx.now; } if (current->connect != CN_ONLINE) { current->connect = CN_ONLINE; - current->ontime = now; - to_server("WHOIS %s\n",current->nick); + current->ontime = cx.now; + to_server("WHOIS %s\n",getbotnick(current)); if ((mode = current->setting[STR_UMODES].str_var)) - to_server("MODE %s %s\n",current->nick,mode); + to_server("MODE %s %s\n",getbotnick(current),mode); } -#ifdef IDWRAP - unlink_identfile(); -#endif /* IDWRAP */ } /* @@ -1113,7 +1118,7 @@ void parse_433(char *from, char *rest) do { s2 = chop(&s); - if (current->connect == CN_ONLINE && !stringcasecmp(current->nick,s2)) + if (current->connect == CN_ONLINE && !stringcasecmp(getbotnick(current),s2)) /* todo: nickcmp? */ { /* nicks listed first are more worth, dont try nicks after */ break; @@ -1134,14 +1139,12 @@ void parse_433(char *from, char *rest) if (nick) { #ifdef DEBUG - debug("(parse_433) Nick: %s, Altnick: %s\n",current->nick,nick); + debug("(parse_433) Nick: %s, Altnick: %s\n",getbotnick(current),nick); #endif /* DEBUG */ to_server("NICK %s\n",nick); if (current->connect != CN_ONLINE) { - Free((char**)¤t->nick); - set_mallocdoer(parse_433); - current->nick = stringdup(nick); + setbotnick(current,nick); } return; } @@ -1225,7 +1228,7 @@ void parse_346(char *from, char *rest) banfrom = "?"; if ((bantime = get_number(rest)) == -1) - bantime = now; + bantime = cx.now; new = make_ban(&chan->banlist,banfrom,banmask,bantime); new->imode = TRUE; @@ -1255,7 +1258,7 @@ void parse_348(char *from, char *rest) banfrom = "?"; if ((bantime = get_number(rest)) == -1) - bantime = now; + bantime = cx.now; new = make_ban(&chan->banlist,banfrom,banmask,bantime); new->emode = TRUE; @@ -1373,21 +1376,24 @@ void parse_005(char *from, char *rest) #define NEEDFROM 1 #define DROPONE 2 -LS const struct +struct ParseFunctions { - uint32_t hash; - short flags; - void (*func)(char *, char *); + const uint32_t hash; + const short flags; + void (*func)(char *, char *); + int hits; } pFuncs[] = { + { 0x50494E47, 0, parse_ping }, /* PING */ { 0x50524956, NEEDFROM, parse_privmsg }, /* PRIVMSG */ + { 0x00333532, NEEDFROM|DROPONE, parse_352 }, /* 352 RPL_WHOREPLY */ + { 0x00333637, NEEDFROM|DROPONE, parse_367 }, /* 367 RPL_BANLIST */ { 0x4A4F494E, NEEDFROM, parse_join }, /* JOIN */ { 0x50415254, NEEDFROM, parse_part }, /* PART */ { 0x4D4F4445, NEEDFROM, parse_mode }, /* MODE */ { 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 */ @@ -1395,7 +1401,6 @@ LS const struct { 0x494E5649, NEEDFROM|DROPONE, parse_invite }, /* INVITE */ { 0x57414C4C, NEEDFROM, parse_wallops }, /* WALLOPS */ { 0x4552524F, 0, parse_error }, /* ERROR */ - { 0x00333532, NEEDFROM|DROPONE, parse_352 }, /* 352 RPL_WHOREPLY */ { 0x00333135, NEEDFROM|DROPONE, parse_315 }, /* 315 RPL_ENDOFWHO */ { 0x00323231, NEEDFROM, parse_mode }, /* 221 RPL_UMODEIS */ { 0x00333131, NEEDFROM|DROPONE, parse_311 }, /* 311 RPL_WHOISUSER */ @@ -1429,7 +1434,6 @@ LS const struct { 0x00333137, NEEDFROM|DROPONE, parse_317 }, /* 317 RPL_WHOISIDLE */ { 0x00333139, NEEDFROM|DROPONE, parse_319 }, /* 319 RPL_WHOISCHANNELS */ { 0x00333234, NEEDFROM|DROPONE, parse_324 }, /* 324 RPL_CHANNELMODEIS */ - { 0x00333637, NEEDFROM|DROPONE, parse_367 }, /* 367 RPL_BANLIST */ { 0x00343531, 0, parse_451 }, /* 451 ERR_NOTREGISTERED */ { 0x00343035, NEEDFROM|DROPONE, parse_471 }, /* 405 ERR_TOOMANYCHANNELS */ { 0x00343731, NEEDFROM|DROPONE, parse_471 }, /* 471 ERR_CHANNELISFULL */ @@ -1448,7 +1452,7 @@ LS const struct { 0, 0, NULL } }; -uint32_t stringhash(char *s) +static __INLINE__ uint32_t stringhash(char *s) { uint32_t hash; int i; @@ -1463,16 +1467,28 @@ void parse_server_input(char *rest) { #ifdef SCRIPTING Hook *hook; + int skip; #endif /* SCRIPTING */ char *from,*command; uint32_t cmdhash; int i; +#ifdef DEBUG + if (rest == NULL) + { + for(i=0;pFuncs[i].hash;i++) + { + debug("[PsI] (%i) hash %X: hits %i\n",i,pFuncs[i].hash,pFuncs[i].hits); + } + return; + } +#endif /* DEBUG */ + if (current->spy & (SPYF_RAWIRC|SPYF_RANDSRC)) send_spy(SPYSTR_RAWIRC,rest); -/*new undernet amusements */ -/*(in) {5} NOTICE AUTH :*** You have identd disabled (or broken), to continue to connect you must type /QUOTE PASS 17071 */ +/* New undernet amusements */ +/* NOTICE AUTH :*** You have identd disabled (or broken), to continue to connect you must type /QUOTE PASS 17071 */ if (current->connect == CN_CONNECTED && *rest == 'N' && !matches("NOTICE AUTH * /QUOTE PASS *",rest)) { from = STREND(rest); @@ -1502,7 +1518,7 @@ void parse_server_input(char *rest) rest++; #ifdef SCRIPTING - cmdhash = 1; + skip = 0; for(hook=hooklist;hook;hook=hook->next) { /* @@ -1515,18 +1531,16 @@ void parse_server_input(char *rest) */ if (hook->flags == MEV_PARSE && !stringcasecmp(command,hook->type.command)) { - if (hook->func(from,rest,hook)) - /* if the hook returns non-zero, the input should not be parsed internally */ - cmdhash = 0; + /* if the hook returns non-zero, the input should not be parsed internally */ + skip += hook->func(from,rest,hook); } } - if (cmdhash == 0) + if (skip) return; #endif /* SCRIPTING */ cmdhash = stringhash(command); - /*debug("cmdhash = %08X\n",cmdhash); */ for(i=0;pFuncs[i].hash;i++) { if (cmdhash == pFuncs[i].hash) @@ -1535,9 +1549,9 @@ void parse_server_input(char *rest) return; if (pFuncs[i].flags & DROPONE) chop(&rest); /* discard one argument (usually bot nick) */ + pFuncs[i].hits++; pFuncs[i].func(from,rest); return; } } - /*debug("unmatched cmdhash %08X\n",cmdhash); */ } diff --git a/src/partyline.c b/src/partyline.c index 319276d..9290ac9 100644 --- a/src/partyline.c +++ b/src/partyline.c @@ -55,7 +55,7 @@ check_telnet_malloc: client->fileno = -1; #endif /* DCC_FILE */ client->flags = DCC_TELNETPASS; - client->lasttime = now; + client->lasttime = cx.now; client->next = current->clientlist; current->clientlist = client; #ifdef DEBUG @@ -119,12 +119,12 @@ void partyline_banner(Client *client) char tmp[MSGLEN]; client->flags = DCC_ACTIVE; - client->lasttime = now; + client->lasttime = cx.now; sprintf(tmp,"[%s] %s[%i] has connected", - current->nick,client->user->name,(int)client->user->x.x.access); + getbotnick(current),client->user->name,(int)client->user->x.x.access); - if ((to_file(client->sock,"[%s] %s\n",time2medium(now),tmp)) < 0) + if ((to_file(client->sock,"[%s] %s\n",maketimestr(cx.now,TFMT_CLOCK),tmp)) < 0) { client->flags = DCC_DELETE; return; @@ -134,7 +134,7 @@ void partyline_banner(Client *client) { CurrentDCC = client; stringcpy(tmp,SPYSTR_STATUS); - do_spy(client->user->name,current->nick,tmp,0); + do_spy(client->user->name,getbotnick(current),tmp,0); CurrentDCC = NULL; } } @@ -142,9 +142,10 @@ void partyline_banner(Client *client) void dcc_chat(char *from) { struct sockaddr_in sai; + unsigned int sz; Client *client; User *user; - int sock,sz; + int sock; if ((user = get_authuser(from,NULL)) == NULL) return; @@ -169,7 +170,7 @@ void dcc_chat(char *from) client->user = user; client->sock = sock; client->flags = DCC_WAIT; - client->lasttime = now; + client->lasttime = cx.now; client->next = current->clientlist; current->clientlist = client; @@ -240,11 +241,11 @@ void do_whom(COMMAND_ARGS) { stringcpy(stt,TEXT_NOTCONNECTED); } - table_buffer(TEXT_WHOMSELFLINE,bot->nick,(bot == current) ? "(me)" : "b200",stt); + table_buffer(TEXT_WHOMSELFLINE,getbotnick(bot),(bot == current) ? "(me)" : "b200",stt); for(client=bot->clientlist;client;client=client->next) { - m = (now - client->lasttime) / 60; - s = (now - client->lasttime) % 60; + m = (cx.now - client->lasttime) / 60; + s = (cx.now - client->lasttime) % 60; table_buffer(TEXT_WHOMUSERLINE, #ifdef TELNET client->user->name,client->user->x.x.access,(client->flags & DCC_TELNET) ? "telnet" : "DCC",m,s); diff --git a/src/prot.c b/src/prot.c index 9db1f22..0c2fd6a 100644 --- a/src/prot.c +++ b/src/prot.c @@ -28,6 +28,60 @@ #include "text.h" #include "mcmd.h" +/* + * deal with undesired lusers + */ +void screwban_format(char *userhost) +{ + int sz,n,pos; + +#ifdef DEBUG + debug("(screwban_format) %s\n",userhost); +#endif /* DEBUG */ + + if ((sz = strlen(userhost)) < 8) + return; + + n = RANDOM(4,sz); + while(--n) + { + pos = RANDOM(0,(sz - 1)); + if (!stringchr("?!@*",userhost[pos])) + { + userhost[pos] = (RANDOM(0,3) == 0) ? '*' : '?'; + } + } +} + +void deop_ban(Chan *chan, ChanUser *victim, char *mask) +{ + if (!mask) + mask = format_uh(get_nuh(victim),FUH_USERHOST); + send_mode(chan,85,QM_CHANUSER,'-','o',victim); + send_mode(chan,90,QM_RAWMODE,'+','b',mask); +} + +void deop_siteban(Chan *chan, ChanUser *victim) +{ + char *mask; + + mask = format_uh(get_nuh(victim),FUH_HOST); + deop_ban(chan,victim,mask); +} + +void deop_screwban(Chan *chan, ChanUser *victim) +{ + char *mask; + int i; + + for(i=2;--i;) + { + mask = format_uh(get_nuh(victim),FUH_USERHOST); + screwban_format(mask); + deop_ban(chan,victim,mask); + } +} + /* * * kicking and screaming @@ -63,7 +117,7 @@ void push_kicks(Chan *chan) qKick *kick; int n; - n = (current->sendq_time - now); + n = (current->sendq_time - cx.now); while(n < 6) { if ((kick = chan->kicklist) == NULL) @@ -189,7 +243,7 @@ void push_modes(Chan *chan, int lowpri) char *dstflag,*dstparm,lastmode; int n,maxmodes; - n = (current->sendq_time - now); + n = (current->sendq_time - cx.now); loop: maxmodes = current->setting[INT_MODES].int_var; @@ -278,7 +332,6 @@ void update_modes(Chan *chan) */ int check_mass(Chan *chan, ChanUser *doer, int type) { - time_t when; int num,limit; /* @@ -325,9 +378,9 @@ int check_mass(Chan *chan, ChanUser *doer, int type) break; } - if ((now - doer->action_time[num]) > 10) + if ((cx.now - doer->action_time[num]) > 10) { - doer->action_time[num] = now; + doer->action_time[num] = cx.now; doer->action_num[num] = 0; } ++(doer->action_num[num]); @@ -388,6 +441,9 @@ void prot_action(Chan *chan, char *from, ChanUser *doer, char *target, ChanUser uprot = get_protaction(chan,target); } + /* dont enforce protection levels higher than channel is set to */ + if (maxprot < uprot) uprot = maxprot; + if ((uprot >= 4) && (!(doer->flags & CU_BANNED))) { doer->flags |= CU_BANNED|CU_DEOPPED; @@ -442,12 +498,12 @@ void check_dynamode(Chan *chan) } } v[0] = (v[0] < 20) ? 20 : (v[0] > 600) ? 600 : v[0]; - if ((now - chan->lastlimit) < v[0]) + if ((cx.now - chan->lastlimit) < v[0]) return; v[1] = (v[1] < 5) ? 5 : (v[1] > 50) ? 50 : v[1]; v[2] = (v[2] < 1) ? 1 : (v[2] > 50) ? 50 : v[2]; - chan->lastlimit = now; + chan->lastlimit = cx.now; n = 0; for(cu=chan->users;cu;cu=cu->next) @@ -494,18 +550,18 @@ void process_chanbans(void) for (current=botlist;current;current=current->next) { - if (current->lastchanban > (now - 10)) + if (current->lastchanban > (cx.now - 10)) { #ifdef DEBUG debug("(process_chanbans) skipping %s (%i), (lastchanban (%lu) > now - 10 (%lu)\n", - current->nick,current->guid,current->lastchanban,(now - 10)); + getbotnick(current),current->guid,current->lastchanban,(cx.now - 10)); #endif /* DEBUG */ continue; } if (current->sendq) /* only do chanbans on empty queue */ { #ifdef DEBUG - debug("(process_chanbans) skipping %s (%i), sendq not empty\n",current->nick,current->guid); + debug("(process_chanbans) skipping %s (%i), sendq not empty\n",getbotnick(current),current->guid); #endif /* DEBUG */ continue; } @@ -530,11 +586,11 @@ void process_chanbans(void) } } - if (selcu && selcu->lastwhois < (now-30)) + if (selcu && selcu->lastwhois < (cx.now-30)) { selcu->flags &= ~CU_CHANBAN; - selcu->lastwhois = now; - current->lastchanban = now; + selcu->lastwhois = cx.now; + current->lastchanban = cx.now; pp = ¤t->sendq; while(*pp) @@ -659,7 +715,7 @@ void check_kicksay(Chan *chan, ChanUser *doer, char *text) mask = format_uh(get_nuh(doer),FUH_USERHOST); if (action > 2) { - add_shit("Auto KS",chan->name,mask,save->reason,2,now+3600); + add_shit("Auto KS",chan->name,mask,save->reason,2,cx.now+3600); } if (!(doer->flags & CU_BANNED)) { @@ -819,7 +875,7 @@ void do_unban(COMMAND_ARGS) if (((chan = find_channel_ac(to)) == NULL) || !chan->bot_is_op) return; - if (nick && STRCHR(nick,'*')) + if (nick && stringchr(nick,'*')) { channel_massunban(chan,nick,0); return; diff --git a/src/python.c b/src/python.c index 1b8ee35..7252698 100644 --- a/src/python.c +++ b/src/python.c @@ -88,11 +88,11 @@ static PyObject *python_getvar(PyObject *self, PyObject *args) case PYVAR_currentnick: return Py_BuildValue("s", CurrentNick); case PYVAR_botnick: - return Py_BuildValue("s", current && current->nick ? current->nick : ""); + return Py_BuildValue("s", current && getbotnick(current)); case PYVAR_wantnick: - return Py_BuildValue("s", current && current->wantnick ? current->wantnick : ""); + return Py_BuildValue("s", current && getbotwantnick(current)); case PYVAR_userhost: - return Py_BuildValue("s", current && current->userhost ? current->userhost : ""); + return Py_BuildValue("s", current && getbotuserhost(current)); case PYVAR_server: return Py_BuildValue("i", current && current->server ? current->server : -1); case PYVAR_nextserver: diff --git a/src/reset.c b/src/reset.c index f3ed471..1e173ab 100644 --- a/src/reset.c +++ b/src/reset.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 1997-2018 proton + Copyright (c) 1997-2025 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 @@ -27,11 +27,13 @@ #include "h.h" #ifdef TELNET -LS int client_type = DCC_ACTIVE; + +int client_type = DCC_ACTIVE; + #endif /* TELNET */ -#define mkaxx(x) (0x40404040 + (0x0f0f & x) + ((0xf0f0 & x) << 12)) -#define getaxx(x) (((x & 0x0f0f0000) >> 12) | (x & 0x00000f0f)) +#define simpleencode(x) (0x41414141 + (0x0f0f & x) + ((0xf0f0 & x) << 12)) +#define simpledecode(x) ((((x - 0x41410000) & 0x0f0f0000) >> 12) | ((x - 0x4141) & 0x0f0f)) char *recover_client(char *env) { @@ -40,17 +42,18 @@ char *recover_client(char *env) char asc[8]; } axx; struct sockaddr_in sai; + unsigned int sz; Client *client; User *user; char *p,*handle; - int guid = 0,fd = 0,sz; + int guid = 0,fd = 0; if (env[8] != ':') return(env); memcpy(axx.asc,env,8); /* compiler is not stupid and will optimize the shit out of this */ - guid = getaxx(axx.num[0]); - fd = getaxx(axx.num[1]); + guid = simpledecode(axx.num[0]); + fd = simpledecode(axx.num[1]); handle = p = (env = env + 9); while(*p) @@ -97,7 +100,7 @@ char *recover_client(char *env) found_user: if (to_file(fd,"[%s] [%s] %s[%i] has connected (reset recover)\n", - time2medium(now),current->wantnick,handle,user->x.x.access) < 0) + maketimestr(cx.now,TFMT_CLOCK),getbotwantnick(current),handle,user->x.x.access) < 0) { close(fd); return(p); @@ -112,7 +115,7 @@ found_user: #else client->flags = DCC_ACTIVE; #endif /* TELNET */ - client->lasttime = now; + client->lasttime = cx.now; client->next = current->clientlist; current->clientlist = client; @@ -121,7 +124,7 @@ found_user: { CurrentDCC = client; stringcpy(client->sockdata,"status"); - do_spy(user->name,current->wantnick,client->sockdata,0); + do_spy(user->name,getbotwantnick(current),client->sockdata,0); *client->sockdata = 0; CurrentDCC = NULL; } @@ -142,16 +145,16 @@ char *recover_debug(char *env) char asc[4]; } axx; struct stat s; + char *d; debug_fd = 0; + d = stringchr(env,'&'); - if (env[4] != ' ' && env[4] != 0) - return(env); /* * get the fd number */ memcpy(axx.asc,env,4); /* compiler is not stupid and will optimize the shit out of this */ - debug_fd = getaxx(axx.num); + debug_fd = simpledecode(axx.num); if (fstat(debug_fd,&s) < 0) { @@ -164,17 +167,19 @@ char *recover_debug(char *env) dodebug = TRUE; debug("(recover_debug) {%i} debug fd recovered\n",debug_fd); CoreClient.sock = debug_fd; + if (d && is_safepath(d+1,FILE_MAY_EXIST) == TRUE) + { + debugfile = d+1; + debug("(recover_debug) output file = %s\n",debugfile); + } } - return(env+4); + d = chop(&env); + return(env); } #endif /* DEBUG */ /* -(do_reset) mkaxx(3) = C@@@ -(do_reset) ircx mkaxx(12) = L@@@ -(do_reset) sock mkaxx(2) = B@@@ -(do_reset) guid mkaxx(1881) = IGE@ [StS] {2} PING :OT1523818405 (do_reset) MECHRESET=dC@@@ fXIGE@B@@@L@@@ tIGE@F@@@:joo [44] execve( ./energymech, argv = { ./energymech }, envp = { MECHRESET=dC@@@ fXIGE@B@@@L@@@ tIGE@F@@@:joo } ) @@ -187,8 +192,8 @@ char *recover_server(char *env) char asc[16]; } axx; struct sockaddr_in sai; - char *p; - int guid = 0,fd = 0,sz; + unsigned int sz; + int guid = 0,fd = 0; #ifdef IRCD_EXTENSIONS int ircx = 0; #endif /* IRCD_EXTENSIONS */ @@ -209,10 +214,10 @@ char *recover_server(char *env) memcpy(axx.asc,env,sz); /* compiler is not stupid and will optimize the shit out of this */ env += sz; - guid = getaxx(axx.num[0]); - fd = getaxx(axx.num[1]); + guid = simpledecode(axx.num[0]); + fd = simpledecode(axx.num[1]); #ifdef IRCD_EXTENSIONS - ircx = getaxx(axx.num[2]); + ircx = simpledecode(axx.num[2]); #ifdef DEBUG debug("(recover_server) guid = %i; fd = %i, ircx = %i\n",guid,fd,ircx); #endif /* DEBUG */ @@ -235,7 +240,7 @@ char *recover_server(char *env) current->reset = 1; current->sock = fd; current->connect = CN_ONLINE; - current->ontime = now; + current->ontime = cx.now; #ifdef IRCD_EXTENSIONS current->ircx_flags = ircx; #endif /* IRCD_EXTENSIONS */ @@ -251,7 +256,7 @@ char *recover_server(char *env) /* 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"); + to_file(fd,"QUIT :Am I a figment of my own imagination?\n"); killsock(fd); } return(env); @@ -314,9 +319,8 @@ void do_reset(COMMAND_ARGS) } axx; Client *client; Mech *backup; - char env[MSGLEN]; - char *p; - int n,sz; + char *p,env[MSGLEN]; + int sz; if (current->userlist && current->ul_save) { @@ -350,10 +354,12 @@ void do_reset(COMMAND_ARGS) */ if (dodebug && (debug_fd >= 0)) { - axx.num[0] = mkaxx(debug_fd); + axx.num[0] = simpleencode(debug_fd); axx.num[1] = 0; - sprintf(p,"d%s",axx.asc); - p = STREND(p); + if (debugfile) + p += sprintf(p,"d%s&%s",axx.asc,debugfile); + else + p += sprintf(p,"d%s",axx.asc); } #endif /* DEBUG */ /* @@ -365,17 +371,14 @@ void do_reset(COMMAND_ARGS) if ((current->connect == CN_ONLINE) && ((MSGLEN - (p - env)) > 25)) { unset_closeonexec(current->sock); - axx.num[0] = mkaxx(current->guid); - axx.num[1] = mkaxx(current->sock); -#ifdef IRCD_EXTENSIONS - axx.num[2] = mkaxx(current->ircx_flags); - axx.num[3] = 0; - sprintf(p," fX%s",axx.asc); -#else /* IRCD_EXTENSIONS */ + axx.num[0] = simpleencode(current->guid); + axx.num[1] = simpleencode(current->sock); axx.num[2] = 0; - sprintf(p," fx%s",axx.asc); + axx.num[3] = 0; +#ifdef IRCD_EXTENSIONS + axx.num[2] = simpleencode(current->ircx_flags); #endif /* IRCD_EXTENSIONS */ - p = STREND(p); + p += sprintf(p," fX%s",axx.asc); to_server("PING :OT%lu\n",current->ontime); } for(client=current->clientlist;client;client=client->next) @@ -391,16 +394,15 @@ void do_reset(COMMAND_ARGS) if ((MSGLEN - (p - env)) > sz) { unset_closeonexec(client->sock); - axx.num[0] = mkaxx(current->guid); - axx.num[1] = mkaxx(client->sock); + axx.num[0] = simpleencode(current->guid); + axx.num[1] = simpleencode(client->sock); axx.num[2] = 0; #ifdef TELNET - sprintf(p,(client->flags & DCC_TELNET) ? " t%s:%s" : " c%s:%s", + p += sprintf(p,(client->flags & DCC_TELNET) ? " t%s:%s" : " c%s:%s", axx.asc,client->user->name); #else - sprintf(p," c%s:%s",axx.asc,client->user->name); + p += sprintf(p," c%s:%s",axx.asc,client->user->name); #endif /* TELNET */ - p = STREND(p); } } } diff --git a/src/seen.c b/src/seen.c index dbc2622..8640e9c 100644 --- a/src/seen.c +++ b/src/seen.c @@ -44,7 +44,7 @@ #define NF_OPTIONS 7 -LS const char notify_opt[NF_OPTIONS][10] = +const char notify_opt[NF_OPTIONS][10] = { "-ALL", "-NOMATCH", @@ -53,9 +53,9 @@ LS const char notify_opt[NF_OPTIONS][10] = "-SEEN", }; -LS Notify **endoflist; -LS int lock_ison = FALSE; -LS int nf_header; +Notify **endoflist; +int lock_ison = FALSE; +int nf_header; void purge_notify(void) { @@ -142,11 +142,11 @@ void send_ison(void) * dont send nicks to ISON too often */ period = current->setting[INT_ISONDELAY].int_var; - x = now - current->lastnotify; + x = cx.now - current->lastnotify; if ((x < period) || (lock_ison && (x < 600))) return; - current->lastnotify = now; + current->lastnotify = cx.now; /* * the nature of the code makes it so that the first NULL is @@ -206,7 +206,7 @@ void catch_ison(char *rest) { if (!nickcmp(nf->nick,nick)) { - nf->checked = now; + nf->checked = cx.now; /* * /whois user to get user@host + realname */ @@ -228,14 +228,14 @@ void catch_ison(char *rest) { if (nf->checked == 1) { - nf->checked = now; + nf->checked = cx.now; if (nf->status >= NF_WHOIS) { /* * close the log entry for this online period */ if (nf->log && nf->log->signon && !nf->log->signoff) - nf->log->signoff = now; + nf->log->signoff = cx.now; /* * announce that the user is offline if its a mask match */ @@ -264,7 +264,7 @@ void catch_whois(char *nick, char *userhost, char *realname) */ set_mallocdoer(catch_whois); nlog = (nfLog*)Calloc(sizeof(nfLog) + Strlen2(userhost,realname)); // realname is never NULL - nlog->signon = now; + nlog->signon = cx.now; nlog->next = nf->log; nf->log = nlog; nlog->realname = stringcat(nlog->userhost,userhost) + 1; @@ -390,7 +390,7 @@ void write_notifylog(void) for(nlog=nf->log;nlog;nlog=nlog->next) { to_file(fd,"%s %lu %lu %s :%s\n",nf->nick,nlog->signon, - (nlog->signoff) ? nlog->signoff : now, + (nlog->signoff) ? nlog->signoff : cx.now, nlog->userhost,nlog->realname); } } @@ -466,7 +466,7 @@ int notify_callback(char *rest) { nf->mask = dst + 1; dst = stringcat(nf->mask,rest); - if (STRCHR(nf->mask,' ')) + if (stringchr(nf->mask,' ')) nf->endofmask = dst; } if (src) @@ -530,7 +530,7 @@ void nfshow_brief(Notify *nf) if (nf->log && nf->log->signoff) { s = mem; - when = now - nf->log->signoff; + when = cx.now - nf->log->signoff; d = when / 86400; h = (when -= d * 86400) / 3600; m = (when -= h * 3600) / 60; @@ -565,7 +565,7 @@ void nfshow_full(Notify *nf) for(nlog=nf->log;nlog;nlog=nlog->next) { opt = mem; - s = time2away(nlog->signon); + s = maketimestr(nlog->signon,TFMT_AWAY); if (s[1] == ':') *(opt++) = ' '; *opt = 0; @@ -576,7 +576,7 @@ void nfshow_full(Notify *nf) opt = stringcat(opt," -- "); if (nlog->signoff) { - s = time2away(nlog->signoff); + s = maketimestr(nlog->signoff,TFMT_AWAY); if (s[1] == ':') *(opt++) = ' '; *opt = 0; @@ -654,7 +654,7 @@ int write_seenlist(void) for(seen=seenlist;seen;seen=seen->next) { - if ((seen->when - now) > (86400 * SEEN_TIME)) + if ((seen->when - cx.now) > (86400 * SEEN_TIME)) continue; else { @@ -696,7 +696,7 @@ int read_seenlist_callback(char *rest) pa = chop(&rest); pb = rest; - if ((now - when) < (SEEN_TIME * 86400)) + if ((cx.now - when) < (SEEN_TIME * 86400)) { /* if (pa && !*pa) pa = NULL; chop() doesnt return empty strings */ @@ -826,12 +826,10 @@ void do_seen(COMMAND_ARGS) { Seen *seen; char ago[35]; /* enought for "36500 days, 23 hours and 59 minutes" (100 years) */ - const char *chan; char *fmt,*n,*u,*c1,*c2,*c3; time_t when; int d,h,m,mul; - chan = get_channel(to,&rest); mul = get_maxaccess(from); if (!*rest) @@ -847,7 +845,7 @@ void do_seen(COMMAND_ARGS) return; } - if (!nickcmp(n,current->nick)) + if (!nickcmp(n,getbotnick(current))) { fmt = "%s is me you dweeb!"; } @@ -870,7 +868,7 @@ void do_seen(COMMAND_ARGS) } else { - when = now - seen->when; + when = cx.now - seen->when; d = when / 86400; h = (when -= d * 86400) / 3600; m = (when -= h * 3600) / 60; @@ -985,7 +983,7 @@ void do_notify(COMMAND_ARGS) #ifdef DEBUG debug("(do_notify) dumping errnames\n"); #endif /* DEBUG */ - to_user(from,"User%s not found: %s",(STRCHR(message,',')) ? "s" : "",message); + to_user(from,"User%s not found: %s",(stringchr(message,',')) ? "s" : "",message); } if (nf_header) diff --git a/src/settings.h b/src/settings.h index 94ed125..4196a0b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -24,7 +24,7 @@ #define DEFAULTCMDCHAR '-' -#define ZERO 0 +#define ZERO .v.num=0 #define INTCAST(x) .v.num=x #define CMDCHAR .v.chr=DEFAULTCMDCHAR #define VNULL .v.str=NULL @@ -33,7 +33,7 @@ #define INTPROC(x) .v.numptr=&x #define STRPROC(x) .v.strptr=&x -LS const Setting VarName[SIZE_VARS] = +const Setting VarName[SIZE_VARS] = { /* * all channel settings in the beginning diff --git a/src/shit.c b/src/shit.c index 7b5ae14..d942cd7 100644 --- a/src/shit.c +++ b/src/shit.c @@ -58,7 +58,7 @@ void shit_action(Chan *chan, ChanUser *cu) send_mode(chan,90,QM_RAWMODE,'+','b',shit->mask); fromnick = nickcpy(NULL,shit->from); - send_kick(chan,nick,"%s %s: %s",time2small(shit->time),fromnick, + send_kick(chan,nick,"%s %s: %s",maketimestr(shit->time,TFMT_DATE),fromnick, (shit->reason) ? shit->reason : "GET THE HELL OUT!!!"); return; } @@ -140,7 +140,7 @@ Shit *add_shit(char *from, char *chan, char *mask, char *reason, int axs, int ex shit = (Shit*)Calloc(sizeof(Shit) + StrlenX(from,chan,mask,reason,NULL)); shit->action = axs; - shit->time = now; + shit->time = cx.now; shit->expire = expire; shit->next = current->shitlist; @@ -177,7 +177,7 @@ Shit *find_shit(const char *userhost, const char *channel) } } } - if (save && save->expire < now) + if (save && save->expire < cx.now) { remove_shit(save); save = NULL; @@ -201,7 +201,7 @@ Shit *get_shituser(char *userhost, char *channel) */ if (!current->shitlist) return(NULL); - if (!nickcmp(current->nick,userhost)) + if (!nickcmp(getbotnick(current),userhost)) return(NULL); for(chan=current->chanlist;chan;chan=chan->next) { @@ -332,10 +332,10 @@ void do_shit(COMMAND_ARGS) #ifdef DEBUG debug("(do_shit) adding %s to %s (Level %i)\n",nuh,channel,shitlevel); #endif /* DEBUG */ - add_shit(from,channel,nuh,rest,shitlevel,now + days); + add_shit(from,channel,nuh,rest,shitlevel,cx.now + days); to_user(from,TEXT_HASSHITTED,nuh,channel); - to_user(from,TEXT_SHITEXPIRES,time2str(now + days)); + to_user(from,TEXT_SHITEXPIRES,maketimestr(cx.now + days,TFMT_FULL)); check_shit(); } @@ -390,7 +390,7 @@ void do_shitlist(COMMAND_ARGS) for(shit=current->shitlist;shit;shit=shit->next) { table_buffer(FMT_6XSTRTAB,shit->chan,shit->mask,shit_actions[shit->action], - nickcpy(NULL,shit->from),shit->reason,time2away(shit->expire)); + nickcpy(NULL,shit->from),shit->reason,maketimestr(shit->expire,TFMT_AWAY)); } table_send(from,2); } diff --git a/src/spy.c b/src/spy.c index 633a82c..67107a1 100644 --- a/src/spy.c +++ b/src/spy.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2024 proton + Parts Copyright (c) 1997-2025 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 @@ -34,7 +34,7 @@ #ifdef DEBUG -LS const char SPY_DEFS[][12] = +const char SPY_DEFS[][12] = { "SPY_FILE", "SPY_CHANNEL", @@ -50,27 +50,10 @@ LS const char SPY_DEFS[][12] = #endif /* DEBUG */ -static int basepos(char c) -{ -/* - -lcrypt converts to [a-zA-Z0-9./] - included sha1 converts to hex - included md5 converts to [./0-9A-Za-z] -*/ - if (c >= 'a' && c <= 'z') - return(c - 'a'); - if (c >= 'A' && c <= 'Z') - return(c - 'A' + 26); - if (c >= '0' && c <= '9') - return(c - '0' + 52); - if (c == '.') - return(62); - if (c == '/') - return(63); - return(0); -} #if defined(SHACRYPT) || defined(MD5CRYPT) + char *CRYPT_FUNC(const char *, const char *); + #endif void send_spy(const char *src, const char *format, ...) @@ -79,83 +62,95 @@ void send_spy(const char *src, const char *format, ...) Mech *backup; Spy *spy; va_list msg; - const char *tempsrc; + const char *spysrc; const char *printmsg; - char tempdata[MAXLEN],*rnd,*dst,*end; - int fd,a,b,c,d; - int printed = FALSE; + char tempdata[MAXLEN]; + int fd; - if (src == SPYSTR_RAWIRC) - { - tempsrc = printmsg = format; - printed = TRUE; - format = FMT_PLAIN; - } - else - if (src == SPYSTR_STATUS) - { - tempsrc = time2medium(now); - } - else - { - tempsrc = src; - } + printmsg = (src == SPYSTR_RAWIRC) ? format : NULL; #ifdef DEBUG + if (src != SPYSTR_RAWIRC) /* too much debug spam */ debug("(send_spy) src <%s> format = '%s', current = '%s' (%i)\n",src,format, - (current == NULL) ? "" : nullstr(current->nick),(current == NULL) ? -1 : current->guid); + (current == NULL) ? "" : getbotnick(current),(current == NULL) ? -1 : current->guid); #endif /* DEBUG */ for(spy=current->spylist;spy;spy=spy->next) { + /* + * Dont support RANDSRC unless there is a good hashing function to + * create high quality randomness. + */ +#if defined(SHACRYPT) || defined(MD5CRYPT) if (spy->t_src == SPY_RANDSRC) { + char mysalt[16],mydata[128]; + char *rnd,*dst,*end; + if (src != SPYSTR_RAWIRC) continue; + if (spy->data.delay > cx.now) + continue; /* dont use four-char server messages such as "PING :..." */ - if (tempsrc[5] == ':') -#ifdef DEBUG - { - debug("(send_spy) RANDSRC: skipping four-char server message\n"); -#endif /* DEBUG */ + if (format[5] == ':') continue; -#ifdef DEBUG - } -#endif /* DEBUG */ + /* create delay until next */ + spy->data.delay = cx.now + 20 + RANDOM(0,29); /* make it unpredictable which messages will be sourced */ - if (spy->data.delay > now) - continue; - spy->data.delay = now + 10 + RANDOM(0,9); /* make it unpredictable which messages will be sourced */ - -/* - $6$ for sha512, $1$ for MD5 - MD5 | 22 characters - SHA-512 | 86 characters -*/ + sprintf(mysalt, #ifdef SHACRYPT - sprintf(tempdata,"$6$%04x",(uint32_t)(now & 0xFFFF)); - rnd = CRYPT_FUNC(tempsrc,tempdata); + "$6$%04x", +#else + "$1$%04x", #endif /* SHACRYPT */ + (uint32_t)(cx.now & 0xFFFF)); -#if !defined(SHACRYPT) && defined(MD5CRYPT) - sprintf(tempdata,"$1$%04x",(uint32_t)(now & 0xFFFF)); - rnd = CRYPT_FUNC(tempsrc,tempdata); -#endif /* !SHACRYPT && MD5CRYPT */ + /* SHA512 internal returns NULL if strlen(format) > 256 */ + stringcpy_n(mydata,format,120); + + rnd = CRYPT_FUNC(mydata,mysalt); dst = tempdata; end = STREND(rnd); -#if defined(SHACRYPT) || defined(MD5CRYPT) rnd += 8; /* skip salt */ -#endif - while(rnd < (end - 3)) + + while(rnd < (end - 4)) { + union WordtoBytes + { + uint32_t m; + uint8_t b[4]; + } m32; + uint32_t n, o, p; + int a,b,c,d; + + m32.m = *((uint32_t*)rnd); + + /* + * branchless bit operations to do 4 bytes at a time + * if input is not base64, the output is undefined + */ + n = (((m32.m - 0x3a3a3a3a) & 0x80808080) >> 7) * 7; + o = (((m32.m - 0x5b5b5b5b) & 0x80808080) >> 7) * 6; + p = (((m32.m - 0x7b7b7b7b) & 0x80808080) >> 7) * 6; + + m32.m = m32.m - 0x41414141 + n + o + p; + + a = m32.b[0]; + b = m32.b[1]; + c = m32.b[2]; + d = m32.b[3]; + + /* + |..aaaaaa|..bbbbbb|..cccccc|..dddddd| + | |aaaaaa..|bbbbbb..|cccccc..| + | | ddddDD| + | ddDD|dd + DD|dddd | + */ /* base64 to bin, 4 chars to 3 */ - a = basepos(rnd[0]); - b = basepos(rnd[1]); dst[0] = (a << 2) | (b >> 4); /* aaaaaabb */ - c = basepos(rnd[2]); dst[1] = (b << 4) | (c >> 2); /* bbbbcccc */ - d = basepos(rnd[3]); dst[2] = (c << 6) | (d); /* ccdddddd */ dst += 3; rnd += 4; @@ -167,14 +162,14 @@ void send_spy(const char *src, const char *format, ...) #endif /* DEBUG */ if ((fd = open(spy->dest,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) >= 0) { - int n; - + int n __notused__; n = write(fd,tempdata,dst - tempdata); close(fd); } } continue; } +#endif /* defined(SHACRYPT) || defined(MD5CRYPT) */ if ((*src == '#' || *src == '*') && spy->t_src == SPY_CHANNEL) { @@ -184,7 +179,6 @@ void send_spy(const char *src, const char *format, ...) continue; if (find_chanuser(chan,CurrentNick) == NULL) continue; - tempsrc = spy->src; } else /* @@ -193,18 +187,25 @@ void send_spy(const char *src, const char *format, ...) if (spy->src != src) continue; - if (!printed) + if (spy->t_src == SPY_STATUS) + { + spysrc = maketimestr(cx.now,TFMT_CLOCK); + } + else + spysrc = spy->src; + + if (printmsg == NULL) { - printed = TRUE; va_start(msg,format); vsprintf(tempdata,format,msg); va_end(msg); printmsg = tempdata; } + switch(spy->t_dest) { case SPY_DCC: - to_file(spy->data.dcc->sock,"[%s] %s\n",tempsrc,printmsg); + to_file(spy->data.dcc->sock,"[%s] %s\n",spysrc,printmsg); break; case SPY_CHANNEL: if (spy->data.destbot >= 0) @@ -214,7 +215,7 @@ void send_spy(const char *src, const char *format, ...) { if (current->guid == spy->data.destbot) { - to_server("PRIVMSG %s :[%s] %s\n",spy->dest,tempsrc,printmsg); + to_server("PRIVMSG %s :[%s] %s\n",spy->dest,spysrc,printmsg); break; } } @@ -222,13 +223,13 @@ void send_spy(const char *src, const char *format, ...) } else { - to_user(spy->dest,"[%s] %s",tempsrc,printmsg); + to_user(spy->dest,"[%s] %s",spysrc,printmsg); } break; case SPY_FILE: if ((fd = open(spy->dest,O_WRONLY|O_CREAT|O_APPEND,NEWFILEMODE)) >= 0) { - to_file(fd,"[%s] %s\n",logtime(now),printmsg); + to_file(fd,"[%s] %s\n",maketimestr(cx.now,TFMT_LOG),printmsg); close(fd); } } @@ -325,7 +326,7 @@ int begin_redirect(char *from, char *args) if (!args) return(0); - pt = STRCHR(args,'>'); + pt = stringchr(args,'>'); if (pt) { *pt = 0; @@ -427,7 +428,7 @@ void send_redirect(char *message) Mech *backup; /* PM */ - sprintf(tempdata,"%i %s %s %s",redirect.guid,redirect.to,current->nick,message); + sprintf(tempdata,"%i %s %s %s",redirect.guid,redirect.to,getbotnick(current),message); backup = current; partyMessage(NULL,tempdata); current = backup; @@ -462,10 +463,10 @@ void end_redirect(void) #ifdef URLCAPTURE -char *urlhost(const char *url) +void urlhost(const char *url) { char copy[strlen(url)]; - const char *end,*beg,*dst; + const char *end,*beg; int n = 0; beg = end = url; @@ -493,7 +494,7 @@ char *urlhost(const char *url) void urlcapture(const char *rest) { - Strp *sp,*nx; + Strp *sp; char *dest,url[MSGLEN]; int n; @@ -538,7 +539,7 @@ void stats_loghour(Chan *chan, char *filename, int hour) if (!(stats = chan->stats)) return; - when = (now - (now % 3600)); + when = (cx.now - (cx.now % 3600)); if ((fd = open(filename,O_WRONLY|O_APPEND|O_CREAT,NEWFILEMODE)) >= 0) { @@ -567,16 +568,16 @@ void stats_plusminususer(Chan *chan, int plusminus) stats->users++; stats->userpeak = stats->users; stats->userlow = stats->users; - stats->lastuser = now; + stats->lastuser = cx.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->userseconds += stats->users * (cx.now - stats->lastuser); - stats->lastuser = now; + stats->lastuser = cx.now; stats->users += plusminus; /* can be both negative (-1), zero (0) and positive (+1) */ if (stats->userpeak < stats->users) @@ -769,7 +770,7 @@ spy_dest_ok: debug("(do_spy) src = `%s'; t_src = %i (%s); dest = `%s'; t_dest = %i (%s), CurrentDCC "mx_pfmt"\n", src,t_src,SPY_DEFS[t_src-1],nullstr(dest),t_dest,SPY_DEFS[t_dest-1],CurrentDCC); if (guid >= 0) - debug("(do_spy) spying from remote bot guid %i (%s), channel %s\n",guid,(destbot) ? destbot->nick : "unknown",src); + debug("(do_spy) spying from remote bot guid %i (%s), channel %s\n",guid,(destbot) ? getbotnick(destbot) : "unknown",src); #endif /* DEBUG */ if (t_dest == SPY_DCC) @@ -1028,8 +1029,7 @@ void do_info(COMMAND_ARGS) { ChanStats *stats; Chan *chan; - char *p; - char text[MSGLEN]; + char modes[128]; uint32_t avg; if (current->chanlist == NULL) @@ -1037,39 +1037,34 @@ void do_info(COMMAND_ARGS) to_user(from,ERR_NOCHANNELS); return; } - to_user(from,"\037channel\037 " - "\037average\037 \037peak\037 \037low\037"); + table_buffer(str_underline("Channel") "\t" str_underline("Statistics") "\t"); + 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)) + stats = chan->stats; + if (stats == NULL) { - 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,"%-7u %-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); + table_buffer("%s (no current data)",chan->name); + continue; } + + if (stats->LHuserseconds > 0) + avg = stats->LHuserseconds / (60*60); else - { - stringcpy(p," (no current data)"); - } - to_user(from,FMT_PLAIN,text); + avg = (stats->userpeak + stats->userlow) / 2; + + chan_modestr(chan,modes); + + table_buffer("%s%s%s\tUsers:\tAvg\t%u\tPeak\t%i\tLow\t%i", + chan->name,(chan == current->activechan) ? " (current)" : EMPTYSTR, + (stats->flags == CSTAT_PARTIAL) ? " (partial)" : EMPTYSTR, + avg,stats->userpeak,stats->userlow); + table_buffer("Modes: %s\tMessages:\t\t%i\tNotices:\t%i\tJoins:\t%i",modes, + stats->privmsg,stats->notice,stats->joins); + table_buffer("\tParts:\t\t%i\tKicks:\t%i\tQuits:\t%i", + stats->parts,stats->kicks,stats->quits); } + table_send(from,2); } #endif /* STATS */ diff --git a/src/lib/string.c b/src/string.c similarity index 91% rename from src/lib/string.c rename to src/string.c index 2f8f7f3..fc6d7e3 100644 --- a/src/lib/string.c +++ b/src/string.c @@ -34,24 +34,25 @@ char *chop(char **src) { char *tok,*cut = *src; - while(*cut && *cut == ' ') + /* skip leading spaces */ + while(*cut == ' ') cut++; - if (*cut) - { - tok = cut; - while(*cut && *cut != ' ') - cut++; - *src = cut; - while(*cut && *cut == ' ') - cut++; - **src = 0; - *src = cut; - } - else - { - tok = NULL; - } + if (*cut == 0) + return(NULL); + + tok = cut; + while(*cut && *cut != ' ') + cut++; + *src = cut; + + /* skip more spaces */ + while(*cut == ' ') + cut++; + + **src = 0; + cx.chop_end = *src = cut; + return(tok); } @@ -132,17 +133,6 @@ void stringcpy_n(char *dst, const char *src, int sz) n++; } dst[n] = 0; -/* - char *stop = dst + sz - 1; - - while(*src) - { - *(dst++) = *(src++); - if (dst == stop) - break; - } - *dst = 0; -*/ } char *stringcpy(char *dst, const char *src) diff --git a/src/structs.h b/src/structs.h index 1ba6e6f..d216cda 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2020 proton + Parts Copyright (c) 1997-2025 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 @@ -21,35 +21,40 @@ #ifndef STRUCTS_H #define STRUCTS_H 1 -typedef union usercombo +typedef struct Strp { - struct - { - uint32_t access:8, /* access level (0-200) [0-255] */ - prot:3, /* protlevel (0-4) [0-7] */ -#ifdef BOTNET - noshare:1, /* dont share this user over botnet */ - readonly:1, /* botnet cannot alter this user */ -#endif /* BOTNET */ -#ifdef GREET - greetfile:1, /* greeting is filename */ - randline:1, /* grab random line from filename */ -#endif /* GREET */ -#ifdef BOUNCE - bounce:1, /* user has access to bouncer */ -#endif /* BOUNCE */ - echo:1, /* partyline echo of own messages */ - aop:1, /* auto-opping */ - avoice:1; /* auto-voicing */ - } x; - uint32_t comboflags; + struct Strp *next; + char p[1]; -} usercombo; +} Strp; + +typedef struct Mix16 +{ + union + { + char string[16]; + char *ptr; + } x; + int8_t opt; + +} Mix16; + +typedef struct Mix64 +{ + union + { + char string[64]; + char *ptr; + } x; + int8_t opt; + +} Mix64; typedef struct OnMsg { const char *name; void (*func)(char *, const char *, char *, const int); + void (*noargfunc)(const char *); uint32_t defaultaccess:8, /* defaultaccess */ dcc:1, cc:1, @@ -63,15 +68,14 @@ typedef struct OnMsg lbuf:1, cbang:1, acchan:1, - supres:1; /* -- 21 bits */ + supres:1, /* -- 21 bits */ + noargf:1; /* -- 22 bits */ const char *cmdarg; } OnMsg; typedef unsigned char OnMsg_access; -#ifndef GENCMD_C - typedef struct ircLink { struct ircLink *next; @@ -88,10 +92,6 @@ typedef struct ircLink char *nick; /* which nick to speak to */ char *handle; -#ifdef IDWRAP - char *idfile; -#endif /* IDWRAP */ - char servmem[MSGLEN]; char usermem[MSGLEN]; @@ -106,12 +106,7 @@ typedef struct typedef struct DEFstruct { - union - { - int id; - void *func; - - } v; + int id; char *idstr; } DEFstruct; @@ -120,6 +115,7 @@ typedef struct Alias { struct Alias *next; + int hash; char *format; char alias[1]; @@ -206,19 +202,12 @@ typedef struct Setting char **strptr; } v; - char *name; + char name[16]; int max; - void (*func)(const struct Setting *); + void (*onchangefunc)(const struct Setting *); } Setting; -typedef struct Strp -{ - struct Strp *next; - char p[1]; - -} Strp; - typedef struct KickSay { struct KickSay *next; @@ -252,6 +241,28 @@ typedef struct Shit } Shit; +typedef union usercombo +{ + struct + { + /* dont gatekeep these flags with ifdefs, + make userfiles compatible between different compiles */ + uint32_t access:8, /* access level (0-200) [0-255] */ + prot:3, /* protlevel (0-4) [0-7] */ + noshare:1, /* dont share this user over botnet */ + readonly:1, /* botnet cannot alter this user */ + greetfile:1, /* greeting is filename */ + randline:1, /* grab random line from filename */ + bounce:1, /* user has access to bouncer */ + echo:1, /* partyline echo of own messages */ + aop:1, /* auto-opping */ + avoice:1; /* auto-voicing */ + } x; + uint32_t comboflags; + +} usercombo; + +#ifndef GENCMD_C /* * this struct is put to use in global.h @@ -491,34 +502,33 @@ typedef struct Spy } Spy; +typedef struct sockaddr_in sai_v4; +typedef struct sockaddr_in6 sai_v6; + typedef struct Server { struct Server *next; int ident; int usenum; - int servergroup; int port; int err; time_t lastconnect; time_t lastattempt; time_t maxontime; + char ipv; + union { + sai_v4 ipv4; + sai_v6 ipv6; + } resolved; char realname[NAMEBUF]; char name[NAMEBUF]; - char pass[PASSLEN]; + char pass[PASSBUF]; + char group[SERVERGROUPBUF]; } Server; -typedef struct ServerGroup -{ - struct ServerGroup *next; - - int servergroup; - char name[1]; - -} ServerGroup; - typedef struct FileMon { struct FileMon *next; @@ -535,6 +545,7 @@ typedef struct Mech uint16_t guid; /* globally uniqe ID */ int connect; int sock; + char ipv; /* ip version */ struct in_addr ip; /* for DCC */ int server; /* ident of my current server */ int nextserver; @@ -553,9 +564,10 @@ typedef struct Mech /* * Basic bot information */ - char *nick; /* current nickname */ - char *wantnick; /* wanted nickname */ - char *userhost; + Mix16 nick; + Mix16 wantnick; + Mix64 userhost; + int vhost_type; uint32_t reset:1, @@ -582,33 +594,31 @@ typedef struct Mech #endif /* NOTIFY */ time_t lastreset; /* last time bot was reset */ + time_t ontime; /* how long the bot has been connected */ time_t lastantiidle; /* avoid showing large idle times */ + time_t activity; /* Away timer (AAWAY) */ time_t lastrejoin; /* last time channels were reset */ #ifdef CHANBAN time_t lastchanban; /* last time a chanban check was run */ #endif /* CHANBAN */ - time_t conntry; /* when connect try started */ /* re-used for server activity once connected */ int heartbeat; /* handle server timeout stuff */ - time_t activity; /* Away timer (AAWAY) */ - - time_t ontime; /* how long the bot has been connected */ #ifdef IRCD_EXTENSIONS int ircx_flags; #endif /* IRCD_EXTENSIONS */ +#ifdef DEBUG + char *inject; +#endif /* DEBUG */ + /* * Buffers for do_die() command. */ char *signoff; char *from; -#ifdef IDWRAP - char *identfile; -#endif /* IDWRAP */ - /* big buffers at the end */ UniVar setting[SIZE_VARS]; /* global vars + channel defaults */ char modes[32]; @@ -698,8 +708,8 @@ typedef struct BotNet { uint32_t pta:1, /* plain text auth */ sha:1, /* SHA */ - md5:1; /* MD5 */ - + md5:1, /* MD5 */ + links_complete; /* All links shared to this bot */ } opt; Mech *controller; @@ -711,7 +721,6 @@ typedef struct BotNet time_t when; struct BotInfo *botinfo; - int list_complete; char sockdata[MSGLEN]; diff --git a/src/tcl.c b/src/tcl.c index 6f020a3..20d9d12 100644 --- a/src/tcl.c +++ b/src/tcl.c @@ -32,7 +32,7 @@ #include -LS Tcl_Interp *energymech_tcl = NULL; +Tcl_Interp *energymech_tcl = NULL; #define tclv_READ TCL_TRACE_READS #define tclv_WRITE TCL_TRACE_WRITES @@ -62,7 +62,7 @@ typedef struct Tcl_TVInfo } Tcl_TVInfo; -LS Tcl_TVInfo vinfolist[] = +Tcl_TVInfo vinfolist[] = { { TVINFO_pointer | TVINFO_CHAR, tclv_READ, "mech_currentnick", CurrentNick }, { TVINFO_guid | TVINFO_INT, tclv_READ, "mech_guid" }, @@ -99,7 +99,7 @@ char *tcl_var_read(Tcl_TVInfo *vinfo, Tcl_Interp *I, char *n1, char *n2, int fla rdata.i = (current) ? current->guid : -1; break; case TVINFO_nick: - rdata.c = (current) ? current->nick : "(undefined variable)"; + rdata.c = (current) ? getbotnick(current) : "(undefined variable)"; break; case TVINFO_wantnick: rdata.c = (current) ? current->wantnick : "(undefined variable)"; @@ -518,7 +518,7 @@ int tcl_dns(void *foo, Tcl_Interp *I, int objc, Tcl_Obj *CONST objv[]) * */ -LS struct +struct { char *cmdname; void *func; diff --git a/src/text.h b/src/text.h index 5680a30..03d8b02 100755 --- a/src/text.h +++ b/src/text.h @@ -25,14 +25,6 @@ * These are more or less globally used.. */ -/* -#define FMT_PLAIN "%s" -#define FMT_6XSTRTAB "%s\t%s\t%s\t%s\t%s\t%s" -#define FMT_4XSTRTAB "%s\t%s\t%s\t%s" -#define FMT_3XSTRTAB "%s\t%s\t%s" -*/ - -#define FMT_PLAINLINE "%s\n" #define MATCH_ALL "*" #define TEXT_NOTINSERVLIST "(not in serverlist)" @@ -80,8 +72,8 @@ #define TEXT_SERVERDELETED "Server has been deleted: %s:%i" #define TEXT_MANYSERVMATCH "Several entries for %s exists, please specify port also" /* do_core() */ -#define TEXT_CURRNICKWANT "Current nick\t%s (Wanted: %s) [guid #%i]" -#define TEXT_CURRNICKHAS "Current nick\t%s [guid #%i]" +#define TEXT_CURRNICKWANT "Current nick\t%s%s (Wanted: %s) [guid #%i]" +#define TEXT_CURRNICKHAS "Current nick\t%s%s [guid #%i]" #define TEXT_USERLISTSTATS "Users in userlist\t%i (%i Superuser%s, %i Bot%s)" #define TEXT_ACTIVECHANS "Active channels\t%s" #define TEXT_MOREACTIVECHANS "\t%s" @@ -91,11 +83,11 @@ #define TEXT_VHINACTIVE " - Inactive" #define TEXT_CURRSERVER "Current Server\t%s:%i" +#define TEXT_CURRSERVGRP "Current Server\t%s:%i @%s" #define TEXT_CURRSERVERNOT "Current Server\t" TEXT_NOTINSERVLIST #define TEXT_TRYNEWSERVER "Trying new server, brb..." #define TEXT_SWITCHSERVER "Switching servers..." #define TEXT_SERVERONTIME "Server Ontime\t%s" -#define TEXT_BOTMODES "Mode\t+%s" #define TEXT_CURRENTTIME "Current Time\t%s" #define TEXT_BOTSTARTED "Started\t%s" @@ -141,11 +133,11 @@ #define TEXT_CSWITCH " -c make core file instead of coredebug/reset\n" #define TEXT_HSWITCH " -h show this help\n" #define TEXT_VSWITCH " -v show EnergyMech version\n" -#define TEXT_ESWITCH " -e run a single command, then exit\n" -#define TEXT_TSWITCH " -t run normal startup, but exit right before going into main loop\n" +#define TEXT_ESWITCH " -e run a single command, then exit\n" +#define TEXT_TSWITCH " -t run normal startup, but exit right before going into main loop\n" #ifdef SHACRYPT -#define TEXT_PSWITCH1 " -p encrypt using the password hashing algorithm (SHA-512),\n" +#define TEXT_PSWITCH1 " -p encrypt using the password hashing algorithm (SHA),\n" #elif MD5CRYPT #define TEXT_PSWITCH1 " -p encrypt using the password hashing algorithm (MD5),\n" #else @@ -153,9 +145,8 @@ #endif #define TEXT_PSWITCH2 " output the result and then quit.\n" -#define TEXT_DSWITCH " -d start mech in debug mode\n" -#define TEXT_OSWITCH " -o write debug output to \n" -#define TEXT_XSWITCH " -X write a debug file before exit\n" +#define TEXT_DSWITCH " -d [file] start mech in debug mode, with an optional output file\n" +#define TEXT_XSWITCH " -x write a debug file before any exit\n" #define TEXT_HDR_VERS "EnergyMech %s, %s\n" #define TEXT_HDR_FEAT "Features: %s\n" diff --git a/src/toybox.c b/src/toybox.c index 2a1420e..3580026 100644 --- a/src/toybox.c +++ b/src/toybox.c @@ -46,20 +46,19 @@ #define DAY_IN_SECONDS (24*60*60) #define WEEK_IN_SECONDS (7*24*60*60) -LS TrivScore *lastwinner; -LS Chan *triv_chan = NULL; -LS Strp *triv_answers = NULL; -LS time_t triv_ask_time; -LS time_t triv_next_time = 0; -LS time_t triv_weektop10; -LS int triv_mode; -LS int triv_score; -LS int triv_streak; -LS int triv_halt_flag; +TrivScore *lastwinner; +Chan *triv_chan = NULL; +Strp *triv_answers = NULL; +time_t triv_ask_time; +time_t triv_weektop10; +int triv_mode; +int triv_score; +int triv_streak; +int triv_halt_flag; #endif /* TRIVIA */ -#define BIGSAY_DEFAULTFONT "default" +#define BIGSAY_DEFAULTFONT DEFAULTSTR #define FONT_EXTENSION ".bigchars" BigC *newchar; @@ -196,6 +195,7 @@ int read_bigcharset(char *fname) int read_ascii(char *rest) { to_user_q(global_from,FMT_PLAIN,rest); + return(0); } #ifdef TRIVIA @@ -216,7 +216,7 @@ void trivia_week_toppers(void) int i,x; chosen[0] = NULL; - week = (now + (3 * DAY_IN_SECONDS)) / WEEK_IN_SECONDS; + week = (cx.now + (3 * DAY_IN_SECONDS)) / WEEK_IN_SECONDS; for(su=scorelist;su;su=su->next) { @@ -269,7 +269,7 @@ void hint_one(void) src = triv_answers->p; while(*src) { - if (STRCHR(TRIV_METACHARS,*src)) + if (stringchr(TRIV_METACHARS,*src)) *(dst++) = *src; else *(dst++) = triv_qchar; @@ -306,7 +306,7 @@ void hint_two(void) while(*src) { - if (STRCHR(TRIV_METACHARS,*src)) + if (stringchr(TRIV_METACHARS,*src)) *(dst++) = *src; else *(dst++) = triv_qchar; @@ -343,7 +343,7 @@ void hint_three(void) while(*src) { - if (STRCHR(TRIV_METACHARS "aeiouyAEIOUY",*src)) + if (stringchr(TRIV_METACHARS "aeiouyAEIOUY",*src)) *(dst++) = *src; else *(dst++) = triv_qchar; @@ -364,7 +364,7 @@ void trivia_cleanup(void) Strp *ans; triv_mode = TRIV_WAIT_QUESTION; - triv_next_time = now + triv_qdelay; + triv_next_time = cx.now + triv_qdelay; while((ans = triv_answers)) { triv_answers = ans->next; @@ -389,7 +389,7 @@ void trivia_check(Chan *chan, char *rest) return; have_answer: - week = (now + (3 * DAY_IN_SECONDS)) / WEEK_IN_SECONDS; + week = (cx.now + (3 * DAY_IN_SECONDS)) / WEEK_IN_SECONDS; for(su=scorelist;su;su=su->next) { @@ -425,7 +425,7 @@ have_answer: to_server("PRIVMSG %s :Yes, %s! got the answer -> %s <- in %i seconds, and gets %i points!\n", triv_chan->name,CurrentNick,triv_answers->p, - (int)(now - triv_ask_time),triv_score); + (int)(cx.now - triv_ask_time),triv_score); if (su == lastwinner) { @@ -481,7 +481,7 @@ char *random_question(char *triv_rand) } entry; - if (STRCHR(triv_qfile,'/') || strlen(triv_qfile) > 100) /* really bad filenames... */ + if (stringchr(triv_qfile,'/') || strlen(triv_qfile) > 100) /* really bad filenames... */ return(NULL); stringcat(stringcpy(tmpname,"trivia/"),triv_qfile); @@ -497,7 +497,7 @@ char *random_question(char *triv_rand) #endif /* DEBUG */ stringcpy(triv_rand,tmpname); - if ((p = STRCHR(triv_rand,'.')) == NULL) + if ((p = stringchr(triv_rand,'.')) == NULL) p = STREND(triv_rand); stringcpy(p,".index"); @@ -545,7 +545,7 @@ stop_trivia: triv_chan = NULL; triv_next_time = 0; triv_halt_flag = FALSE; - short_tv &= ~TV_TRIVIA; + cx.short_tv &= ~TV_TRIVIA; return; } @@ -558,12 +558,12 @@ stop_trivia: goto bad_question; triv_score = (RANDOM(2,9) + RANDOM(2,10) + RANDOM(2,10)) / 3; - triv_ask_time = now; + triv_ask_time = cx.now; - if (now > (triv_weektop10 + 1200)) + if (cx.now > (triv_weektop10 + 1200)) { trivia_week_toppers(); - triv_weektop10 = now; + triv_weektop10 = cx.now; } to_server("PRIVMSG %s :%s\n",triv_chan->name,question); @@ -575,37 +575,34 @@ void trivia_tick(void) Chan *chan; Mech *bot; - if (triv_next_time && (now >= triv_next_time)) + for(bot=botlist;bot;bot=bot->next) { - for(bot=botlist;bot;bot=bot->next) + for(chan=bot->chanlist;chan;chan=chan->next) { - for(chan=bot->chanlist;chan;chan=chan->next) + if (triv_chan == chan) { - if (triv_chan == chan) + current = bot; + triv_next_time = cx.now + TRIV_HINT_DELAY; + switch(triv_mode) { - current = bot; - triv_next_time = now + TRIV_HINT_DELAY; - switch(triv_mode) - { - case TRIV_WAIT_QUESTION: - trivia_question(); - break; - case TRIV_HINT_TWO: - hint_two(); - break; - case TRIV_HINT_THREE: - hint_three(); - break; - case TRIV_NO_ANSWER: - trivia_no_answer(); - return; /* dont increment with triv_mode */ - } - triv_mode++; -#ifdef DEBUG - current = NULL; -#endif /* DEBUG */ - return; + case TRIV_WAIT_QUESTION: + trivia_question(); + break; + case TRIV_HINT_TWO: + hint_two(); + break; + case TRIV_HINT_THREE: + hint_three(); + break; + case TRIV_NO_ANSWER: + trivia_no_answer(); + return; /* dont increment with triv_mode */ } + triv_mode++; +#ifdef DEBUG + current = NULL; +#endif /* DEBUG */ + return; } } } @@ -737,7 +734,7 @@ void do_bigsay(COMMAND_ARGS) if (temp[1] == '-') ; /* allow .bigsay -- -dash- */ else - if (STRCHR(temp,'/') == NULL) /* no filesystem perversions... */ + if (stringchr(temp,'/') == NULL) /* no filesystem perversions... */ { stringcat(stringcat(stringcpy(output,COMMONDIR),temp+1),".bigchars"); /* temp+1 = skip initial '-' */ } @@ -770,7 +767,7 @@ reuse_font: } for(bigc=fontlist;bigc;bigc=bigc->next) { - if (STRCHR(bigc->chars,*pt)) + if (stringchr(bigc->chars,*pt)) { sp = bigc->data; for(x=0;x= '0' && *rest <= '9') + void do_rand(COMMAND_ARGS) { const char *opt; @@ -968,18 +969,18 @@ void do_rand(COMMAND_ARGS) if (!rest || *rest == 0) goto pick_randnum; - if (attrtab[(uchar)*rest] & NUM) + if (characterisnumeric) { max = 0; - while(attrtab[(uchar)*rest] & NUM) + while(characterisnumeric) max = 10 * max + (*(rest++) - '0'); if (*rest == '-' || *rest == ' ') rest++; - if ((attrtab[(uchar)*rest] & NUM) == 0) + if (characterisnumeric == 0) goto pick_randnum; min = max; max = 0; - while(attrtab[(uchar)*rest] & NUM) + while(characterisnumeric) max = 10 * max + (*(rest++) - '0'); goto pick_randnum; } @@ -1069,10 +1070,10 @@ void do_trivia(COMMAND_ARGS) to_server("PRIVMSG %s :Trivia starting! Get ready...\n",chan->name); triv_chan = chan; triv_mode = TRIV_WAIT_QUESTION; - triv_next_time = now + triv_qdelay; - triv_weektop10 = now; + triv_next_time = cx.now + triv_qdelay; + triv_weektop10 = cx.now; lastwinner = NULL; - short_tv |= TV_TRIVIA; + cx.short_tv |= TV_TRIVIA; if (!scorelist) { read_triviascore(); @@ -1096,7 +1097,7 @@ void do_trivia(COMMAND_ARGS) if (triv_chan) { uaccess = get_authaccess(from,triv_chan->name); - if (now > (triv_weektop10 + 300)) + if (cx.now > (triv_weektop10 + 300)) n = 1; else n = uaccess; @@ -1104,7 +1105,7 @@ void do_trivia(COMMAND_ARGS) if (n) { trivia_week_toppers(); - if (!uaccess) triv_weektop10 = now; + if (!uaccess) triv_weektop10 = cx.now; } } } diff --git a/src/uptime.c b/src/uptime.c index 41e332c..9fe42aa 100644 --- a/src/uptime.c +++ b/src/uptime.c @@ -38,10 +38,10 @@ typedef struct int regnr; int pid; int type; - uint32_t cookie; + uint32_t packets_sent; uint32_t uptime; uint32_t ontime; - uint32_t now; + uint32_t mytime; uint32_t sysup; } PackStub; @@ -51,10 +51,10 @@ typedef struct int regnr; int pid; int type; - uint32_t cookie; + uint32_t packets_sent; uint32_t uptime; uint32_t ontime; - uint32_t now; + uint32_t mytime; uint32_t sysup; char string[512]; @@ -64,7 +64,7 @@ void init_uptime(void) { struct sockaddr_in sai; - uptimecookie = rand(); + uptimepackets = 0; if (!uptimehost) { @@ -94,9 +94,8 @@ void init_uptime(void) void send_uptime(int type) { - PackUp upPack; + PackUp *upPack; struct sockaddr_in sai; - struct stat st; Server *sp; const char *server,*nick; int sz; @@ -109,7 +108,7 @@ void send_uptime(int type) { char *host; - uptimelast = now + 10; + uptimelast = cx.now + 10; if ((host = poll_rawdns(uptimehost))) { if ((uptimeip = inet_addr(host)) != -1) @@ -128,37 +127,28 @@ void send_uptime(int type) } #endif /* RAWDNS */ + upPack = (PackUp*)&globaldata; + /* * update the time when we last sent packet */ sz = (uptimelast + 1) & 7; - uptimelast = (now & ~7) + 21600 + sz; /* 21600 seconds = 6 hours */ + uptimelast = (cx.now & ~7) + 21600 + sz; /* 21600 seconds = 6 hours */ - uptimecookie = (uptimecookie + 1) * 18457; - upPack.cookie = htonl(uptimecookie); + uptimepackets = uptimepackets + 1; + upPack->packets_sent = htonl(uptimepackets); - upPack.now = htonl(now); - upPack.regnr = uptimeregnr; - upPack.type = htonl(type); - upPack.uptime = htonl(uptime); - upPack.ontime = 0; /* set a few lines down */ + upPack->mytime = htonl(cx.now); + upPack->regnr = uptimeregnr; + upPack->type = htonl(type); + upPack->uptime = htonl(uptime); + upPack->ontime = 0; /* set a few lines down */ /* * callouts to other functions should be done last (think compiler optimizations) */ - upPack.pid = htonl(getpid()); - - /* - * this trick for most systems gets the system uptime - */ - if (stat("/proc",&st) < 0) - { - upPack.sysup = 0; - } - else - { - upPack.sysup = htonl(st.st_ctime); - } + upPack->pid = htonl(getpid()); + upPack->sysup = htonl(cx.system_uptime); server = UNKNOWN; nick = BOTLOGIN; @@ -168,8 +158,8 @@ void send_uptime(int type) */ if (botlist) { - nick = botlist->nick; - upPack.ontime = htonl(botlist->ontime); + nick = getbotnick(botlist); + upPack->ontime = htonl(botlist->ontime); if ((sp = find_server(botlist->server))) { server = (*sp->realname) ? sp->realname : sp->name; @@ -190,12 +180,11 @@ void send_uptime(int type) } #endif /* ! RAWDNS */ - sz = sizeof(PackStub) + 3 + StrlenX(nick,server,VERSION,NULL); - if (sz > sizeof(PackUp)) - return; - - sprintf(upPack.string,"%s %s %s",nick,server,VERSION); + sz = sizeof(PackStub) + snprintf(upPack->string,256,"%s %s %s",nick,server,VERSION); +#ifdef DEBUG + debug("(send_uptime) packets sent %i, my pid %i, my ident = \"%s\"\n",uptimepackets,ntohl(upPack->pid),upPack->string); +#endif /* DEBUG */ /* * udp sending... */ @@ -204,7 +193,7 @@ void send_uptime(int type) sai.sin_addr.s_addr = uptimeip; sai.sin_port = htons(uptimeport); - sendto(uptimesock,(void*)&upPack,sz,0,(struct sockaddr*)&sai,sizeof(sai)); + sendto(uptimesock,(void*)upPack,sz,0,(struct sockaddr*)&sai,sizeof(sai)); } void uptime_death(int type) @@ -212,7 +201,7 @@ void uptime_death(int type) #ifdef DEBUG debug("(uptime_death) sending death message\n"); #endif /* DEBUG */ - time(&now); + time(&cx.now); uptimelast = 0; /* avoid resolving the hostname */ send_uptime(type); uptimeport = 0; /* avoid sending more packets */ @@ -221,7 +210,8 @@ void uptime_death(int type) void process_uptime(void) { struct sockaddr_in sai; - int res,sz; + unsigned int sz; + int res; struct { int regnr; @@ -238,7 +228,7 @@ void process_uptime(void) res = recvfrom(uptimesock,(void*)®Pack,sizeof(regPack),0,(struct sockaddr*)&sai,&sz); if (res == sizeof(regPack)) { - if (uptimecookie == ntohl(regPack.cookie)) + if (uptimepackets == ntohl(regPack.cookie)) { if (uptimeregnr == 0) uptimeregnr = ntohl(regPack.regnr); @@ -246,7 +236,7 @@ void process_uptime(void) } } - if (uptimelast < now) + if (uptimelast < cx.now) { send_uptime(UPTIME_BOTTYPE); } diff --git a/src/usage.h b/src/usage.h index 95c1b14..2225fc8 100644 --- a/src/usage.h +++ b/src/usage.h @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Copyright (c) 2000-2009 proton + Copyright (c) 2000-2025 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 @@ -26,7 +26,7 @@ typedef struct } UsageList; -LS const UsageList ulist[] = +const UsageList ulist[] = { #ifdef TOYBOX { C_8BALL, "[text]" }, @@ -59,7 +59,7 @@ LS const UsageList ulist[] = #endif /* CTCP */ { C_CYCLE, "[channel]" }, #ifdef DEBUG -{ C_DEBUG, NULL }, +{ C_DEBUG, "[On |Off]" }, #endif /* DEBUG */ { C_DEOP, "[channel] " }, { C_DIE, "[reason]" }, @@ -115,6 +115,9 @@ LS const UsageList ulist[] = #endif /* CTCP */ { C_QSHIT, " [reason]" }, #ifdef NOTE +#ifdef TOYBOX +{ C_RAND, "[#|#-#|# #|\"nick\"|\"luser\"]" }, +#endif /* TOYBOX */ { C_READ, "[-]" }, #endif /* NOTE */ { C_RESET, NULL }, @@ -137,7 +140,6 @@ LS const UsageList ulist[] = { C_SEND, "[to] " }, #endif /* DCC_FILE */ { C_SERVER, "[[+|-]servername] [port] [pass]" }, -{ C_SERVERGROUP,"[identifier]" }, { C_SET, "[channel|*] [setting [value]]" }, { C_SETPASS, " " }, { C_SHIT, " [expire] " }, @@ -146,7 +148,7 @@ LS const UsageList ulist[] = { C_SHUTDOWN, NULL }, { C_SITEBAN, "[channel] " }, { C_SITEKB, "[channel] [reason]" }, -{ C_SPY, "[STATUS|MESSAGE|RAWIRC|[guid\":\"|botnick\":\"] [channel|\">\" filename]" }, +{ C_SPY, "[|[guid\":\"|botnick\":\"] [channel|\">\" filename]]" }, { C_STATS, " [servername]" }, #ifdef TCL #ifdef PLEASE_HACK_MY_SHELL diff --git a/src/user.c b/src/user.c index 18ee00b..0083a87 100644 --- a/src/user.c +++ b/src/user.c @@ -77,26 +77,22 @@ void cfg_chan(char *rest) addtouser(&cfgUser->chan,rest,TRUE); } -LS struct +struct { char modechar; int modeflag; } cfg_opt_flags[] = +/* dont gatekeep these flags with ifdefs, + make userfiles compatible between different compiles */ { { 'a', COMBO_AOP }, -#ifdef BOUNCE { 'b', COMBO_BOUNCE }, -#endif /* BOUNCE */ { 'e', COMBO_ECHO }, -#ifdef BOTNET { 'L', COMBO_NOSHARE }, { 'R', COMBO_READONLY }, -#endif /* BOTNET */ -#ifdef GREET { 'g', COMBO_GREETFILE }, { 'r', COMBO_RANDLINE }, -#endif /* GREET */ { 'v', COMBO_AVOICE }, { 0, 0, }}; @@ -148,7 +144,7 @@ void cfg_shit(char *rest) * convert the expiry time */ expire = asc2int(chop(&rest)); /* asc2int() can handle NULLs */ - if (errno || expire < now) + if (errno || expire < cx.now) return; /* @@ -161,10 +157,10 @@ void cfg_shit(char *rest) /* * finally, add the sucker */ - backup_now = now; - now = when; + backup_now = cx.now; + cx.now = when; add_shit(from,channel,mask,rest,shitlevel,expire); - now = backup_now; + cx.now = backup_now; } void cfg_kicksay(char *rest) @@ -173,7 +169,7 @@ void cfg_kicksay(char *rest) backup = CurrentDCC; CurrentDCC = (Client*)&CoreClient; - do_kicksay((char*)CoreUser.name,NULL,rest,0); + do_kicksay((char*)cx.CoreUser.name,NULL,rest,0); CurrentDCC = backup; } @@ -232,7 +228,7 @@ typedef struct CommandStruct } ConfCommand; -LS const ConfCommand userlist_cmds[] = +const ConfCommand userlist_cmds[] = { /* * users @@ -564,7 +560,9 @@ void mirror_user(User *user) { Mech *backup,*anybot; User *newuser,*olduser; +#ifdef NOTE Strp *notes; +#endif /* NOTE */ #ifdef BOTNET /* dont mirror noshare users */ @@ -593,7 +591,7 @@ void mirror_user(User *user) } #ifdef DEBUG debug("(mirror_user) mirroring user %s[%i] to local bot %s(%i)\n", - user->name,user->x.x.access,nullstr(anybot->nick),anybot->guid); + user->name,user->x.x.access,getbotnick(anybot),anybot->guid); #endif /* DEBUG */ current = anybot; @@ -646,7 +644,7 @@ void mirror_userlist(void) User *user; #ifdef DEBUG - debug("(mirror_userlist) mirroring userlist of %s(%i)\n",nullstr(current->nick),current->guid); + debug("(mirror_userlist) mirroring userlist of %s(%i)\n",getbotnick(current),current->guid); #endif /* DEBUG */ for(user=current->userlist;user;user=user->next) @@ -903,7 +901,7 @@ int is_bot(const char *userhost) for(bot=botlist;bot;bot=bot->next) { - if (!nickcmp(userhost,bot->nick)) + if (!nickcmp(userhost,getbotnick(bot))) return(TRUE); } return(FALSE); @@ -1077,7 +1075,7 @@ void do_userlist(COMMAND_ARGS) channel = rest; } else - if (STRCHR(rest,'*') != NULL) + if (stringchr(rest,'*') != NULL) { mask = rest; } @@ -1184,7 +1182,6 @@ void do_user(COMMAND_ARGS) /* * on_msg checks: CARGS */ - Mech *anybot; User *user; Strp *ump; char *handle,*pt,*mask,*nick,*chan,*anum,*pass,*encpass; diff --git a/src/vars.c b/src/vars.c index dfc6a88..16f7b56 100644 --- a/src/vars.c +++ b/src/vars.c @@ -1,7 +1,7 @@ /* EnergyMech, IRC bot software - Parts Copyright (c) 1997-2009 proton + Parts Copyright (c) 1997-2025 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 @@ -53,10 +53,12 @@ int find_setting(const char *name) { int i; - for(i=0;VarName[i].name;i++) + for(i=0;i convert lower case to upper */ + if ((*name & 223) == *VarName[i].name) + if (stringcasecmp(name,VarName[i].name) == 0) + return(i); } return(-1); } @@ -86,8 +88,10 @@ void set_binarydefault(UniVar *dst) { int i; - for(i=0;VarName[i].name;i++) + for(i=0;iontime,FALSE)); + nobo_strcpy(idle2str(current->ontime,FALSE)); } void ec_server(char *from, const char *to) @@ -259,7 +278,7 @@ void ec_server(char *from, const char *to) void ec_up(char *from, const char *to) { - nobo_strcpy(idle2str(now - uptime,FALSE)); + nobo_strcpy(idle2str(uptime,FALSE)); } void ec_ver(char *from, const char *to) @@ -277,7 +296,7 @@ void ec_guid(char *from, const char *to) nobo_strcpy(tmp); } -LS const struct +static const struct { void (*func)(char *, const char *); char name[12]; @@ -285,17 +304,23 @@ LS const struct } ecmd[] = { +/* + * Sorted by the second parameter alphabetical + */ { ec_access, "$access", 7 }, { ec_capabilities, "$cap", 4 }, { ec_cc, "$cc", 3 }, { ec_channels, "$channels", 9 }, - { ec_time, "$time", 5 }, - { ec_set, "$var(", 5 }, + { ec_guid, "$guid", 5 }, +#ifdef HOSTINFO + { ec_loadavg, "$load", 5 }, +#endif /* HOSTINFO */ { ec_on, "$on", 3 }, { ec_server, "$server", 7 }, + { ec_time, "$time", 5 }, { ec_up, "$up", 3 }, + { ec_set, "$var(", 5 }, { ec_ver, "$ver", 4 }, - { ec_guid, "$guid", 5 }, { NULL, "", 0 }, }; @@ -382,6 +407,7 @@ void do_set(COMMAND_ARGS) /* * empty args, its "set" or "set #channel" + * list setting and values */ if (!name) { @@ -463,6 +489,10 @@ second_pass: if ((which = find_setting(name)) == -1) { set_usage: +#ifdef DEBUG + if (from == cx.CoreUser.name) + debug("init: set error: %s\n",nullstr(name)); +#endif usage(from); /* usage for CurrentCmd->name */ return; } @@ -573,6 +603,9 @@ num_data_ok: } to_user(from,"Var: %s On: %s Set to: %s",VarName[which].name, (which >= CHANSET_SIZE) ? "(global)" : channel,(*rest) ? rest : NULLSTR); - if (VarName[which].func) - VarName[which].func(&VarName[which]); + /* + * if there is an onchange function + */ + if (VarName[which].onchangefunc) + VarName[which].onchangefunc(&VarName[which]); } diff --git a/src/web.c b/src/web.c index 533b664..fd6a6f3 100644 --- a/src/web.c +++ b/src/web.c @@ -35,9 +35,9 @@ #define WEBROOT "web/" -LS WebSock *weblist; +WebSock *weblist; -LS WebDoc docraw = { NULL, NULL, &web_raw }; +WebDoc docraw = { NULL, NULL, &web_raw }; #if 0 { @@ -45,7 +45,7 @@ LS WebDoc docraw = { NULL, NULL, &web_raw }; }; #endif -LS WebDoc doclist[] = +WebDoc doclist[] = { { NULL, "/internalstatus.html", &web_botstatus }, #ifdef DEBUG @@ -125,7 +125,7 @@ char *webread(int s, char *rest, char *line) return(NULL); } -#define NOBO if (dest == &mem[MSGLEN-2]) { int n; n = write(s,mem,dest-mem); dest = mem; } +#define NOBO if (dest == &mem[MSGLEN-2]) { int _n_ __notused__; _n_ = write(s,mem,dest-mem); dest = mem; } void eml_fmt(WebSock *client, char *format) { @@ -133,7 +133,7 @@ void eml_fmt(WebSock *client, char *format) char *src,*dest,*org; int out; int s = client->sock; - int n; + int n __notused__; org = NULL; out = TRUE; @@ -165,7 +165,7 @@ restart: client->echan = (client->ebot) ? client->ebot->chanlist : NULL; break; case 'b': - src = (client->ebot) ? client->ebot->nick : (char*)NULLSTR; + src = (client->ebot) ? getbotnick(client->ebot) : (char*)NULLSTR; while(*src) { NOBO; @@ -241,7 +241,7 @@ void web_raw(WebSock *client, char *url) char path[MSGLEN]; char *src,*dest; ino_t ino; - int fd,eml,n; + int fd,eml,n __notused__; size_t sz; eml = (matches("*.html",url)) ? TRUE : FALSE; @@ -328,7 +328,7 @@ void web_botstatus(WebSock *client, char *url) "

EnergyMech Status

\r\n" "Uptime: %s

\r\n" "Current bots:
\r\n", - idle2str(now - uptime,FALSE)); + idle2str(uptime,FALSE)); for(;bot;bot=bot->next) { @@ -474,7 +474,7 @@ void process_web(void) new = (WebSock*)Calloc(sizeof(WebSock)); new->sock = s; new->status = WEB_WAITURL; - new->when = now; + new->when = cx.now; new->next = weblist; weblist = new; }