Install Battle.net quickly and easily, even for a secondary user
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

496 lines
16KB

  1. #!/bin/bash
  2. ## Copyright © 2018-2020 Bret Human
  3. ## https://cynicaloptimist.me/
  4. ##
  5. ## Documentation at:
  6. ## https://mage.cynicaloptimist.me/en/bn3t
  7. ## https://psi.cynicaloptimist.me/Caffarius/bn3t/
  8. ##
  9. ## For questions or comments write:
  10. ## info@cynicaloptimist.me
  11. #####################################################################
  12. # bn3t
  13. script_ver="0.3"
  14. page="https://mage.cynicaloptimist.me/en/bn3t"
  15. # author: Bret Human
  16. # date: Dec 6, 2018
  17. #
  18. #####################################################################
  19. #
  20. # A wrapper for wrappers, used to install/manage/own a Battle.net
  21. # installation within Wine in a Linux environment.
  22. #
  23. # Extra handy for running Battle.net under a secondary account for
  24. # added security. Can be used for lots of zany wine needs, like
  25. # spawning a multitude of Wine prefixes and installing Battle.net in
  26. # all of them.
  27. #
  28. # This is the first of two scripts. It is meant to be the sanitizer
  29. # crew and the firing squad for bn3t-run. bn3t-run must be installed.
  30. #
  31. # Install bn3t-run for your desired user with:
  32. # ./bn3t.sh -u username -i
  33. #
  34. # Then you can prep the environment and install Battle.net via:
  35. # ./bn3t.sh -u username -bxs
  36. #
  37. # Or I guess you could manually download the script from:
  38. dl_addr="https://psi.cynicaloptimist.me/Caffarius/bn3t/raw/branch/master/bn3t-run.sh"
  39. #####################################################################
  40. #
  41. # This is free software; you are free to change and redistribute it.
  42. # There is NO WARRANTY of any kind.
  43. #
  44. #####################################################################
  45. runas_user="`whoami`"
  46. app_name="Battle.net"
  47. run_cmd="bn3t-run.sh"
  48. jail_dir="/var/jail"
  49. check_wait="3"
  50. usage="bn3t, version ${script_ver}
  51. Usage: ./`basename ${0}` -g (game) -u (user) -p (prefix) -a (arch) -dvksbwtnchxi
  52. -a | Selects the architecture to run as (32 | 64)
  53. -b | Runs wineboot
  54. -c | Launch a console session as specified user (can launch Xapps)
  55. -d | Debug messages on (turns verbose on)
  56. -g | Launches the game of your choice
  57. -h | Help (this message)
  58. -i | Install the bn3t-run script for the specified user - mandantory
  59. -j | Run ${run_cmd} inside a chroot jail at ${jail_dir}
  60. -k | Kill all processes for a user (not current user or root)
  61. -m | Runs Twitch Client (for /M/ods - I'm running out of letters)
  62. -n | No BS mode - doesn't launch an app (for boot/tricks/console safety)
  63. -p | Selects the location of the Wine prefix
  64. -s | Runs ${app_name} setup
  65. -t | Attempts to launch to the system tray
  66. -u | Runs ${app_name} as the user specified
  67. -v | Verbose messages on
  68. -w | Runs winetricks
  69. -x | Force upgrade DXVK
  70. -z | Set the DISPLAY variable used in ${run_cmd}
  71. See more documentation at: ${page}"
  72. # Catch CTRL+C and cleanup
  73. trap "echo '' && inform '---------------------------------' && inform 'Caught CTRL+C' && check" 2
  74. ## Define our functions
  75. function refresh {
  76. app_dir="/home/${runas_user}/.script/"
  77. app_check="ps -ef | grep ${runas_user} | grep Battle.net.exe | grep -v grep"
  78. }
  79. function debug () {
  80. if [ "${app_debug}" ]; then
  81. echo -e "-D- ${1}"
  82. fi
  83. }
  84. function inform () {
  85. if [ "${app_verbose}" ]; then
  86. echo -e "--- ${1}"
  87. fi
  88. }
  89. function buff_cmd_output () {
  90. read cmd_input
  91. cmd_output=$(eval "${cmd_input}")
  92. if [ ! -z "${cmd_output}" ]; then
  93. debug "${cmd_output}"
  94. fi
  95. }
  96. function clean {
  97. debug "Clean"
  98. # Var
  99. unset script_ver
  100. unset page
  101. unset runas_user
  102. unset app_name
  103. unset run_cmd
  104. unset check_wait
  105. unset usage
  106. unset app_dir
  107. unset app_check
  108. unset app_debug
  109. unset app_verbose
  110. unset launch_opt
  111. unset nobs_mode
  112. unset dl_addr
  113. # Func
  114. unset refresh
  115. unset debug
  116. unset inform
  117. unset check
  118. }
  119. function die () {
  120. debug "die"
  121. echo "Cleaning up..."
  122. if [ "`whoami`" == "${runas_user}" ]; then
  123. debug "Launched as original user, not killing processes"
  124. else
  125. if [ "${runas_user}" == "root" ]; then
  126. debug "Root? Madness. Just removing xhost then..."
  127. inform "`xhost -SI:localuser:root`"
  128. else
  129. debug "Launched as ${runas_user}, killing processes and removing xhost..."
  130. sudo -u "${runas_user}" -- bash -c "kill -9 -1"
  131. inform "`xhost -SI:localuser:"${runas_user}"`"
  132. fi
  133. fi
  134. if [ "${jailbird}" == "1" ]; then
  135. debug "Removing root from xhost..."
  136. inform "`xhost -SI:localuser:root`"
  137. debug "Delaying jail demolition..."
  138. sleep 1
  139. debug "Demolishing jail..."
  140. echo "sudo rm ${jail_dir}/${runas_user}/bin 2>&1" | buff_cmd_output
  141. echo "sudo rm ${jail_dir}/${runas_user}/sbin 2>&1" | buff_cmd_output
  142. echo "sudo rm ${jail_dir}/${runas_user}/lib 2>&1" | buff_cmd_output
  143. echo "sudo rm ${jail_dir}/${runas_user}/lib64 2>&1" | buff_cmd_output
  144. echo "sudo umount -l ${jail_dir}/${runas_user}/usr 2>&1" | buff_cmd_output
  145. echo "sudo umount -l ${jail_dir}/${runas_user}/etc 2>&1" | buff_cmd_output
  146. echo "sudo umount -l ${jail_dir}/${runas_user}/tmp/pulse-socket 2>&1" | buff_cmd_output
  147. echo "sudo umount -l ${jail_dir}/${runas_user}/dev 2>&1" | buff_cmd_output
  148. echo "sudo umount -l ${jail_dir}/${runas_user}/proc 2>&1" | buff_cmd_output
  149. echo "sudo umount -l ${jail_dir}/${runas_user}/sys 2>&1" | buff_cmd_output
  150. echo "sudo umount -l ${jail_dir}/${runas_user}/run 2>&1" | buff_cmd_output
  151. echo "sudo umount -l ${jail_dir}/${runas_user}/tmp 2>&1" | buff_cmd_output
  152. echo "sudo umount -l ${jail_dir}/${runas_user}/var 2>&1" | buff_cmd_output
  153. echo "sudo umount -l ${jail_dir}/${runas_user}/home/${runas_user} 2>&1" | buff_cmd_output
  154. debug "Jail demolished."
  155. fi
  156. clean
  157. unset clean
  158. unset fizzle
  159. if [ "$1" ]; then
  160. unset die && exit $1
  161. else
  162. echo "...what?"
  163. unset die && exit 5
  164. fi
  165. exit 5
  166. }
  167. function fizzle () {
  168. debug "fizzle" # https://mtg.gamepedia.com/Fizzle
  169. echo "Exiting..."
  170. clean
  171. unset clean
  172. unset die
  173. if [ "$1" ]; then
  174. unset fizzle && exit $1
  175. else
  176. echo "...what?"
  177. unset fizzle && exit 5
  178. fi
  179. exit 5
  180. }
  181. function check {
  182. debug "check"
  183. i="0"
  184. while [ "${i}" -lt "${check_wait}" ]; do
  185. if [ "$(eval ${app_check})" ]; then
  186. inform "${app_name} is still running. Waiting to see if we need to murder... $[ ${check_wait} - ${i} ]"
  187. sleep 1
  188. else
  189. unset i
  190. die 0
  191. fi
  192. i=$[ $i + 1 ]
  193. done
  194. unset i
  195. }
  196. ## Pick up any arguments provided
  197. # None are required, we'll use default values.
  198. launch_opt=""
  199. while getopts ":a:A:g:G:p:P:u:U:z:Z:bBcCdDhHiIjJkKmMnNsStTvVwWxX" option; do
  200. case "${option}" in
  201. "a"|"A") launch_opt="${launch_opt} -a ${OPTARG}";;
  202. "b"|"B")
  203. inform "Wineboot mode"
  204. launch_opt="${launch_opt} -b"
  205. ;;
  206. "c"|"C")
  207. inform "Console requested"
  208. nobs_mode="y"
  209. launch_opt="${launch_opt} -c"
  210. ;;
  211. "d"|"D")
  212. if [ ! "${app_debug}" ]; then # Let's not do this too much...
  213. app_debug="y"
  214. launch_opt=" -d${launch_opt}"
  215. debug "Debug enabled"
  216. if [ ! "${app_verbose}" ]; then
  217. debug "`realpath "${0}"` version ${script_ver} running as `whoami`"
  218. fi
  219. app_verbose="y"
  220. debug ""
  221. debug "This is free software; you are free to change and redistribute it."
  222. debug "There is NO WARRANTY of any kind."
  223. debug ""
  224. debug "Documentation at: ${page}"
  225. debug ""
  226. fi
  227. ;;
  228. "g"|"G") launch_opt="${launch_opt} -g ${OPTARG}";;
  229. "h"|"H")
  230. echo "${usage}"
  231. fizzle 0
  232. ;;
  233. "i"|"I")
  234. debug "User-side install requested"
  235. refresh
  236. if [ "`whoami`" == "${runas_user}" ]; then
  237. debug "Running as original user, just downloading it"
  238. mkdir -p "${app_dir}" ||
  239. (echo "Failed to make directory ${app_dir}" && fizzle 1)
  240. wget "${dl_addr}" -O "${app_dir}${run_cmd}" ||
  241. (echo "Failed to download script from ${dl_addr}" && fizzle 1)
  242. chmod 700 "${app_dir}${run_cmd}" ||
  243. (echo "Failed to change permissions on ${app_dir}${run_cmd}" && fizzle 1)
  244. else
  245. debug "Running as ${runas_user}, switching and downloading"
  246. sudo -u "${runas_user}" -- mkdir -p "${app_dir}" ||
  247. (echo "Failed to make directory ${app_dir}" && fizzle 1)
  248. sudo -u "${runas_user}" -- wget "${dl_addr}" -O "${app_dir}${run_cmd}" ||
  249. (echo "Failed to download script from ${dl_addr}" && fizzle 1)
  250. sudo -u "${runas_user}" -- chmod 700 "${app_dir}${run_cmd}" ||
  251. (echo "Failed to change permissions on ${app_dir}${run_cmd}" && fizzle 1)
  252. fi
  253. echo "Install process completed."
  254. fizzle 0
  255. ;;
  256. "j"|"J")
  257. debug "Running ${appname} in a chroot jail under ${jail_dir}/${runas_user}/"
  258. jailbird=1
  259. ;;
  260. "k"|"K") die 0;;
  261. "m"|"M")
  262. inform "Twitch mode"
  263. launch_opt="${launch_opt} -m"
  264. ;;
  265. "n"|"N")
  266. inform "No BS mode"
  267. nobs_mode="y"
  268. launch_opt="${launch_opt} -n"
  269. ;;
  270. "p"|"P") launch_opt="${launch_opt} -p ${OPTARG}";;
  271. "s"|"S")
  272. inform "Setup mode"
  273. nobs_mode="y"
  274. launch_opt="${launch_opt} -s"
  275. ;;
  276. "t"|"T")
  277. debug "Hiding to system tray"
  278. launch_opt="${launch_opt} -t"
  279. ;;
  280. "u"|"U")
  281. debug "Setting user to ${OPTARG}"
  282. runas_user="${OPTARG}"
  283. ;;
  284. "v"|"V")
  285. if [ ! "${app_debug}" ]; then
  286. if [ ! "${app_verbose}" ]; then
  287. app_verbose="y"
  288. inform "Verbose enabled"
  289. inform "`realpath "${0}"` version ${script_ver} running as `whoami`"
  290. launch_opt=" -v${launch_opt}"
  291. fi
  292. fi
  293. ;;
  294. "w"|"W")
  295. inform "Winetricks mode"
  296. launch_opt="${launch_opt} -w"
  297. ;;
  298. "x"|"X")
  299. inform "Force upgrading dxvk"
  300. launch_opt="${launch_opt} -x"
  301. ;;
  302. "z"|"Z")
  303. inform "Setting DISPLAY to ${OPTARG}"
  304. launch_opt="${launch_opt} -z ${OPTARG}"
  305. ;;
  306. * ) echo "Unknown option: -${OPTARG}"
  307. echo "${usage}"
  308. fizzle 1
  309. ;;
  310. esac
  311. done
  312. debug "launch_opt:${launch_opt}"
  313. ## Pass our knowledge on.
  314. refresh
  315. debug "run_app"
  316. if [ "`whoami`" == "${runas_user}" ]; then
  317. debug "Launching as original user, going native"
  318. ${app_dir}${run_cmd}${launch_opt}
  319. else
  320. debug "Checking xhost"
  321. if [ ! "`xhost | grep ${runas_user}`" ]; then
  322. inform "`xhost +SI:localuser:"${runas_user}"`"
  323. fi
  324. if [ ! "${jailbird}" == "1" ]; then
  325. # Just launch it as a regular secondary user app
  326. debug "Launching as ${runas_user}..."
  327. sudo -u "${runas_user}" -- dbus-launch ${app_dir}${run_cmd}${launch_opt}
  328. else
  329. # Hooooooowiiiiiiee. We're gonna build a jail!
  330. if [ ! "`xhost | grep root`" ]; then
  331. inform "`xhost +SI:localuser:root`"
  332. fi
  333. debug "Preparing ${runas_user}'s chroot environment..."
  334. sudo mkdir -p ${jail_dir}/${runas_user}/tmp
  335. sudo mkdir -p ${jail_dir}/${runas_user}/usr
  336. sudo mkdir -p ${jail_dir}/${runas_user}/var
  337. sudo mkdir -p ${jail_dir}/${runas_user}/proc
  338. sudo mkdir -p ${jail_dir}/${runas_user}/sys
  339. sudo mkdir -p ${jail_dir}/${runas_user}/dev
  340. sudo mkdir -p ${jail_dir}/${runas_user}/run
  341. sudo mkdir -p ${jail_dir}/${runas_user}/etc
  342. sudo mkdir -p ${jail_dir}/${runas_user}/home/${runas_user}
  343. if mountpoint ${jail_dir}/${runas_user}/tmp > /dev/null; then
  344. debug "/tmp is already mounted?"
  345. else
  346. debug "Mounting /tmp..."
  347. sudo mount -t tmpfs -o size=2G tmpfs ${jail_dir}/${runas_user}/tmp
  348. fi
  349. if mountpoint ${jail_dir}/${runas_user}/proc > /dev/null; then
  350. debug "/proc is already mounted?"
  351. else
  352. debug "Mounting /proc..."
  353. sudo mount --bind /proc ${jail_dir}/${runas_user}/proc
  354. fi
  355. if mountpoint ${jail_dir}/${runas_user}/sys > /dev/null; then
  356. debug "/sys is already mounted?"
  357. else
  358. debug "Mounting /sys..."
  359. sudo mount --bind /sys ${jail_dir}/${runas_user}/sys
  360. fi
  361. if mountpoint ${jail_dir}/${runas_user}/dev > /dev/null; then
  362. debug "/dev is already mounted?"
  363. else
  364. debug "Mounting /dev..."
  365. sudo mount --bind /dev ${jail_dir}/${runas_user}/dev
  366. fi
  367. if mountpoint ${jail_dir}/${runas_user}/run > /dev/null; then
  368. debug "/run is already mounted?"
  369. else
  370. debug "Mounting /run..."
  371. sudo mount --bind /run ${jail_dir}/${runas_user}/run
  372. fi
  373. if mountpoint ${jail_dir}/${runas_user}/var > /dev/null; then
  374. debug "/var is already mounted?"
  375. else
  376. debug "Mounting /var..."
  377. sudo mount --bind /var ${jail_dir}/${runas_user}/var
  378. fi
  379. if mountpoint ${jail_dir}/${runas_user}/etc > /dev/null; then
  380. debug "/etc is already mounted?"
  381. else
  382. debug "Mounting /etc..."
  383. sudo mount --bind /etc ${jail_dir}/${runas_user}/etc
  384. fi
  385. if mountpoint ${jail_dir}/${runas_user}/usr > /dev/null; then
  386. debug "/usr is already mounted?"
  387. else
  388. debug "Mounting /usr..."
  389. sudo mount --bind /usr ${jail_dir}/${runas_user}/usr
  390. fi
  391. if mountpoint ${jail_dir}/${runas_user}/home/${runas_user} > /dev/null; then
  392. debug "/home/${runas_user} is already mounted?"
  393. else
  394. debug "Mounting /home/${runas_user}..."
  395. sudo mount --bind /mnt/ace/home/${runas_user} ${jail_dir}/${runas_user}/home/${runas_user}
  396. fi
  397. if [ ! -d ${jail_dir}/${runas_user}/bin ]; then
  398. debug "Linking /bin to usr/bin..."
  399. sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/bin bin"
  400. fi
  401. if [ ! -d ${jail_dir}/${runas_user}/sbin ]; then
  402. debug "Linking /sbin to usr/bin (that's not a typo!)..."
  403. sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/bin sbin"
  404. fi
  405. if [ ! -d ${jail_dir}/${runas_user}/lib ]; then
  406. debug "Linking /lib to usr/lib..."
  407. sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/lib lib"
  408. fi
  409. if [ ! -d ${jail_dir}/${runas_user}/lib64 ]; then
  410. debug "Linking /lib64 to usr/lib (that's not a typo!)..."
  411. sudo bash -c "cd ${jail_dir}/${runas_user}; ln -s usr/lib lib64"
  412. fi
  413. if [ ! -S ${jail_dir}/${runas_user}/tmp/pulse-socket ]; then
  414. if [ ! -f ${jail_dir}/${runas_user}/tmp/pulse-socket ]; then
  415. debug "Creating /tmp/pulse-socket to link sound..."
  416. sudo -u ${runas_user} touch ${jail_dir}/${runas_user}/tmp/pulse-socket
  417. fi
  418. if mountpoint ${jail_dir}/${runas_user}/tmp/pulse-socket > /dev/null; then
  419. debug "/tmp/pulse-socket is already mounted?"
  420. else
  421. debug "Mounting /tmp/pulse-socket..."
  422. sudo mount --bind /tmp/pulse-socket ${jail_dir}/${runas_user}/tmp/pulse-socket
  423. fi
  424. else
  425. debug "/tmp/pulse-socket is already a socket?"
  426. fi
  427. debug "...chroot prepared."
  428. debug "Launching as ${runas_user} jailed inside ${jail_dir}/${runas_user}/..."
  429. sudo -u root -- chroot ${jail_dir}/${runas_user}/ sudo -u ${runas_user} dbus-launch ${app_dir}${run_cmd}${launch_opt}
  430. fi
  431. debug "...returned to wrapper."
  432. fi
  433. ## If we still exist, clean up.
  434. debug "Final Notice"
  435. if [ "${app_check}" ]; then
  436. check
  437. fizzle 0
  438. fi