496 lines
16 KiB
Bash
496 lines
16 KiB
Bash
#!/bin/bash
|
|
## Copyright © 2018-2020 Bret Human
|
|
## https://cynicaloptimist.me/
|
|
##
|
|
## Documentation at:
|
|
## https://mage.cynicaloptimist.me/en/bn3t
|
|
## https://psi.cynicaloptimist.me/Caffarius/bn3t/
|
|
##
|
|
## For questions or comments write:
|
|
## info@cynicaloptimist.me
|
|
#####################################################################
|
|
# bn3t
|
|
script_ver="0.3"
|
|
page="https://mage.cynicaloptimist.me/en/bn3t"
|
|
# author: Bret Human
|
|
# date: Dec 6, 2018
|
|
#
|
|
#####################################################################
|
|
#
|
|
# A wrapper for wrappers, used to install/manage/own a Battle.net
|
|
# installation within Wine in a Linux environment.
|
|
#
|
|
# Extra handy for running Battle.net under a secondary account for
|
|
# added security. Can be used for lots of zany wine needs, like
|
|
# spawning a multitude of Wine prefixes and installing Battle.net in
|
|
# all of them.
|
|
#
|
|
# This is the first of two scripts. It is meant to be the sanitizer
|
|
# crew and the firing squad for bn3t-run. bn3t-run must be installed.
|
|
#
|
|
# Install bn3t-run for your desired user with:
|
|
# ./bn3t.sh -u username -i
|
|
#
|
|
# Then you can prep the environment and install Battle.net via:
|
|
# ./bn3t.sh -u username -bxs
|
|
#
|
|
# Or I guess you could manually download the script from:
|
|
dl_addr="https://psi.cynicaloptimist.me/Caffarius/bn3t/raw/branch/master/bn3t-run.sh"
|
|
#####################################################################
|
|
#
|
|
# This is free software; you are free to change and redistribute it.
|
|
# There is NO WARRANTY of any kind.
|
|
#
|
|
#####################################################################
|
|
|
|
runas_user="`whoami`"
|
|
app_name="Battle.net"
|
|
run_cmd="bn3t-run.sh"
|
|
jail_dir="/var/jail"
|
|
check_wait="3"
|
|
usage="bn3t, version ${script_ver}
|
|
Usage: ./`basename ${0}` -g (game) -u (user) -p (prefix) -a (arch) -dvksbwtnchxi
|
|
-a | Selects the architecture to run as (32 | 64)
|
|
-b | Runs wineboot
|
|
-c | Launch a console session as specified user (can launch Xapps)
|
|
-d | Debug messages on (turns verbose on)
|
|
-g | Launches the game of your choice
|
|
-h | Help (this message)
|
|
-i | Install the bn3t-run script for the specified user - mandantory
|
|
-j | Run ${run_cmd} inside a chroot jail at ${jail_dir}
|
|
-k | Kill all processes for a user (not current user or root)
|
|
-m | Runs Twitch Client (for /M/ods - I'm running out of letters)
|
|
-n | No BS mode - doesn't launch an app (for boot/tricks/console safety)
|
|
-p | Selects the location of the Wine prefix
|
|
-s | Runs ${app_name} setup
|
|
-t | Attempts to launch to the system tray
|
|
-u | Runs ${app_name} as the user specified
|
|
-v | Verbose messages on
|
|
-w | Runs winetricks
|
|
-x | Force upgrade DXVK
|
|
-z | Set the DISPLAY variable used in ${run_cmd}
|
|
See more documentation at: ${page}"
|
|
|
|
# Catch CTRL+C and cleanup
|
|
trap "echo '' && inform '---------------------------------' && inform 'Caught CTRL+C' && check" 2
|
|
|
|
## Define our functions
|
|
function refresh {
|
|
app_dir="/home/${runas_user}/.script/"
|
|
app_check="ps -ef | grep ${runas_user} | grep Battle.net.exe | grep -v grep"
|
|
}
|
|
|
|
function debug () {
|
|
if [ "${app_debug}" ]; then
|
|
echo -e "-D- ${1}"
|
|
fi
|
|
}
|
|
|
|
function inform () {
|
|
if [ "${app_verbose}" ]; then
|
|
echo -e "--- ${1}"
|
|
fi
|
|
}
|
|
|
|
function buff_cmd_output () {
|
|
read cmd_input
|
|
cmd_output=$(eval "${cmd_input}")
|
|
|
|
if [ ! -z "${cmd_output}" ]; then
|
|
debug "${cmd_output}"
|
|
fi
|
|
}
|
|
|
|
function clean {
|
|
debug "Clean"
|
|
|
|
# Var
|
|
unset script_ver
|
|
unset page
|
|
unset runas_user
|
|
unset app_name
|
|
unset run_cmd
|
|
unset check_wait
|
|
unset usage
|
|
unset app_dir
|
|
unset app_check
|
|
unset app_debug
|
|
unset app_verbose
|
|
unset launch_opt
|
|
unset nobs_mode
|
|
unset dl_addr
|
|
|
|
# Func
|
|
unset refresh
|
|
unset debug
|
|
unset inform
|
|
unset check
|
|
}
|
|
|
|
function die () {
|
|
debug "die"
|
|
echo "Cleaning up..."
|
|
|
|
if [ "`whoami`" == "${runas_user}" ]; then
|
|
debug "Launched as original user, not killing processes"
|
|
else
|
|
if [ "${runas_user}" == "root" ]; then
|
|
debug "Root? Madness. Just removing xhost then..."
|
|
inform "`xhost -SI:localuser:root`"
|
|
else
|
|
debug "Launched as ${runas_user}, killing processes and removing xhost..."
|
|
sudo -u "${runas_user}" -- bash -c "kill -9 -1"
|
|
inform "`xhost -SI:localuser:"${runas_user}"`"
|
|
fi
|
|
fi
|
|
|
|
if [ "${jailbird}" == "1" ]; then
|
|
debug "Removing root from xhost..."
|
|
inform "`xhost -SI:localuser:root`"
|
|
|
|
debug "Delaying jail demolition..."
|
|
sleep 1
|
|
debug "Demolishing jail..."
|
|
|
|
echo "sudo rm ${jail_dir}/${runas_user}/bin 2>&1" | buff_cmd_output
|
|
echo "sudo rm ${jail_dir}/${runas_user}/sbin 2>&1" | buff_cmd_output
|
|
echo "sudo rm ${jail_dir}/${runas_user}/lib 2>&1" | buff_cmd_output
|
|
echo "sudo rm ${jail_dir}/${runas_user}/lib64 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/usr 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/etc 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/tmp/pulse-socket 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/dev 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/proc 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/sys 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/run 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/tmp 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/var 2>&1" | buff_cmd_output
|
|
echo "sudo umount -l ${jail_dir}/${runas_user}/home/${runas_user} 2>&1" | buff_cmd_output
|
|
|
|
debug "Jail demolished."
|
|
fi
|
|
|
|
clean
|
|
unset clean
|
|
unset fizzle
|
|
|
|
if [ "$1" ]; then
|
|
unset die && exit $1
|
|
else
|
|
echo "...what?"
|
|
unset die && exit 5
|
|
fi
|
|
exit 5
|
|
}
|
|
|
|
function fizzle () {
|
|
debug "fizzle" # https://mtg.gamepedia.com/Fizzle
|
|
echo "Exiting..."
|
|
clean
|
|
unset clean
|
|
unset die
|
|
|
|
if [ "$1" ]; then
|
|
unset fizzle && exit $1
|
|
else
|
|
echo "...what?"
|
|
unset fizzle && exit 5
|
|
fi
|
|
exit 5
|
|
}
|
|
|
|
function check {
|
|
debug "check"
|
|
i="0"
|
|
while [ "${i}" -lt "${check_wait}" ]; do
|
|
if [ "$(eval ${app_check})" ]; then
|
|
inform "${app_name} is still running. Waiting to see if we need to murder... $[ ${check_wait} - ${i} ]"
|
|
sleep 1
|
|
else
|
|
unset i
|
|
die 0
|
|
fi
|
|
|
|
i=$[ $i + 1 ]
|
|
done
|
|
unset i
|
|
}
|
|
|
|
|
|
|
|
## Pick up any arguments provided
|
|
# None are required, we'll use default values.
|
|
launch_opt=""
|
|
while getopts ":a:A:g:G:p:P:u:U:z:Z:bBcCdDhHiIjJkKmMnNsStTvVwWxX" option; do
|
|
case "${option}" in
|
|
"a"|"A") launch_opt="${launch_opt} -a ${OPTARG}";;
|
|
"b"|"B")
|
|
inform "Wineboot mode"
|
|
launch_opt="${launch_opt} -b"
|
|
;;
|
|
"c"|"C")
|
|
inform "Console requested"
|
|
nobs_mode="y"
|
|
launch_opt="${launch_opt} -c"
|
|
;;
|
|
"d"|"D")
|
|
if [ ! "${app_debug}" ]; then # Let's not do this too much...
|
|
app_debug="y"
|
|
launch_opt=" -d${launch_opt}"
|
|
debug "Debug enabled"
|
|
if [ ! "${app_verbose}" ]; then
|
|
debug "`realpath "${0}"` version ${script_ver} running as `whoami`"
|
|
fi
|
|
app_verbose="y"
|
|
debug ""
|
|
debug "This is free software; you are free to change and redistribute it."
|
|
debug "There is NO WARRANTY of any kind."
|
|
debug ""
|
|
debug "Documentation at: ${page}"
|
|
debug ""
|
|
fi
|
|
;;
|
|
"g"|"G") launch_opt="${launch_opt} -g ${OPTARG}";;
|
|
"h"|"H")
|
|
echo "${usage}"
|
|
fizzle 0
|
|
;;
|
|
"i"|"I")
|
|
debug "User-side install requested"
|
|
refresh
|
|
|
|
if [ "`whoami`" == "${runas_user}" ]; then
|
|
debug "Running as original user, just downloading it"
|
|
mkdir -p "${app_dir}" ||
|
|
(echo "Failed to make directory ${app_dir}" && fizzle 1)
|
|
|
|
wget "${dl_addr}" -O "${app_dir}${run_cmd}" ||
|
|
(echo "Failed to download script from ${dl_addr}" && fizzle 1)
|
|
|
|
chmod 700 "${app_dir}${run_cmd}" ||
|
|
(echo "Failed to change permissions on ${app_dir}${run_cmd}" && fizzle 1)
|
|
else
|
|
debug "Running as ${runas_user}, switching and downloading"
|
|
sudo -u "${runas_user}" -- mkdir -p "${app_dir}" ||
|
|
(echo "Failed to make directory ${app_dir}" && fizzle 1)
|
|
|
|
sudo -u "${runas_user}" -- wget "${dl_addr}" -O "${app_dir}${run_cmd}" ||
|
|
(echo "Failed to download script from ${dl_addr}" && fizzle 1)
|
|
|
|
sudo -u "${runas_user}" -- chmod 700 "${app_dir}${run_cmd}" ||
|
|
(echo "Failed to change permissions on ${app_dir}${run_cmd}" && fizzle 1)
|
|
fi
|
|
|
|
echo "Install process completed."
|
|
fizzle 0
|
|
;;
|
|
"j"|"J")
|
|
debug "Running ${appname} in a chroot jail under ${jail_dir}/${runas_user}/"
|
|
jailbird=1
|
|
;;
|
|
"k"|"K") die 0;;
|
|
"m"|"M")
|
|
inform "Twitch mode"
|
|
launch_opt="${launch_opt} -m"
|
|
;;
|
|
"n"|"N")
|
|
inform "No BS mode"
|
|
nobs_mode="y"
|
|
launch_opt="${launch_opt} -n"
|
|
;;
|
|
"p"|"P") launch_opt="${launch_opt} -p ${OPTARG}";;
|
|
"s"|"S")
|
|
inform "Setup mode"
|
|
nobs_mode="y"
|
|
launch_opt="${launch_opt} -s"
|
|
;;
|
|
"t"|"T")
|
|
debug "Hiding to system tray"
|
|
launch_opt="${launch_opt} -t"
|
|
;;
|
|
"u"|"U")
|
|
debug "Setting user to ${OPTARG}"
|
|
runas_user="${OPTARG}"
|
|
;;
|
|
"v"|"V")
|
|
if [ ! "${app_debug}" ]; then
|
|
if [ ! "${app_verbose}" ]; then
|
|
app_verbose="y"
|
|
inform "Verbose enabled"
|
|
inform "`realpath "${0}"` version ${script_ver} running as `whoami`"
|
|
launch_opt=" -v${launch_opt}"
|
|
fi
|
|
fi
|
|
;;
|
|
"w"|"W")
|
|
inform "Winetricks mode"
|
|
launch_opt="${launch_opt} -w"
|
|
;;
|
|
"x"|"X")
|
|
inform "Force upgrading dxvk"
|
|
launch_opt="${launch_opt} -x"
|
|
;;
|
|
"z"|"Z")
|
|
inform "Setting DISPLAY to ${OPTARG}"
|
|
launch_opt="${launch_opt} -z ${OPTARG}"
|
|
;;
|
|
* ) echo "Unknown option: -${OPTARG}"
|
|
echo "${usage}"
|
|
fizzle 1
|
|
;;
|
|
esac
|
|
done
|
|
debug "launch_opt:${launch_opt}"
|
|
|
|
|
|
|
|
## Pass our knowledge on.
|
|
refresh
|
|
debug "run_app"
|
|
if [ "`whoami`" == "${runas_user}" ]; then
|
|
debug "Launching as original user, going native"
|
|
${app_dir}${run_cmd}${launch_opt}
|
|
else
|
|
debug "Checking xhost"
|
|
if [ ! "`xhost | grep ${runas_user}`" ]; then
|
|
inform "`xhost +SI:localuser:"${runas_user}"`"
|
|
fi
|
|
|
|
if [ ! "${jailbird}" == "1" ]; then
|
|
# Just launch it as a regular secondary user app
|
|
debug "Launching as ${runas_user}..."
|
|
sudo -u "${runas_user}" -- dbus-launch ${app_dir}${run_cmd}${launch_opt}
|
|
else
|
|
# Hooooooowiiiiiiee. We're gonna build a jail!
|
|
if [ ! "`xhost | grep root`" ]; then
|
|
inform "`xhost +SI:localuser:root`"
|
|
fi
|
|
|
|
debug "Preparing ${runas_user}'s chroot environment..."
|
|
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/tmp
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/usr
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/var
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/proc
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/sys
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/dev
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/run
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/etc
|
|
sudo mkdir -p ${jail_dir}/${runas_user}/home/${runas_user}
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/tmp > /dev/null; then
|
|
debug "/tmp is already mounted?"
|
|
else
|
|
debug "Mounting /tmp..."
|
|
sudo mount -t tmpfs -o size=2G tmpfs ${jail_dir}/${runas_user}/tmp
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/proc > /dev/null; then
|
|
debug "/proc is already mounted?"
|
|
else
|
|
debug "Mounting /proc..."
|
|
sudo mount --bind /proc ${jail_dir}/${runas_user}/proc
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/sys > /dev/null; then
|
|
debug "/sys is already mounted?"
|
|
else
|
|
debug "Mounting /sys..."
|
|
sudo mount --bind /sys ${jail_dir}/${runas_user}/sys
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/dev > /dev/null; then
|
|
debug "/dev is already mounted?"
|
|
else
|
|
debug "Mounting /dev..."
|
|
sudo mount --bind /dev ${jail_dir}/${runas_user}/dev
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/run > /dev/null; then
|
|
debug "/run is already mounted?"
|
|
else
|
|
debug "Mounting /run..."
|
|
sudo mount --bind /run ${jail_dir}/${runas_user}/run
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/var > /dev/null; then
|
|
debug "/var is already mounted?"
|
|
else
|
|
debug "Mounting /var..."
|
|
sudo mount --bind /var ${jail_dir}/${runas_user}/var
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/etc > /dev/null; then
|
|
debug "/etc is already mounted?"
|
|
else
|
|
debug "Mounting /etc..."
|
|
sudo mount --bind /etc ${jail_dir}/${runas_user}/etc
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/usr > /dev/null; then
|
|
debug "/usr is already mounted?"
|
|
else
|
|
debug "Mounting /usr..."
|
|
sudo mount --bind /usr ${jail_dir}/${runas_user}/usr
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/home/${runas_user} > /dev/null; then
|
|
debug "/home/${runas_user} is already mounted?"
|
|
else
|
|
debug "Mounting /home/${runas_user}..."
|
|
sudo mount --bind /mnt/ace/home/${runas_user} ${jail_dir}/${runas_user}/home/${runas_user}
|
|
fi
|
|
|
|
if [ ! -d ${jail_dir}/${runas_user}/bin ]; then
|
|
debug "Linking /bin to usr/bin..."
|
|
sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/bin bin"
|
|
fi
|
|
|
|
if [ ! -d ${jail_dir}/${runas_user}/sbin ]; then
|
|
debug "Linking /sbin to usr/bin (that's not a typo!)..."
|
|
sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/bin sbin"
|
|
fi
|
|
|
|
if [ ! -d ${jail_dir}/${runas_user}/lib ]; then
|
|
debug "Linking /lib to usr/lib..."
|
|
sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/lib lib"
|
|
fi
|
|
|
|
if [ ! -d ${jail_dir}/${runas_user}/lib64 ]; then
|
|
debug "Linking /lib64 to usr/lib (that's not a typo!)..."
|
|
sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/lib lib64"
|
|
fi
|
|
|
|
if [ ! -S ${jail_dir}/${runas_user}/tmp/pulse-socket ]; then
|
|
if [ ! -f ${jail_dir}/${runas_user}/tmp/pulse-socket ]; then
|
|
debug "Creating /tmp/pulse-socket to link sound..."
|
|
sudo -u ${runas_user} touch ${jail_dir}/${runas_user}/tmp/pulse-socket
|
|
fi
|
|
|
|
if mountpoint ${jail_dir}/${runas_user}/tmp/pulse-socket > /dev/null; then
|
|
debug "/tmp/pulse-socket is already mounted?"
|
|
else
|
|
debug "Mounting /tmp/pulse-socket..."
|
|
sudo mount --bind /tmp/pulse-socket ${jail_dir}/${runas_user}/tmp/pulse-socket
|
|
fi
|
|
else
|
|
debug "/tmp/pulse-socket is already a socket?"
|
|
fi
|
|
|
|
debug "...chroot prepared."
|
|
|
|
debug "Launching as ${runas_user} jailed inside ${jail_dir}/${runas_user}/..."
|
|
sudo -u root -- chroot ${jail_dir}/${runas_user}/ sudo -u ${runas_user} dbus-launch ${app_dir}${run_cmd}${launch_opt}
|
|
fi
|
|
|
|
debug "...returned to wrapper."
|
|
fi
|
|
|
|
|
|
|
|
## If we still exist, clean up.
|
|
debug "Final Notice"
|
|
if [ "${app_check}" ]; then
|
|
check
|
|
fizzle 0
|
|
fi |