#! /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 <config file>
#
# 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 <eggdrop mainconfig> \[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 <start|stop|restart|reload|enable|disable> ${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 ""