#! /bin/sh # # Copyright (C) 1999-2003 Jeff Fisher (guppy@eggheads.org) # Copyright (C) 2004-2023 Eggheads Development Team # # systemd formatting contributed by PeGaSuS # # 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # This trick is borrowed from Tothwolf's Wolfpack \ # Check for working 'grep -E' before using 'egrep' \ if echo a | (grep -E '(a|b)') >/dev/null 2>&1; \ then \ egrep="grep -E"; \ else \ egrep=egrep; \ fi; \ # Search for tclsh[0-9].[0-9] in each valid dir in PATH \ for dir in $(echo $PATH | sed 's/:/ /g'); \ do \ if test -d $dir; \ then \ files=$(/bin/ls $dir | $egrep '^tclsh[0-9]\.[0-9]$'); \ if test "$files" != ""; \ then \ versions="${versions:+$versions }$(echo $files | sed 's/tclsh//g')"; \ fi; \ fi; \ done; \ for ver in $versions; \ do \ tmpver=$(echo $ver | sed 's/\.//g'); \ if test "$lasttmpver" != ""; \ then \ if test "$tmpver" -gt "$lasttmpver"; \ then \ lastver=$ver; \ lasttmpver=$tmpver; \ fi; \ else \ lastver=$ver; \ lasttmpver=$tmpver; \ fi; \ done; \ exec tclsh$lastver "$0" ${1+"$@"} # # AutoBotchk - An eggdrop utility to autogenerate botchk/crontab entries # # Copyright (C) 1999-2003 Jeff Fisher (guppy@eggheads.org) # Copyright (C) 2004-2023 Eggheads Development Team # # How to use # ---------- # # Most people begin to use AutoBotchk by moving it from the script # directory to their Eggdrop directory -- this will save you from having to # use the -dir option. # # If you run AutoBotchk without any arguments, it will present you with # a list of valid ones. Most people run AutoBotchk by doing: # # ./autobotchk # # This will setup crontab to check every 10 minutes to see whether or not # your bot needs to be restarted and it will e-mail if a restart was # performed. A lot of people turn off crontab e-mail support; however, I do # not recommend this since you will be unable to see any errors that might # happen. # # Updates # ------- # 27Sep2001: added new pidfile setting # 14Nov2001: removed old autobotchk update entries and updated the help # section a little bit. also made autobotchk move down one # directory if being run from the scripts directory. # 15Apr2003: cleaned up a few things, fixed a few bugs, and made a little # love! j/k # 13Dec2016: add possibility to use multiple confs; fixes for (botnet-)nick # with len > handlen, for (botnet-)nicks with \[ \] and for # $(botnet-)nick used in pidfile, userfile or (botnet-)nick # 19Apr2017: Fix running this from a non-eggdrop dir. # 28Nov2023: Added -systemd option, to (duh) create a systemd job if {$argc == 0} { puts "\nusage: $argv0 \[options\] \[additional configs\]" puts "Options:" puts "--------" puts " systemd options:" puts " -systemd (install systemd job instead of cron)" puts "" puts " crontab options:" puts " -dir (directory to run autobotchk in)" puts " -noemail (discard crontab e-mails)" puts " -5 (5 minute checks)" puts " -10 (10 minute checks)" puts " -15 (15 minute checks)" puts " -30 (30 minute checks)" puts "" puts "Additional Configs:" puts "-------------------" puts " If you source additional configs from your main config and they" puts " contain either nick, botnet-nick, userfile or pidfile settings," puts " list them here so that autobotchk can check in them as well." puts "" exit } fconfigure stdout -buffering none proc newsplit {text {split " "}} { upvar $text ours append ours $split set index [string first $split $ours] if {$index == -1} { set ours "" return "" } set tmp [string trim [string range $ours 0 $index]] set ours [string trim [string range $ours [expr $index + [string length $split]] end]] return $tmp } puts "\nautobotchk 1.11, (C) 1999-2003 Jeff Fisher (guppy@eggheads.org)" puts " (C) 2004-2022 Eggheads Development Team" puts "------------------------------------------------------------\n" set mainconf [newsplit argv] set confs [list $mainconf] set dir [pwd] set delay 10 set email 1 set systemd 0 catch {exec which kill} kill # If you renamed your eggdrop binary, you should change this variable set binary "eggdrop" while {[set opt [newsplit argv]] != ""} { switch -- $opt { "-systemd" { set systemd 1 } "-time" - "-1" { set delay 1 } "-5" { set delay 5 } "-10" { set delay 10 } "-15" { set delay 15 } "-20" { set delay 20 } "-30" { set delay 30 } "-nomail" - "-noemail" {set email 0} "-dir" { set dir [newsplit argv] if {[string match -* $dir]} { puts "*** ERROR: you did not supply a directory name" puts "" exit } if {![file isdirectory $dir]} { puts "*** ERROR: the directory you supplied is not a directory" puts "" exit } } default { # Treat as extra config file if {[file isfile $opt] && [file readable $opt]} { lappend confs $opt } } } } switch -- $delay { "30" { set minutes "0,30" } "20" { set minutes "0,20,40" } "15" { set minutes "0,15,30,45" } "5" { set minutes "0,5,10,15,20,25,30,35,40,45,50,55" } "1" { set minutes "*" } default { set minutes "0,10,20,30,40,50" } } if {[string match "*/scripts" $dir]} { set dir [string range $dir 0 [expr [string length $dir] - 8]] } set dir [string trimright $dir /] if {![file exists $dir/help] || ![file isdirectory $dir/help]} { puts "*** ERROR: are you sure you are running from a bot directory?" puts "" exit } elseif {![file exists $dir/$binary]} { puts "*** ERROR: are you sure you are running from a bot directory?" puts "" exit } foreach config $confs { puts -nonewline "Opening '$config' for processing ... " if {[catch {open $dir/$config r} fd]} { puts "error:" puts " $fd\n" exit } else { puts "done" } set count 0 puts -nonewline "Scanning the config file " while {![eof $fd]} { incr count if {$count == 100} { puts -nonewline "." set count 0 } set line [gets $fd] if {[set blarg [newsplit line]] != "set"} { continue } switch -- [set opt [newsplit line]] { "pidfile" - "nick" - "userfile" - "botnet-nick" { set $opt [string trim [newsplit line] " \"{}"] } } } close $fd if {$count != 0} { puts -nonewline "." } puts " done" } if {![info exists {botnet-nick}] && [info exists nick]} { puts " Defaulting \$botnet-nick to \"$nick\"" set botnet-nick $nick } if {![info exists {botnet-nick}] || ![info exists userfile]} { puts " *** ERROR: could not find either \$userfile or \$botnet-nick" puts "" puts " Are you sure this is a valid eggdrop config file?" puts "" exit } catch {exec "$dir/$binary" -v} execres if {![regexp {handlen=([0-9]+)} "$execres" -> handlen]} { puts " Could not find handlen used, defaulting to 32." # len 32 means up to index 31 set handlen 31 } else { set handlen [expr $handlen - 1] } set nick [string range [subst -nocommands $nick] 0 $handlen] set botnet-nick [string range [subst -nocommands ${botnet-nick}] 0 $handlen] ### systemd stuff if {$systemd} { puts "Enabling user lingering..." if {[catch {exec loginctl enable-linger} res]} { puts "Oops, something went wrong. Is systemd running on this system?" exit } puts "Creating systemd directory..." catch {file mkdir ~/.config/systemd/user } res if {[catch {open ~/.config/systemd/user/${botnet-nick}.service w} fd]} { puts " *** ERROR: unable to open '${botnet-nick}.service' for writing" puts "" exit } puts $fd "### Eggdrop systemd unit, generated by autosystemd" puts $fd "" puts $fd "\[Unit\]" puts $fd "Description=${botnet-nick} (Eggdrop)" puts $fd "After=default.target" puts $fd "" puts $fd "\[Service\]" puts $fd "WorkingDirectory=${dir}" puts $fd "ExecStart=${dir}/eggdrop ${config}" puts $fd "ExecReload=${kill} -s HUP \$MAINPID" puts $fd "Type=forking" puts $fd "Restart=on-abnormal" puts $fd "" puts $fd "\[Install\]" puts $fd "WantedBy=default.target" close $fd catch {exec systemctl --user enable ${botnet-nick}.service} res puts $res puts "systemd job successfully installed as '${botnet-nick}.service'." puts "* Use 'systemctl --user ${botnet-nick}.service' to control your Eggdrop" puts "Starting Eggdrop..." if {[catch {exec systemctl --user start ${botnet-nick}.service} res]} { puts "ERROR: Eggdrop did not start." puts $res } else { puts "Success." } exit } if {![info exists pidfile]} { puts " Defaulting \$pidfile to \"pid.${botnet-nick}\"" set pidfile "pid.${botnet-nick}" } set pidfile [subst -nocommands $pidfile] if {[catch {open $dir/${botnet-nick}.botchk w} fd]} { puts " *** ERROR: unable to open '${botnet-nick}.botchk' for writing" puts "" exit } puts $fd "#! /bin/sh # # ${botnet-nick}.botchk (generated on [clock format [clock seconds] -format "%B %d, %Y @ %I:%M%p"]) # # Generated by AutoBotchk 1.11 # Copyright (C) 1999-2003 Jeff Fisher (guppy@eggheads.org) # Copyright (C) 2004-2023 Eggheads Development Team # # change this to the directory you run your bot from: botdir=\"$dir\" # change this to the name of your bot's script in that directory: botscript=\"$binary $mainconf\" # change this to the nickname of your bot (capitalization COUNTS) botname=\"${botnet-nick}\" # change this to the name of your bot's userfile (capitalization COUNTS) userfile=\"$userfile\" # change this to the name of your bot's pidfile (capitalization COUNTS) pidfile=\"$pidfile\" ########## you probably don't need to change anything below here ########## cd \$botdir # is there a pid file? if test -r \$pidfile then # there is a pid file -- is it current? botpid=`cat \$pidfile` if `kill -CHLD \$botpid >/dev/null 2>&1` then # it's still going -- back out quietly exit 0 fi echo \"\" echo \"Stale \$pidfile file, erasing...\" rm -f \$pidfile fi if test -r CANTSTART.\$botname then if test -r \$userfile || test -r \$userfile~new || test -r \$userfile~bak then echo \"\" echo \"Userfile found, removing check file 'CANTSTART.\$botname'...\" rm -f CANTSTART.\$botname fi fi # test if we have run botchk previously and didn't find a userfile if test ! -f CANTSTART.\$botname then echo \"\" echo \"Couldn't find bot '\$botname' running, reloading...\" echo \"\" # check for userfile and reload bot if found if test -r \$userfile then # It's there, load the bot ./\$botscript exit 0 else if test -r \$userfile~new then # Bot f*@!ed up while saving the userfile last time. Move it over. echo \"Userfile missing. Using last saved userfile...\" mv -f \$userfile~new \$userfile ./\$botscript exit 0 else if test -r \$userfile~bak then # Userfile is missing, use backup userfile. echo \"Userfile missing. Using backup userfile...\" cp -f \$userfile~bak \$userfile ./\$botscript exit 0 else # Well, nothing to work with... echo \"No userfile. Could not reload the bot...\" echo \"no userfile\" > CANTSTART.\$botname exit 1 fi fi fi fi exit 0 " close $fd puts "Wrote '${botnet-nick}.botchk' successfully ([file size $dir/${botnet-nick}.botchk] bytes)" if {[catch {exec chmod u+x $dir/${botnet-nick}.botchk} 0]} { puts " *** ERROR: unable to 'chmod u+x' the output file" puts "" exit } puts -nonewline "Scanning crontab entries ... " set tmp ".autobotchk[clock clicks].[pid]" set cronbotchk [string map {\\ \\\\ \[ \\\[ \] \\\]} "${botnet-nick}.botchk"] if {$email} { set line "$minutes \* \* \* \* $dir/${cronbotchk}" } { set line "$minutes \* \* \* \* $dir/${cronbotchk} >\/dev\/null 2>&1" } if {[catch {exec crontab -l > $tmp} error ]} { if {![string match "*no*cron*" [string tolower $error]] && ![string match "*can't open*" [string tolower $error]]} { catch {file delete -force $tmp} 0 puts "error: unable to get crontab listing" puts "" puts $error puts "" exit } } set cronbotchk [string map {\\ \\\\ \[ \\\[ \] \\\]} "${cronbotchk}"] set fd [open $tmp r] while {![eof $fd]} { set z [gets $fd] if {[string match "*$dir/${cronbotchk}*" $z] || [string match "*$dir//${cronbotchk}*" $z]} { puts "found an existing entry, we're done now" puts "" exit } } close $fd puts "done" puts -nonewline "Adding the new crontab entry ... " set fd [open $tmp a] puts $fd $line close $fd if {[catch {exec crontab $tmp} error]} { puts "error: unable to do 'crontab $tmp'" puts "" puts $error puts "" exit } else { catch {file delete -force $tmp} 0 } puts "done" puts "" puts "Use 'crontab -l' to view all your current crontab entries" puts " 'crontab -r' to remove all your crontab entries" puts ""