Ver código fonte

feat(update-lgsm): LinuxGSM update refactor (#2884)

This update is a major refactor of how LinuxGSM updates itself.
* will now use a version tag if downloading module for the first time.
* added backup repo (Bitbucket) that will be used if Github is unavailable.
* added ./gameserver and module version comparison this will allow instances to be correctly updated if there is a version mismatch.
* UI changes when modules are fetched for the first time
* added sessionname to fix broken tmux session is ./gameserver is called ./gameserver.sh
* change apt to apt-get as recommended by the apt packages when dealing with scripts.
Daniel Gibbs 6 anos atrás
pai
commit
a76cd3f7b3

+ 4 - 0
lgsm/functions/check.sh

@@ -14,6 +14,10 @@ if [ "${commandname}" != "INSTALL" ]; then
 	check_root.sh
 fi
 
+if [ "${commandname}" != "UPDATE-LGSM" ]; then
+	check_version.sh
+fi
+
 check_tmuxception.sh
 
 if [ "$(whoami)" != "root" ]; then

+ 7 - 7
lgsm/functions/check_deps.sh

@@ -26,13 +26,13 @@ fn_install_mono_repo(){
 			echo -en "   \r"
 			if [ "${distroid}" == "ubuntu" ]; then
 				if [ "${distroversion}" == "18.04" ]; then
-					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/ubuntu stable-bionic main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/ubuntu stable-bionic main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt-get update"
 					eval "${cmd}"
 				elif [ "${distroversion}" == "16.04" ]; then
-					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt install apt-transport-https;echo 'deb https://download.mono-project.com/repo/ubuntu stable-xenial main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt-get install apt-transport-https;echo 'deb https://download.mono-project.com/repo/ubuntu stable-xenial main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt-get update"
 					eval "${cmd}"
 				elif [ "${distroversion}" == "14.04" ]; then
-					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt install apt-transport-https;echo 'deb https://download.mono-project.com/repo/ubuntu stable-trusty main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt-get install apt-transport-https;echo 'deb https://download.mono-project.com/repo/ubuntu stable-trusty main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt-get update"
 					eval "${cmd}"
 				else
 					fn_print_warn_nl "Installing Mono repository."
@@ -43,13 +43,13 @@ fn_install_mono_repo(){
 				fi
 			elif [ "${distroid}" == "debian" ]; then
 				if [ "${distroversion}" == "10" ]; then
-					cmd="sudo apt install apt-transport-https dirmngr;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/debian stable-buster main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+					cmd="sudo apt-get install apt-transport-https dirmngr;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/debian stable-buster main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt-get update"
 					eval "${cmd}"
 				elif [ "${distroversion}" == "9" ]; then
-					cmd="sudo apt install apt-transport-https dirmngr;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/debian stable-stretch main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+					cmd="sudo apt-get install apt-transport-https dirmngr;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/debian stable-stretch main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt-get update"
 					eval "${cmd}"
 				elif [ "${distroversion}" == "8" ]; then
-					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt install apt-transport-https;echo 'deb https://download.mono-project.com/repo/debian stable-jessie main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+					cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt-get install apt-transport-https;echo 'deb https://download.mono-project.com/repo/debian stable-jessie main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt-get update"
 					eval "${cmd}"
 				else
 					echo -e "Mono auto install not available for ${distroname}"
@@ -248,7 +248,7 @@ fn_found_missing_deps(){
 			sleep 1
 			echo -en "   \r"
 			if [ "$(command -v dpkg-query 2>/dev/null)" ]; then
-				cmd="echo steamcmd steam/question select \"I AGREE\" | sudo debconf-set-selections; echo steamcmd steam/license note '' | sudo debconf-set-selections; sudo dpkg --add-architecture i386; sudo apt update; sudo apt -y install ${array_deps_missing[*]}"
+				cmd="echo steamcmd steam/question select \"I AGREE\" | sudo debconf-set-selections; echo steamcmd steam/license note '' | sudo debconf-set-selections; sudo dpkg --add-architecture i386; sudo apt-get update; sudo apt-get -y install ${array_deps_missing[*]}"
 				eval "${cmd}"
 			elif [ "$(command -v dnf 2>/dev/null)" ]; then
 				cmd="sudo dnf -y install ${array_deps_missing[*]}"

+ 1 - 1
lgsm/functions/check_status.sh

@@ -7,4 +7,4 @@
 
 functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
-status=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | grep -Ecx "^${selfname}")
+status=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | grep -Ecx "^${sessionname}")

+ 11 - 1
lgsm/functions/check_steamcmd.sh

@@ -13,7 +13,17 @@ fn_install_steamcmd(){
 	if [ ! -d "${steamcmddir}" ]; then
 		mkdir -p "${steamcmddir}"
 	fi
-	fn_fetch_file "http://media.steampowered.com/client/steamcmd_linux.tar.gz" "${tmpdir}" "steamcmd_linux.tar.gz"
+	remote_fileurl="${1}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
+	fn_fetch_file "http://media.steampowered.com/client/steamcmd_linux.tar.gz" "" "" "" "${tmpdir}" "steamcmd_linux.tar.gz" "" "norun" "noforce" "nomd5"
 	fn_dl_extract "${tmpdir}" "steamcmd_linux.tar.gz" "${steamcmddir}"
 	chmod +x "${steamcmddir}/steamcmd.sh"
 }

+ 19 - 0
lgsm/functions/check_version.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+# LinuxGSM command_version.sh function
+# Author: Daniel Gibbs
+# Website: https://linuxgsm.com
+# Description: Will run update-lgsm if gameserver.sh and modules version does not match
+# this will allow gameserver.sh to update - useful for multi instance servers.
+
+if [ -n "${modulesversion}" ]&&[ -n "${version}" ]&&[ "${version}" != "${modulesversion}" ]; then
+	exitbypass=1
+	echo -e ""
+	fn_print_error_nl "LinuxGSM version mismatch"
+	echo -e ""
+	echo -e "* ${selfname}: ${version}"
+	echo -e "* modules: ${modulesversion}"
+	echo -e ""
+	fn_sleep_time
+	fn_script_log_error "LinuxGSM Version mismatch: ${selfname}: ${version}: modules: ${modulesversion}"
+	command_update_linuxgsm.sh
+fi

+ 1 - 1
lgsm/functions/command_console.sh

@@ -26,7 +26,7 @@ check_status.sh
 if [ "${status}" != "0" ]; then
 	fn_print_ok_nl "Accessing console"
 	fn_script_log_pass "Console accessed"
-	tmux attach-session -t "${selfname}"
+	tmux attach-session -t "${sessionname}"
 	fn_print_ok_nl "Closing console"
 	fn_script_log_pass "Console closed"
 else

+ 1 - 1
lgsm/functions/command_dev_query_raw.sh

@@ -44,7 +44,7 @@ echo -e ""
 echo -e "./query_gsquery.py -a \"${ip}\" -p \"${queryport}\" -e \"${querytype}\""
 echo -e ""
 if [ ! -f "${functionsdir}/query_gsquery.py" ]; then
-	fn_fetch_file_github "lgsm/functions" "query_gsquery.py" "${functionsdir}" "chmodx" "norun" "noforce" "nomd5"
+	fn_fetch_file_git "lgsm/functions" "query_gsquery.py" "${functionsdir}" "chmodx" "norun" "noforce" "nomd5"
 fi
 "${functionsdir}"/query_gsquery.py -a "${ip}" -p "${queryport}" -e "${querytype}"
 

+ 1 - 1
lgsm/functions/command_monitor.sh

@@ -84,7 +84,7 @@ fn_monitor_check_queryport(){
 
 fn_query_gsquery(){
 	if [ ! -f "${functionsdir}/query_gsquery.py" ]; then
-		fn_fetch_file_github "lgsm/functions" "query_gsquery.py" "${functionsdir}" "chmodx" "norun" "noforce" "nomd5"
+		fn_fetch_file_git "lgsm/functions" "query_gsquery.py" "${functionsdir}" "chmodx" "norun" "noforce" "nomd5"
 	fi
 	"${functionsdir}"/query_gsquery.py -a "${ip}" -p "${queryport}" -e "${querytype}" > /dev/null 2>&1
 	querystatus="$?"

+ 10 - 11
lgsm/functions/command_start.sh

@@ -64,7 +64,7 @@ fn_start_tmux(){
 	# Create lockfile
 	date '+%s' > "${lockdir}/${selfname}.lock"
 	cd "${executabledir}" || exit
-	tmux new-session -d -x "${sessionwidth}" -y "${sessionheight}" -s "${selfname}" "${executable} ${parms}" 2> "${lgsmlogdir}/.${selfname}-tmux-error.tmp"
+	tmux new-session -d -x "${sessionwidth}" -y "${sessionheight}" -s "${sessionname}" "${executable} ${parms}" 2> "${lgsmlogdir}/.${selfname}-tmux-error.tmp"
 
 	# Create logfile.
 	touch "${consolelog}"
@@ -79,7 +79,7 @@ fn_start_tmux(){
 		fn_script_log "Tmux version: master (user compiled)"
 		echo -e "Tmux version: master (user compiled)" >> "${consolelog}"
 		if [ "${consolelogging}" == "on" ]||[ -z "${consolelogging}" ]; then
-			tmux pipe-pane -o -t "${selfname}" "exec cat >> '${consolelog}'"
+			tmux pipe-pane -o -t "${sessionname}" "exec cat >> '${consolelog}'"
 		fi
 	elif [ "${tmuxversion}" ]; then
 		# Get the digit version of tmux.
@@ -97,19 +97,19 @@ fn_start_tmux(){
 			Currently installed: $(tmux -V)" > "${consolelog}"
 		# Console logging enable or not set.
 		elif [ "${consolelogging}" == "on" ]||[ -z "${consolelogging}" ]; then
-			tmux pipe-pane -o -t "${selfname}" "exec cat >> '${consolelog}'"
+			tmux pipe-pane -o -t "${sessionname}" "exec cat >> '${consolelog}'"
 		fi
 	else
 		echo -e "Unable to detect tmux version" >> "${consolelog}"
 		fn_script_log_warn "Unable to detect tmux version"
 	fi
 
-# Console logging disabled.
-if [ "${consolelogging}" == "off" ]; then
-	echo -e "Console logging disabled by user" >> "${consolelog}"
-	fn_script_log_info "Console logging disabled by user"
-fi
-fn_sleep_time
+	# Console logging disabled.
+	if [ "${consolelogging}" == "off" ]; then
+		echo -e "Console logging disabled by user" >> "${consolelog}"
+		fn_script_log_info "Console logging disabled by user"
+	fi
+	fn_sleep_time
 
 	# If the server fails to start.
 	check_status.sh
@@ -122,7 +122,7 @@ fn_sleep_time
 			echo -e ""
 			echo -e "Command"
 			echo -e "================================="
-			echo -e "tmux new-session -d -s \"${selfname}\" \"${executable} ${parms}\"" | tee -a "${lgsmlog}"
+			echo -e "tmux new-session -d -s \"${sessionname}\" \"${executable} ${parms}\"" | tee -a "${lgsmlog}"
 			echo -e ""
 			echo -e "Error"
 			echo -e "================================="
@@ -156,7 +156,6 @@ fn_sleep_time
 				fi
 			fi
 		fi
-
 		core_exit.sh
 	else
 		fn_print_ok "${servername}"

+ 7 - 7
lgsm/functions/command_stop.sh

@@ -14,7 +14,7 @@ fn_stop_graceful_ctrlc(){
 	fn_print_dots "Graceful: CTRL+c"
 	fn_script_log_info "Graceful: CTRL+c"
 	# Sends quit.
-	tmux send-keys -t "${selfname}" C-c  > /dev/null 2>&1
+	tmux send-keys -t "${sessionname}" C-c  > /dev/null 2>&1
 	# Waits up to 30 seconds giving the server time to shutdown gracefuly.
 	for seconds in {1..30}; do
 		check_status.sh
@@ -42,7 +42,7 @@ fn_stop_graceful_cmd(){
 	fn_print_dots "Graceful: sending \"${1}\""
 	fn_script_log_info "Graceful: sending \"${1}\""
 	# Sends specific stop command.
-	tmux send -t "${selfname}" "${1}" ENTER > /dev/null 2>&1
+	tmux send -t "${sessionname}" "${1}" ENTER > /dev/null 2>&1
 	# Waits up to ${seconds} seconds giving the server time to shutdown gracefully.
 	for ((seconds=1; seconds<=${2}; seconds++)); do
 		check_status.sh
@@ -70,7 +70,7 @@ fn_stop_graceful_goldsrc(){
 	fn_print_dots "Graceful: sending \"quit\""
 	fn_script_log_info "Graceful: sending \"quit\""
 	# sends quit
-	tmux send -t "${selfname}" quit ENTER > /dev/null 2>&1
+	tmux send -t "${sessionname}" quit ENTER > /dev/null 2>&1
 	# Waits 3 seconds as goldsrc servers restart with the quit command.
 	for seconds in {1..3}; do
 		sleep 1
@@ -183,10 +183,10 @@ fn_stop_graceful_avorion(){
 	fn_print_dots "Graceful: /save /stop"
 	fn_script_log_info "Graceful: /save /stop"
 	# Sends /save.
-	tmux send-keys -t "${selfname}" /save ENTER > /dev/null 2>&1
+	tmux send-keys -t "${sessionname}" /save ENTER > /dev/null 2>&1
 	sleep 5
 	# Sends /quit.
-	tmux send-keys -t "${selfname}" /stop ENTER > /dev/null 2>&1
+	tmux send-keys -t "${sessionname}" /stop ENTER > /dev/null 2>&1
 	# Waits up to 30 seconds giving the server time to shutdown gracefuly.
 	for seconds in {1..30}; do
 		check_status.sh
@@ -233,9 +233,9 @@ fn_stop_graceful_select(){
 
 fn_stop_tmux(){
 	fn_print_dots "${servername}"
-	fn_script_log_info "tmux kill-session: ${servername}"
+	fn_script_log_info "tmux kill-session: ${sessionname}: ${servername}"
 	# Kill tmux session.
-	tmux kill-session -t "${selfname}" > /dev/null 2>&1
+	tmux kill-session -t "${sessionname}" > /dev/null 2>&1
 	sleep 0.5
 	check_status.sh
 	if [ "${status}" == "0" ]; then

+ 160 - 72
lgsm/functions/command_update_linuxgsm.sh

@@ -8,109 +8,197 @@ commandname="UPDATE-LGSM"
 commandaction="Updating LinuxGSM"
 functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
-fn_print_dots "Updating LinuxGSM"
 check.sh
+
+fn_print_dots ""
 fn_script_log_info "Updating LinuxGSM"
-echo -en "\n"
 
-if [ -z "${legacymode}" ]; then
-	# Check and update _default.cfg.
-	echo -en "    checking config _default.cfg...\c"
-	config_file_diff=$(diff "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" <(curl -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/lgsm/config-default/config-lgsm/${gameservername}/_default.cfg"))
-	if [ "${config_file_diff}" != "" ]; then
-		fn_print_update_eol_nl
-		fn_script_log_info "checking config _default.cfg: UPDATE"
-		rm -f "${configdirdefault:?}/config-lgsm/${gameservername}/_default.cfg"
-		fn_fetch_config "lgsm/config-default/config-lgsm/${gameservername}" "_default.cfg" "${configdirdefault}/config-lgsm/${gameservername}" "_default.cfg" "nochmodx" "norun" "noforce" "nomd5"
-		alert="config"
-		alert.sh
+fn_print_dots "Selecting repo"
+fn_script_log_info "Selecting repo"
+# Select remotereponame
+curl -IsfL "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/linuxgsm.sh" 1>/dev/null
+if [ $? != "0" ]; then
+	curl -IsfL "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/linuxgsm.sh" 1>/dev/null
+	if [ $? != "0" ]; then
+		fn_print_fail_nl "Selecting repo: Unable to to access GitHub or Bitbucket repositories"
+		fn_script_log_fatal "Selecting repo: Unable to to access GitHub or Bitbucket repositories"
+		core_exit.sh
 	else
-		fn_print_ok_eol_nl
-		fn_script_log_info "checking config _default.cfg: OK"
+		remotereponame="Bitbucket"
+		fn_print_ok_nl "Selecting repo: ${remotereponame}"
 	fi
+else
+	remotereponame="GitHub"
+	fn_print_ok_nl "Selecting repo: ${remotereponame}"
+fi
+
+# Check _default.cfg.
+echo -en "checking ${remotereponame} config _default.cfg...\c"
+fn_script_log_info "Checking ${remotereponame} config _default.cfg"
+if [ "${remotereponame}" == "GitHub" ]; then
+	curl -IsfL "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/lgsm/config-default/config-lgsm/${gameservername}/_default.cfg" 1>/dev/null
+else
+	curl -IsfL "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/lgsm/config-default/config-lgsm/${gameservername}/_default.cfg" 1>/dev/null
+fi
+if [ $? != "0" ]; then
+	fn_print_fail_eol_nl
+	fn_script_log_fatal "Checking ${remotereponame} config _default.cfg"
+	fn_script_log_fatal "Curl returned error: $?"
+	core_exit.sh
+fi
+
+if [ "${remotereponame}" == "GitHub" ]; then
+	config_file_diff=$(diff "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" <(curl -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/lgsm/config-default/config-lgsm/${gameservername}/_default.cfg"))
+else
+	config_file_diff=$(diff "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" <(curl -s "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/lgsm/config-default/config-lgsm/${gameservername}/_default.cfg"))
+fi
+
+if [ "${config_file_diff}" != "" ]; then
+	fn_print_update_eol_nl
+	fn_script_log_update "Checking ${remotereponame} config _default.cfg"
+	rm -f "${configdirdefault:?}/config-lgsm/${gameservername:?}/_default.cfg"
+	fn_fetch_file_github "lgsm/config-default/config-lgsm/${gameservername}" "_default.cfg" "${configdirdefault}/config-lgsm/${gameservername}" "nochmodx" "norun" "noforce" "nomd5"
+	alert="config"
+	alert.sh
+else
+	fn_print_ok_eol_nl
+	fn_script_log_pass "Checking ${remotereponame} config _default.cfg"
+fi
+
+# Check linuxsm.sh
+echo -en "checking ${remotereponame} linuxgsm.sh...\c"
+if [ "${remotereponame}" == "GitHub" ]; then
+	curl -IsfL "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/linuxgsm.sh" 1>/dev/null
+else
+	curl -IsfL "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/linuxgsm.sh" 1>/dev/null
+fi
+if [ $? != "0" ]; then
+	fn_print_fail_eol_nl
+	fn_script_log_fatal "Checking ${remotereponame} linuxgsm.sh"
+	fn_script_log_fatal "Curl returned error: $?"
+	core_exit.sh
+fi
 
-	echo -en "    checking linuxgsm.sh...\c"
+if [ "${remotereponame}" == "GitHub" ]; then
 	tmp_script_diff=$(diff "${tmpdir}/linuxgsm.sh" <(curl -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/linuxgsm.sh"))
-	if [ "${tmp_script_diff}" != "" ]; then
-		fn_print_update_eol_nl
-		fn_script_log_info "checking linuxgsm.sh: UPDATE"
-		rm -f "${tmpdir:?}/linuxgsm.sh"
-		fn_fetch_file_github "" "linuxgsm.sh" "${tmpdir}" "nochmodx" "norun" "noforcedl" "nomd5"
-		# Compare selfname against linuxgsm.sh in the tmp dir. Ignoring server specific vars.
+else
+	tmp_script_diff=$(diff "${tmpdir}/linuxgsm.sh" <(curl -s "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/linuxgsm.sh"))
+fi
+
+if [ "${tmp_script_diff}" != "" ]; then
+	fn_print_update_eol_nl
+	fn_script_log_update "Checking ${remotereponame} linuxgsm.sh"
+	rm -f "${tmpdir:?}/linuxgsm.sh"
+	fn_fetch_file_github "" "linuxgsm.sh" "${tmpdir}" "nochmodx" "norun" "noforcedl" "nomd5"
+else
+	fn_print_ok_eol_nl
+	fn_script_log_pass "Checking ${remotereponame} linuxgsm.sh"
+fi
+
+# Check gameserver.sh
+# Compare gameserver.sh against linuxgsm.sh in the tmp dir.
+# Ignoring server specific vars.
+echo -en "checking ${selfname}...\c"
+fn_script_log_info "Checking ${selfname}"
+echo "TMPDIR: ${tmpdir}"
+echo "ROOTDIR: ${rootdir}"
+echo "SELFNAME: ${selfname}"
+script_diff=$(diff <(sed '\/shortname/d;\/gameservername/d;\/gamename/d;\/githubuser/d;\/githubrepo/d;\/githubbranch/d' "${tmpdir}/linuxgsm.sh") <(sed '\/shortname/d;\/gameservername/d;\/gamename/d;\/githubuser/d;\/githubrepo/d;\/githubbranch/d' "${rootdir}/${selfname}"))
+echo "=========================================="
+if [ "${script_diff}" != "" ]; then
+	fn_print_update_eol_nl
+	fn_script_log_update "Checking ${selfname}"
+	echo -en "backup ${selfname}...\c"
+	fn_script_log_info "Backup ${selfname}"
+	if [ ! -d "${backupdir}/script" ]; then
+		mkdir -p "${backupdir}/script"
+	fi
+	cp "${rootdir}/${selfname}" "${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak"
+	if [ $? -ne 0 ]; then
+		fn_print_fail_eol_nl
+		fn_script_log_fatal "Backup ${selfname}"
+		core_exit.sh
 	else
-		fn_script_log_info "checking linuxgsm.sh: OK"
 		fn_print_ok_eol_nl
+		fn_script_log_pass "Backup ${selfname}"
+		echo -e "backup location ${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak"
+		fn_script_log_pass "Backup location ${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak"
 	fi
-	echo -en "    checking ${selfname}...\c"
-	script_diff=$(diff <(sed '\/shortname/d;\/gameservername/d;\/gamename/d;\/githubuser/d;\/githubrepo/d;\/githubbranch/d' "${tmpdir}/linuxgsm.sh") <(sed '\/shortname/d;\/gameservername/d;\/gamename/d;\/githubuser/d;\/githubrepo/d;\/githubbranch/d' "${rootdir}/${selfname}"))
-	if [ "${script_diff}" != "" ]; then
-		fn_print_update_eol_nl
-		echo -en "    backup ${selfname}...\c"
-		mkdir -p "${backupdir}/script/"
-		cp "${rootdir}/${selfname}" "${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak"
-		if [ $? -ne 0 ]; then
-			fn_print_fail_eol_nl
-			core_exit.sh
-		else
-			fn_print_ok_eol_nl
-			echo -e "	Backup: ${backupdir}/script/${selfname}-$(date +"%m_%d_%Y_%M").bak"
-		fi
-		echo -en "    fetching ${selfname}...\c"
-		cp "${tmpdir}/linuxgsm.sh" "${rootdir}/${selfname}"
-		sed -i "s/shortname=\"core\"/shortname=\"${shortname}\"/g" "${rootdir}/${selfname}"
-		sed -i "s/gameservername=\"core\"/gameservername=\"${gameservername}\"/g" "${rootdir}/${selfname}"
-		sed -i "s/gamename=\"core\"/gamename=\"${gamename}\"/g" "${rootdir}/${selfname}"
-		exitcode=$?
-		if [ "${exitcode}" != "0" ]; then
-			fn_print_fail_eol_nl
-			core_exit.sh
-		else
-			fn_print_ok_eol_nl
-		fi
+
+	echo -en "copying ${selfname}...\c"
+	fn_script_log_info "copying ${selfname}"
+	cp "${tmpdir}/linuxgsm.sh" "${rootdir}/${selfname}"
+	sed -i "s+shortname=\"core\"+shortname=\"${shortname}\"+g" "${rootdir}/${selfname}"
+	sed -i "s+gameservername=\"core\"+gameservername=\"${gameservername}\"+g" "${rootdir}/${selfname}"
+	sed -i "s+gamename=\"core\"+gamename=\"${gamename}\"+g" "${rootdir}/${selfname}"
+	sed -i "s+githubuser=\"GameServerManagers\"+githubuser=\"${githubuser}\"+g" "${rootdir}/${selfname}"
+	sed -i "s+githubrepo=\"LinuxGSM\"+githubrepo=\"${githubrepo}\"+g" "${rootdir}/${selfname}"
+	sed -i "s+githubbranch=\"master\"+githubbranch=\"${githubbranch}\"+g" "${rootdir}/${selfname}"
+
+	if [ $? != "0" ]; then
+		fn_print_fail_eol_nl
+		fn_script_log_fatal "copying ${selfname}"
+		core_exit.sh
 	else
 		fn_print_ok_eol_nl
+		fn_script_log_pass "copying ${selfname}"
 	fi
+else
+	fn_print_ok_eol_nl
+	fn_script_log_info "Checking ${selfname}"
 fi
 
-# Check and update functions.
-if [ "${functionsdir}" ]; then
+# Check and update modules.
+if [ -n "${functionsdir}" ]; then
 	if [ -d "${functionsdir}" ]; then
 		cd "${functionsdir}" || exit
 		for functionfile in *
 		do
-			echo -en "    checking function ${functionfile}...\c"
+			# check if module exists in the repo and remove if missing.
+			# commonly used if module names change.
+			echo -en "checking ${remotereponame} module ${functionfile}...\c"
 			github_file_url_dir="lgsm/functions"
-			get_function_file=$(curl --fail -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${functionfile}")
-			exitcode=$?
-			function_file_diff=$(diff "${functionsdir}/${functionfile}" <(curl --fail -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${functionfile}"))
-			if [ ${exitcode} -ne 0 ]; then
-				fn_print_fail_eol_nl
-				echo -en "    removing unknown function ${functionfile}...\c"
-				fn_script_log_fatal "removing unknown function ${functionfile}"
+			if [ "${remotereponame}" == "GitHub" ]; then
+				curl -IsfL "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${functionfile}" 1>/dev/null
+			else
+				curl -IsfL "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${functionfile}" 1>/dev/null
+			fi
+			if [ $? -ne 0 ]; then
+				fn_print_error_eol_nl
+				fn_script_log_error "Checking ${remotereponame} module ${functionfile}"
+				echo -en "removing module ${functionfile}...\c"
 				if ! rm -f "${functionfile:?}"; then
 					fn_print_fail_eol_nl
+					fn_script_log_fatal "Removing module ${functionfile}"
 					core_exit.sh
 				else
 					fn_print_ok_eol_nl
+					fn_script_log_pass "Removing module ${functionfile}"
 				fi
-			elif [ "${function_file_diff}" != "" ]; then
-				fn_print_update_eol_nl
-				fn_script_log_info "checking function ${functionfile}: UPDATE"
-				rm -rf "${functionsdir:?}/${functionfile}"
-				fn_update_function
 			else
-				fn_print_ok_eol_nl
+				# compare file
+				if [ "${remotereponame}" == "GitHub" ]; then
+					function_file_diff=$(diff "${functionsdir}/${functionfile}" <(curl -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${functionfile}"))
+				else
+					function_file_diff=$(diff "${functionsdir}/${functionfile}" <(curl -s "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${functionfile}"))
+				fi
+
+				# results
+				if [ "${function_file_diff}" != "" ]; then
+					fn_print_update_eol_nl
+					fn_script_log_update "Checking ${remotereponame} module ${functionfile}"
+					rm -rf "${functionsdir:?}/${functionfile}"
+					fn_update_function
+				else
+					fn_print_ok_eol_nl
+					fn_script_log_pass "Checking ${remotereponame} module ${functionfile}"
+				fi
 			fi
 		done
 	fi
 fi
 
-if [ "${exitcode}" != "0" ]&&[ -n "${exitcode}" ]; then
-	fn_print_fail "Updating functions"
-	fn_script_log_fatal "Updating functions"
-else
-	fn_print_ok "Updating functions"
-	fn_script_log_pass "Updating functions"
-fi
+fn_print_ok "Updating functions"
+fn_script_log_pass "Updating functions"
 
 core_exit.sh

+ 0 - 1
lgsm/functions/command_validate.sh

@@ -79,7 +79,6 @@ fn_stop_warning(){
 fn_print_dots "Validating server"
 fn_print_dots "Validating server: SteamCMD"
 check.sh
-check_status.sh
 if [ "${status}" != "0" ]; then
 	fn_stop_warning
 	exitbypass=1

+ 132 - 60
lgsm/functions/core_dl.sh

@@ -112,54 +112,99 @@ fn_fetch_trap(){
 
 fn_fetch_file(){
 	remote_fileurl="${1}"
-	local_filedir="${2}"
-	local_filename="${3}"
-	chmodx="${4:-0}"
-	run="${5:-0}"
-	forcedl="${6:-0}"
-	md5="${7:-0}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
 
 	# Download file if missing or download forced.
 	if [ ! -f "${local_filedir}/${local_filename}" ]||[ "${forcedl}" == "forcedl" ]; then
-		if [ ! -d "${local_filedir}" ]; then
-			mkdir -p "${local_filedir}"
-		fi
-		# Trap will remove part downloaded files if canceled.
-		trap fn_fetch_trap INT
-		# Larger files show a progress bar.
-		if [ "${local_filename##*.}" == "bz2" ]||[ "${local_filename##*.}" == "gz" ]||[ "${local_filename##*.}" == "zip" ]||[ "${local_filename##*.}" == "jar" ]||[ "${local_filename##*.}" == "xz" ]; then
-			echo -en "downloading ${local_filename}..."
-			fn_sleep_time
-			echo -en "\033[1K"
-			curlcmd=$(curl --progress-bar --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}")
-			echo -en "downloading ${local_filename}..."
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=( remote_fileurl remote_fileurl_backup )
 		else
-			echo -en "    fetching ${local_filename}...\c"
-			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}" 2>&1)
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=( remote_fileurl )
 		fi
-		local exitcode=$?
-		if [ ${exitcode} -ne 0 ]; then
-			fn_print_fail_eol_nl
-			if [ -f "${lgsmlog}" ]; then
-				fn_script_log_fatal "Downloading ${local_filename}"
-				echo -e "${remote_fileurl}" >> "${lgsmlog}"
-				echo -e "${curlcmd}" >> "${lgsmlog}"
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"
+		do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
 			fi
-			echo -e "${remote_fileurl}"
-			echo -e "${curlcmd}"
-			core_exit.sh
-		else
-			fn_print_ok_eol_nl
-			if [ -f "${lgsmlog}" ]; then
-				fn_script_log_pass "Downloading ${local_filename}"
+			counter=$((counter+1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
 			fi
-		fi
-		# Remove trap.
-		trap - INT
-		# Make file executable if chmodx is set.
-		if [ "${chmodx}" == "chmodx" ]; then
-			chmod +x "${local_filedir}/${local_filename}"
-		fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			# Larger files show a progress bar.
+			if [ "${local_filename##*.}" == "bz2" ]||[ "${local_filename##*.}" == "gz" ]||[ "${local_filename##*.}" == "zip" ]||[ "${local_filename##*.}" == "jar" ]||[ "${local_filename##*.}" == "xz" ]; then
+				echo -en "downloading ${local_filename}..."
+				fn_sleep_time
+				echo -en "\033[1K"
+				curlcmd=$(curl --progress-bar --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}")
+				echo -en "downloading ${local_filename}..."
+			else
+				echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+				curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}" 2>&1)
+			fi
+			local exitcode=$?
+
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if [ -n "$(head "${local_filedir}/${local_filename}" | grep "DOCTYPE" )" ]; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
+			if [ ${exitcode} -ne 0 ]; then
+				if [ ${counter} -ge 2 ]; then
+					fn_print_fail_eol_nl
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}"
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					fn_print_error_eol_nl
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}"
+						fn_script_log_error "${fileurl}"
+					fi
+				fi
+			else
+				fn_print_ok_eol
+				sleep 0.3
+				echo -en "\033[2K\\r"
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}"
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
+			fi
+		done
 	fi
 
 	if [ -f "${local_filedir}/${local_filename}" ]; then
@@ -187,13 +232,19 @@ fn_fetch_file(){
 # forcedl: Optional, force re-download of file even if exists
 # md5: Optional, set an md5 sum and will compare it against the file.
 
-# Fetches any files from the GitHub repo.
+# Fetches files from the Git repo.
 fn_fetch_file_github(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
@@ -201,15 +252,22 @@ fn_fetch_file_github(){
 	forcedl="${6:-0}"
 	md5="${7:-0}"
 	# Passes vars to the file download function.
-	fn_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
+# Fetches config files from the Git repo.
 fn_fetch_config(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${4}"
 	chmodx="nochmodx"
@@ -217,16 +275,22 @@ fn_fetch_config(){
 	forcedl="noforce"
 	md5="nomd5"
 	# Passes vars to the file download function.
-	fn_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
-# Fetches functions.
+# Fetches modules from the Git repo during first download.
 fn_fetch_function(){
 	github_file_url_dir="lgsm/functions"
 	github_file_url_name="${functionfile}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${functionsdir}"
 	local_filename="${github_file_url_name}"
 	chmodx="chmodx"
@@ -234,23 +298,31 @@ fn_fetch_function(){
 	forcedl="noforce"
 	md5="nomd5"
 	# Passes vars to the file download function.
-	fn_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
+# Fetches modules from the Git repo during update-lgsm.
 fn_update_function(){
-	exitbypass=1
 	github_file_url_dir="lgsm/functions"
 	github_file_url_name="${functionfile}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${functionsdir}"
 	local_filename="${github_file_url_name}"
 	chmodx="chmodx"
 	run="norun"
 	forcedl="noforce"
 	md5="nomd5"
-	fn_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	# Passes vars to the file download function.
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+
 }
 
 # Check that curl is installed

+ 12 - 0
lgsm/functions/core_functions.sh

@@ -7,6 +7,8 @@
 
 functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
+modulesversion="v20.2.1"
+
 # Core
 
 core_dl.sh(){
@@ -235,6 +237,11 @@ functionfile="${FUNCNAME[0]}"
 fn_fetch_function
 }
 
+check_version.sh(){
+functionfile="${FUNCNAME[0]}"
+fn_fetch_function
+}
+
 # Compress
 
 compress_unreal2_maps.sh(){
@@ -666,6 +673,11 @@ functionfile="${FUNCNAME[0]}"
 fn_fetch_function
 }
 
+install_modules.sh(){
+functionfile="${FUNCNAME[0]}"
+fn_fetch_function
+}
+
 install_retry.sh(){
 functionfile="${FUNCNAME[0]}"
 fn_fetch_function

+ 11 - 0
lgsm/functions/core_messages.sh

@@ -116,6 +116,17 @@ fn_script_log_info(){
 	fi
 }
 
+## Feb 28 14:56:58 ut99-server: Monitor: INFO:
+fn_script_log_update(){
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: UPDATE: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: UPDATE: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+}
+
 # On-Screen - Automated functions
 ##################################
 

+ 1 - 1
lgsm/functions/info_distro.sh

@@ -9,7 +9,7 @@ functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 ### Game Server pid
 if [ "${status}" == "1" ]; then
-	gameserverpid=$(tmux list-sessions -F "#{session_name} #{pane_pid}"| grep "^${selfname}"|awk '{print $2}')
+	gameserverpid=$(tmux list-sessions -F "#{session_name} #{pane_pid}"| grep "^${sessionname}"|awk '{print $2}')
 fi
 ### Distro information
 

+ 2 - 2
lgsm/functions/info_stats.sh

@@ -23,10 +23,10 @@ fi
 if [ ! -f "${datadir}/uuid-${selfname}.txt" ]||[ ! -f "${datadir}/uuid-install.txt" ]; then
 	# download dictionary words
 	if [ ! -f "${datadir}/name-left.csv" ]; then
-		fn_fetch_file_github "lgsm/data" "name-left.csv" "${datadir}" "nochmodx" "norun" "forcedl" "nomd5"
+		fn_fetch_file_git "lgsm/data" "name-left.csv" "${datadir}" "nochmodx" "norun" "forcedl" "nomd5"
 	fi
 	if [ ! -f "${datadir}/name-right.csv" ]; then
-		fn_fetch_file_github "lgsm/data" "name-right.csv" "${datadir}" "nochmodx" "norun" "forcedl" "nomd5"
+		fn_fetch_file_git "lgsm/data" "name-right.csv" "${datadir}" "nochmodx" "norun" "forcedl" "nomd5"
 	fi
 
 	# generate instance uuid

+ 1 - 1
lgsm/functions/install_config.sh

@@ -25,7 +25,7 @@ fn_fetch_default_config(){
 	mkdir -p "${lgsmdir}/config-default/config-game"
 	githuburl="https://raw.githubusercontent.com/GameServerManagers/Game-Server-Configs/master"
 	for config in "${array_configs[@]}"; do
-		fn_fetch_file "${githuburl}/${gamedirname}/${config}" "${lgsmdir}/config-default/config-game" "${config}" "nochmodx" "norun" "forcedl" "nomd5"
+		fn_fetch_file "${githuburl}/${gamedirname}/${config}" "${remote_fileurl_backup}" "GitHub" "Bitbucket" "${lgsmdir}/config-default/config-game" "${config}" "nochmodx" "norun" "forcedl" "nomd5"
 	done
 }
 

+ 16 - 0
lgsm/functions/install_modules.sh

@@ -0,0 +1,16 @@
+#!/bin/bash
+# LinuxGSM install_modules.sh function
+# Author: Daniel Gibbs
+# Website: https://linuxgsm.com
+# Description: Downloads all modules on install
+
+echo -e ""
+echo -e "${lightyellow}Downloading LinuxGSM Modules${default}"
+echo -e "================================="
+
+fn_fetch_file "https://github.com/GameServerManagers/LinuxGSM/archive/master.tar.gz" "${tmpdir}" "master.tar.gz" "nochmodx" "norun" "noforce" "nomd5"
+fn_dl_extract "${tmpdir}" "master.tar.gz" "${tmpdir}"
+cp "${tmpdir}/LinuxGSM-master/lgsm/functions"/*.sh "${functionsdir}"
+cp "${tmpdir}/LinuxGSM-master/lgsm/functions"/*.py "${functionsdir}"
+chmod +x "${functionsdir}"/*
+command_update_linuxgsm.sh

+ 1 - 1
lgsm/functions/update_factorio.sh

@@ -7,7 +7,7 @@
 functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_update_factorio_dl(){
-	fn_fetch_file "https://factorio.com/get-download/${downloadbranch}/headless/${factorioarch}" "${tmpdir}" "factorio_headless_${factorioarch}-${remotebuild}.tar.xz"
+	fn_fetch_file "https://factorio.com/get-download/${downloadbranch}/headless/${factorioarch}" "" "" "" "${tmpdir}" "factorio_headless_${factorioarch}-${remotebuild}.tar.xz" "" "norun" "noforce" "nomd5"
 	fn_dl_extract "${tmpdir}" "factorio_headless_${factorioarch}-${remotebuild}.tar.xz" "${tmpdir}"
 	echo -e "copying to ${serverfiles}...\c"
 	cp -R "${tmpdir}/factorio/"* "${serverfiles}"

+ 1 - 1
lgsm/functions/update_minecraft.sh

@@ -14,7 +14,7 @@ fn_update_minecraft_dl(){
 	fi
 
 	latestmcbuildurl=$(curl -s "${latestmcreleaselink}" | jq -r '.downloads.server.url')
-	fn_fetch_file "${latestmcbuildurl}" "${tmpdir}" "minecraft_server.${remotebuild}.jar"
+	fn_fetch_file "${latestmcbuildurl}" "" "" "" "${tmpdir}" "minecraft_server.${remotebuild}.jar" "" "norun" "noforce" "nomd5"
 	echo -e "copying to ${serverfiles}...\c"
 	cp "${tmpdir}/minecraft_server.${remotebuild}.jar" "${serverfiles}/minecraft_server.jar"
 	local exitcode=$?

+ 1 - 1
lgsm/functions/update_mta.sh

@@ -7,7 +7,7 @@
 functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_update_mta_dl(){
-	fn_fetch_file "http://linux.mtasa.com/dl/multitheftauto_linux_x64.tar.gz" "${tmpdir}" "multitheftauto_linux_x64.tar.gz"
+	fn_fetch_file "http://linux.mtasa.com/dl/multitheftauto_linux_x64.tar.gz" "" "" "" "${tmpdir}" "multitheftauto_linux_x64.tar.gz" "" "norun" "noforce" "nomd5"
 	mkdir "${tmpdir}/multitheftauto_linux_x64"
 	fn_dl_extract "${tmpdir}" "multitheftauto_linux_x64.tar.gz" "${tmpdir}/multitheftauto_linux_x64"
 	echo -e "copying to ${serverfiles}...\c"

+ 1 - 1
lgsm/functions/update_mumble.sh

@@ -7,7 +7,7 @@
 functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_update_mumble_dl(){
-	fn_fetch_file "https://github.com/mumble-voip/mumble/releases/download/${remotebuild}/murmur-static_${mumblearch}-${remotebuild}.tar.bz2" "${tmpdir}" "murmur-static_${mumblearch}-${remotebuild}.tar.bz2"
+	fn_fetch_file "https://github.com/mumble-voip/mumble/releases/download/${remotebuild}/murmur-static_${mumblearch}-${remotebuild}.tar.bz2" "" "" "" "${tmpdir}" "murmur-static_${mumblearch}-${remotebuild}.tar.bz2" "" "norun" "noforce" "nomd5"
 	fn_dl_extract "${tmpdir}" "murmur-static_${mumblearch}-${remotebuild}.tar.bz2" "${tmpdir}"
 	echo -e "copying to ${serverfiles}...\c"
 	cp -R "${tmpdir}/murmur-static_${mumblearch}-${remotebuild}/"* "${serverfiles}"

+ 1 - 1
lgsm/functions/update_ts3.sh

@@ -12,7 +12,7 @@ fn_update_ts3_dl(){
 	elif [ "${ts3arch}" == "x86" ]; then
 		remotebuildurl=$(curl -s 'https://www.teamspeak.com/versions/server.json' | jq -r '.linux.x86.mirrors."teamspeak.com"')
 	fi
-	fn_fetch_file "${remotebuildurl}" "${tmpdir}" "teamspeak3-server_linux_${ts3arch}-${remotebuild}.tar.bz2"
+	fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "teamspeak3-server_linux_${ts3arch}-${remotebuild}.tar.bz2" "" "norun" "noforce" "nomd5"
 	fn_dl_extract "${tmpdir}" "teamspeak3-server_linux_${ts3arch}-${remotebuild}.tar.bz2" "${tmpdir}"
 	echo -e "copying to ${serverfiles}...\c"
 	cp -R "${tmpdir}/teamspeak3-server_linux_${ts3arch}/"* "${serverfiles}"

+ 95 - 39
linuxgsm.sh

@@ -26,6 +26,7 @@ gameservername="core"
 commandname="CORE"
 rootdir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
 selfname=$(basename "$(readlink -f "${BASH_SOURCE[0]}")")
+sessionname=$(echo "${selfname}" | cut -f1 -d".")
 lgsmdir="${rootdir}/lgsm"
 logdir="${rootdir}/log"
 lgsmlogdir="${logdir}/lgsm"
@@ -59,46 +60,97 @@ core_functions.sh(){
 # Fetches the core functions required before passed off to core_dl.sh.
 fn_bootstrap_fetch_file(){
 	remote_fileurl="${1}"
-	local_filedir="${2}"
-	local_filename="${3}"
-	chmodx="${4:-0}"
-	run="${5:-0}"
-	forcedl="${6:-0}"
-	md5="${7:-0}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
 	# Download file if missing or download forced.
 	if [ ! -f "${local_filedir}/${local_filename}" ]||[ "${forcedl}" == "forcedl" ]; then
-		if [ ! -d "${local_filedir}" ]; then
-			mkdir -p "${local_filedir}"
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=( remote_fileurl remote_fileurl_backup )
+		else
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=( remote_fileurl )
 		fi
 
-		# If curl exists download file.
-		if [ "$(command -v curl 2>/dev/null)" ]; then
-			# Trap to remove part downloaded files.
-			echo -en "    fetching ${local_filename}...\c"
-			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}" 2>&1)
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"
+		do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
+			fi
+			counter=$((counter+1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
+			fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			# Larger files show a progress bar.
+
+			echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}" 2>&1)
+
 			local exitcode=$?
+
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if [ -n "$(head "${local_filedir}/${local_filename}" | grep "DOCTYPE" )" ]; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
 			if [ ${exitcode} -ne 0 ]; then
-				echo -e "FAIL"
-				if [ -f "${lgsmlog}" ]; then
-					echo -e "${remote_fileurl}" | tee -a "${lgsmlog}"
-					echo -e "${curlcmd}" | tee -a "${lgsmlog}"
+				if [ ${counter} -ge 2 ]; then
+					echo -e "FAIL"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}"
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					echo -e "ERROR"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}"
+						fn_script_log_error "${fileurl}"
+					fi
 				fi
-				exit 1
 			else
-				echo -e "OK"
+				echo -en "OK"
+				sleep 0.3
+				echo -en "\033[2K\\r"
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}"
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
 			fi
-		else
-			echo -e "[ FAIL ] Curl is not installed"
-			exit 1
-		fi
-		# Make file chmodx if chmodx is set.
-		if [ "${chmodx}" == "chmodx" ]; then
-			chmod +x "${local_filedir}/${local_filename}"
-		fi
+		done
 	fi
 
 	if [ -f "${local_filedir}/${local_filename}" ]; then
-		# Run file if run is set.
+		# Execute file if run is set.
 		if [ "${run}" == "run" ]; then
 			# shellcheck source=/dev/null
 			source "${local_filedir}/${local_filename}"
@@ -109,9 +161,15 @@ fn_bootstrap_fetch_file(){
 fn_bootstrap_fetch_file_github(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
@@ -119,7 +177,7 @@ fn_bootstrap_fetch_file_github(){
 	forcedl="${6:-0}"
 	md5="${7:-0}"
 	# Passes vars to the file download function.
-	fn_bootstrap_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_bootstrap_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
 # Installer menu.
@@ -321,10 +379,9 @@ else
 		fi
 		if [ ! -f "${configdirserver}/_default.cfg" ]; then
 			mkdir -p "${configdirserver}"
-			echo -en "    copying _default.cfg...\c"
+			echo -en "copying _default.cfg...\c"
 			cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
-			exitcode=$?
-			if [ ${exitcode} -ne 0 ]; then
+			if [ $? -ne 0 ]; then
 				echo -e "FAIL"
 				exit 1
 			else
@@ -333,11 +390,10 @@ else
 		else
 			function_file_diff=$(diff -q "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg")
 			if [ "${function_file_diff}" != "" ]; then
-				fn_print_warn_nl "_default.cfg has been altered. reloading config."
-				echo -en "    copying _default.cfg...\c"
+				fn_print_warn_nl "_default.cfg has altered. reloading config."
+				echo -en "copying _default.cfg...\c"
 				cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
-				exitcode=$?
-				if [ ${exitcode} -ne 0 ]; then
+				if [ $? -ne 0 ]; then
 					echo -e "FAIL"
 					exit 1
 				else

+ 94 - 40
tests/tests_fctrserver.sh

@@ -23,8 +23,10 @@ fi
 version="v20.2.1"
 shortname="fctr"
 gameservername="fctrserver"
+commandname="CORE"
 rootdir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
 selfname=$(basename "$(readlink -f "${BASH_SOURCE[0]}")")
+sessionname=$(echo "${selfname}" | cut -f1 -d".")
 lgsmdir="${rootdir}/lgsm"
 logdir="${rootdir}/log"
 lgsmlogdir="${logdir}/lgsm"
@@ -43,16 +45,11 @@ userinput="${1}"
 
 # Allows for testing not on Travis CI.
 # if using travis for tests
-if [ -n "${TRAVIS}" ]; then
-	selfname="travis"
-# if not using travis for tests
-else
+if [ -z "${TRAVIS}" ]; then
 	TRAVIS_BRANCH="develop"
 	TRAVIS_BUILD_DIR="${rootdir}"
-
 fi
 travistest="1"
-
 ## GitHub Branch Select
 # Allows for the use of different function files
 # from a different repo and/or branch.
@@ -70,46 +67,97 @@ core_functions.sh(){
 # Fetches the core functions required before passed off to core_dl.sh.
 fn_bootstrap_fetch_file(){
 	remote_fileurl="${1}"
-	local_filedir="${2}"
-	local_filename="${3}"
-	chmodx="${4:-0}"
-	run="${5:-0}"
-	forcedl="${6:-0}"
-	md5="${7:-0}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
 	# Download file if missing or download forced.
 	if [ ! -f "${local_filedir}/${local_filename}" ]||[ "${forcedl}" == "forcedl" ]; then
-		if [ ! -d "${local_filedir}" ]; then
-			mkdir -p "${local_filedir}"
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=( remote_fileurl remote_fileurl_backup )
+		else
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=( remote_fileurl )
 		fi
 
-		# If curl exists download file.
-		if [ "$(command -v curl 2>/dev/null)" ]; then
-			# Trap to remove part downloaded files.
-			echo -en "    fetching ${local_filename}...\c"
-			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}" 2>&1)
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"
+		do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
+			fi
+			counter=$((counter+1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
+			fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			# Larger files show a progress bar.
+
+			echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}" 2>&1)
+
 			local exitcode=$?
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if [ -n "$(head "${local_filedir}/${local_filename}" | grep "DOCTYPE" )" ]; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
 			if [ ${exitcode} -ne 0 ]; then
-				echo -e "FAIL"
-				if [ -f "${lgsmlog}" ]; then
-					echo -e "${remote_fileurl}" | tee -a "${lgsmlog}"
-					echo -e "${curlcmd}" | tee -a "${lgsmlog}"
+				if [ ${counter} -ge 2 ]; then
+					echo -e "FAIL"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}"
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					echo -e "ERROR"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}"
+						fn_script_log_error "${fileurl}"
+					fi
 				fi
-				exit 1
+
 			else
-				echo -e "OK"
+				echo -en "OK"
+				sleep 0.3
+				echo -en "\033[2K\\r"
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}"
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
 			fi
-		else
-			echo -e "[ FAIL ] Curl is not installed"
-			exit 1
-		fi
-		# Make file chmodx if chmodx is set.
-		if [ "${chmodx}" == "chmodx" ]; then
-			chmod +x "${local_filedir}/${local_filename}"
-		fi
+		done
 	fi
 
 	if [ -f "${local_filedir}/${local_filename}" ]; then
-		# Run file if run is set.
+		# Execute file if run is set.
 		if [ "${run}" == "run" ]; then
 			# shellcheck source=/dev/null
 			source "${local_filedir}/${local_filename}"
@@ -120,9 +168,15 @@ fn_bootstrap_fetch_file(){
 fn_bootstrap_fetch_file_github(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
@@ -130,7 +184,7 @@ fn_bootstrap_fetch_file_github(){
 	forcedl="${6:-0}"
 	md5="${7:-0}"
 	# Passes vars to the file download function.
-	fn_bootstrap_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_bootstrap_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
 # Installer menu.
@@ -332,7 +386,7 @@ else
 		fi
 		if [ ! -f "${configdirserver}/_default.cfg" ]; then
 			mkdir -p "${configdirserver}"
-			echo -en "    copying _default.cfg...\c"
+			echo -en "copying _default.cfg...\c"
 			cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 			exitcode=$?
 			if [ ${exitcode} -ne 0 ]; then
@@ -345,7 +399,7 @@ else
 			function_file_diff=$(diff -q "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg")
 			if [ "${function_file_diff}" != "" ]; then
 				fn_print_warn_nl "_default.cfg has been altered. reloading config."
-				echo -en "    copying _default.cfg...\c"
+				echo -en "copying _default.cfg...\c"
 				cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 				exitcode=$?
 				if [ ${exitcode} -ne 0 ]; then

+ 94 - 38
tests/tests_jc2server.sh

@@ -23,8 +23,10 @@ fi
 version="v20.2.1"
 shortname="jc2"
 gameservername="jc2server"
+commandname="CORE"
 rootdir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
 selfname=$(basename "$(readlink -f "${BASH_SOURCE[0]}")")
+sessionname=$(echo "${selfname}" | cut -f1 -d".")
 lgsmdir="${rootdir}/lgsm"
 logdir="${rootdir}/log"
 lgsmlogdir="${logdir}/lgsm"
@@ -43,10 +45,7 @@ userinput="${1}"
 
 # Allows for testing not on Travis CI.
 # if using travis for tests
-if [ -n "${TRAVIS}" ]; then
-	selfname="travis"
-# if not using travis for tests
-else
+if [ -z "${TRAVIS}" ]; then
 	TRAVIS_BRANCH="develop"
 	TRAVIS_BUILD_DIR="${rootdir}"
 fi
@@ -69,46 +68,97 @@ core_functions.sh(){
 # Fetches the core functions required before passed off to core_dl.sh.
 fn_bootstrap_fetch_file(){
 	remote_fileurl="${1}"
-	local_filedir="${2}"
-	local_filename="${3}"
-	chmodx="${4:-0}"
-	run="${5:-0}"
-	forcedl="${6:-0}"
-	md5="${7:-0}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
 	# Download file if missing or download forced.
 	if [ ! -f "${local_filedir}/${local_filename}" ]||[ "${forcedl}" == "forcedl" ]; then
-		if [ ! -d "${local_filedir}" ]; then
-			mkdir -p "${local_filedir}"
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=( remote_fileurl remote_fileurl_backup )
+		else
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=( remote_fileurl )
 		fi
 
-		# If curl exists download file.
-		if [ "$(command -v curl 2>/dev/null)" ]; then
-			# Trap to remove part downloaded files.
-			echo -en "    fetching ${local_filename}...\c"
-			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}" 2>&1)
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"
+		do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
+			fi
+			counter=$((counter+1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
+			fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			# Larger files show a progress bar.
+
+			echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}" 2>&1)
+
 			local exitcode=$?
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if [ -n "$(head "${local_filedir}/${local_filename}" | grep "DOCTYPE" )" ]; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
 			if [ ${exitcode} -ne 0 ]; then
-				echo -e "FAIL"
-				if [ -f "${lgsmlog}" ]; then
-					echo -e "${remote_fileurl}" | tee -a "${lgsmlog}"
-					echo -e "${curlcmd}" | tee -a "${lgsmlog}"
+				if [ ${counter} -ge 2 ]; then
+					echo -e "FAIL"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}"
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					echo -e "ERROR"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}"
+						fn_script_log_error "${fileurl}"
+					fi
 				fi
-				exit 1
+
 			else
-				echo -e "OK"
+				echo -en "OK"
+				sleep 0.3
+				echo -en "\033[2K\\r"
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}"
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
 			fi
-		else
-			echo -e "[ FAIL ] Curl is not installed"
-			exit 1
-		fi
-		# Make file chmodx if chmodx is set.
-		if [ "${chmodx}" == "chmodx" ]; then
-			chmod +x "${local_filedir}/${local_filename}"
-		fi
+		done
 	fi
 
 	if [ -f "${local_filedir}/${local_filename}" ]; then
-		# Run file if run is set.
+		# Execute file if run is set.
 		if [ "${run}" == "run" ]; then
 			# shellcheck source=/dev/null
 			source "${local_filedir}/${local_filename}"
@@ -119,9 +169,15 @@ fn_bootstrap_fetch_file(){
 fn_bootstrap_fetch_file_github(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
@@ -129,7 +185,7 @@ fn_bootstrap_fetch_file_github(){
 	forcedl="${6:-0}"
 	md5="${7:-0}"
 	# Passes vars to the file download function.
-	fn_bootstrap_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_bootstrap_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
 # Installer menu.
@@ -331,7 +387,7 @@ else
 		fi
 		if [ ! -f "${configdirserver}/_default.cfg" ]; then
 			mkdir -p "${configdirserver}"
-			echo -en "    copying _default.cfg...\c"
+			echo -en "copying _default.cfg...\c"
 			cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 			exitcode=$?
 			if [ ${exitcode} -ne 0 ]; then
@@ -344,7 +400,7 @@ else
 			function_file_diff=$(diff -q "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg")
 			if [ "${function_file_diff}" != "" ]; then
 				fn_print_warn_nl "_default.cfg has been altered. reloading config."
-				echo -en "    copying _default.cfg...\c"
+				echo -en "copying _default.cfg...\c"
 				cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 				exitcode=$?
 				if [ ${exitcode} -ne 0 ]; then

+ 94 - 39
tests/tests_mcserver.sh

@@ -23,8 +23,10 @@ fi
 version="v20.2.1"
 shortname="mc"
 gameservername="mcserver"
+commandname="CORE"
 rootdir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
 selfname=$(basename "$(readlink -f "${BASH_SOURCE[0]}")")
+sessionname=$(echo "${selfname}" | cut -f1 -d".")
 lgsmdir="${rootdir}/lgsm"
 logdir="${rootdir}/log"
 lgsmlogdir="${logdir}/lgsm"
@@ -43,13 +45,9 @@ userinput="${1}"
 
 # Allows for testing not on Travis CI.
 # if using travis for tests
-if [ -n "${TRAVIS}" ]; then
-	selfname="travis"
-# if not using travis for tests
-else
+if [ -z "${TRAVIS}" ]; then
 	TRAVIS_BRANCH="develop"
 	TRAVIS_BUILD_DIR="${rootdir}"
-
 fi
 travistest="1"
 
@@ -70,46 +68,97 @@ core_functions.sh(){
 # Fetches the core functions required before passed off to core_dl.sh.
 fn_bootstrap_fetch_file(){
 	remote_fileurl="${1}"
-	local_filedir="${2}"
-	local_filename="${3}"
-	chmodx="${4:-0}"
-	run="${5:-0}"
-	forcedl="${6:-0}"
-	md5="${7:-0}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
 	# Download file if missing or download forced.
 	if [ ! -f "${local_filedir}/${local_filename}" ]||[ "${forcedl}" == "forcedl" ]; then
-		if [ ! -d "${local_filedir}" ]; then
-			mkdir -p "${local_filedir}"
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=( remote_fileurl remote_fileurl_backup )
+		else
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=( remote_fileurl )
 		fi
 
-		# If curl exists download file.
-		if [ "$(command -v curl 2>/dev/null)" ]; then
-			# Trap to remove part downloaded files.
-			echo -en "    fetching ${local_filename}...\c"
-			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}" 2>&1)
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"
+		do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
+			fi
+			counter=$((counter+1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
+			fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			# Larger files show a progress bar.
+
+			echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}" 2>&1)
+
 			local exitcode=$?
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if [ -n "$(head "${local_filedir}/${local_filename}" | grep "DOCTYPE" )" ]; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
 			if [ ${exitcode} -ne 0 ]; then
-				echo -e "FAIL"
-				if [ -f "${lgsmlog}" ]; then
-					echo -e "${remote_fileurl}" | tee -a "${lgsmlog}"
-					echo -e "${curlcmd}" | tee -a "${lgsmlog}"
+				if [ ${counter} -ge 2 ]; then
+					echo -e "FAIL"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}"
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					echo -e "ERROR"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}"
+						fn_script_log_error "${fileurl}"
+					fi
 				fi
-				exit 1
+
 			else
-				echo -e "OK"
+				echo -en "OK"
+				sleep 0.3
+				echo -en "\033[2K\\r"
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}"
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
 			fi
-		else
-			echo -e "[ FAIL ] Curl is not installed"
-			exit 1
-		fi
-		# Make file chmodx if chmodx is set.
-		if [ "${chmodx}" == "chmodx" ]; then
-			chmod +x "${local_filedir}/${local_filename}"
-		fi
+		done
 	fi
 
 	if [ -f "${local_filedir}/${local_filename}" ]; then
-		# Run file if run is set.
+		# Execute file if run is set.
 		if [ "${run}" == "run" ]; then
 			# shellcheck source=/dev/null
 			source "${local_filedir}/${local_filename}"
@@ -120,9 +169,15 @@ fn_bootstrap_fetch_file(){
 fn_bootstrap_fetch_file_github(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
@@ -130,7 +185,7 @@ fn_bootstrap_fetch_file_github(){
 	forcedl="${6:-0}"
 	md5="${7:-0}"
 	# Passes vars to the file download function.
-	fn_bootstrap_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_bootstrap_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
 # Installer menu.
@@ -332,7 +387,7 @@ else
 		fi
 		if [ ! -f "${configdirserver}/_default.cfg" ]; then
 			mkdir -p "${configdirserver}"
-			echo -en "    copying _default.cfg...\c"
+			echo -en "copying _default.cfg...\c"
 			cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 			exitcode=$?
 			if [ ${exitcode} -ne 0 ]; then
@@ -345,7 +400,7 @@ else
 			function_file_diff=$(diff -q "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg")
 			if [ "${function_file_diff}" != "" ]; then
 				fn_print_warn_nl "_default.cfg has been altered. reloading config."
-				echo -en "    copying _default.cfg...\c"
+				echo -en "copying _default.cfg...\c"
 				cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 				exitcode=$?
 				if [ ${exitcode} -ne 0 ]; then

+ 94 - 39
tests/tests_ts3server.sh

@@ -23,8 +23,10 @@ fi
 version="v20.2.1"
 shortname="ts3"
 gameservername="ts3server"
+commandname="CORE"
 rootdir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
 selfname=$(basename "$(readlink -f "${BASH_SOURCE[0]}")")
+sessionname=$(echo "${selfname}" | cut -f1 -d".")
 lgsmdir="${rootdir}/lgsm"
 logdir="${rootdir}/log"
 lgsmlogdir="${logdir}/lgsm"
@@ -43,13 +45,9 @@ userinput="${1}"
 
 # Allows for testing not on Travis CI.
 # if using travis for tests
-if [ -n "${TRAVIS}" ]; then
-	selfname="travis"
-# if not using travis for tests
-else
+if [ -z "${TRAVIS}" ]; then
 	TRAVIS_BRANCH="develop"
 	TRAVIS_BUILD_DIR="${rootdir}"
-
 fi
 travistest="1"
 
@@ -70,46 +68,97 @@ core_functions.sh(){
 # Fetches the core functions required before passed off to core_dl.sh.
 fn_bootstrap_fetch_file(){
 	remote_fileurl="${1}"
-	local_filedir="${2}"
-	local_filename="${3}"
-	chmodx="${4:-0}"
-	run="${5:-0}"
-	forcedl="${6:-0}"
-	md5="${7:-0}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	md5="${10:-0}"
 	# Download file if missing or download forced.
 	if [ ! -f "${local_filedir}/${local_filename}" ]||[ "${forcedl}" == "forcedl" ]; then
-		if [ ! -d "${local_filedir}" ]; then
-			mkdir -p "${local_filedir}"
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=( remote_fileurl remote_fileurl_backup )
+		else
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=( remote_fileurl )
 		fi
 
-		# If curl exists download file.
-		if [ "$(command -v curl 2>/dev/null)" ]; then
-			# Trap to remove part downloaded files.
-			echo -en "    fetching ${local_filename}...\c"
-			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${remote_fileurl}" 2>&1)
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"
+		do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
+			fi
+			counter=$((counter+1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
+			fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			# Larger files show a progress bar.
+
+			echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+			curlcmd=$(curl -s --fail -L -o "${local_filedir}/${local_filename}" "${fileurl}" 2>&1)
+
 			local exitcode=$?
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if [ -n "$(head "${local_filedir}/${local_filename}" | grep "DOCTYPE" )" ]; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
 			if [ ${exitcode} -ne 0 ]; then
-				echo -e "FAIL"
-				if [ -f "${lgsmlog}" ]; then
-					echo -e "${remote_fileurl}" | tee -a "${lgsmlog}"
-					echo -e "${curlcmd}" | tee -a "${lgsmlog}"
+				if [ ${counter} -ge 2 ]; then
+					echo -e "FAIL"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}"
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					echo -e "ERROR"
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}"
+						fn_script_log_error "${fileurl}"
+					fi
 				fi
-				exit 1
+
 			else
-				echo -e "OK"
+				echo -en "OK"
+				sleep 0.3
+				echo -en "\033[2K\\r"
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}"
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
 			fi
-		else
-			echo -e "[ FAIL ] Curl is not installed"
-			exit 1
-		fi
-		# Make file chmodx if chmodx is set.
-		if [ "${chmodx}" == "chmodx" ]; then
-			chmod +x "${local_filedir}/${local_filename}"
-		fi
+		done
 	fi
 
 	if [ -f "${local_filedir}/${local_filename}" ]; then
-		# Run file if run is set.
+		# Execute file if run is set.
 		if [ "${run}" == "run" ]; then
 			# shellcheck source=/dev/null
 			source "${local_filedir}/${local_filename}"
@@ -120,9 +169,15 @@ fn_bootstrap_fetch_file(){
 fn_bootstrap_fetch_file_github(){
 	github_file_url_dir="${1}"
 	github_file_url_name="${2}"
-	githuburl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
-
-	remote_fileurl="${githuburl}"
+	if [ "${githubbranch}" == "master" ]&&[ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
 	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
@@ -130,7 +185,7 @@ fn_bootstrap_fetch_file_github(){
 	forcedl="${6:-0}"
 	md5="${7:-0}"
 	# Passes vars to the file download function.
-	fn_bootstrap_fetch_file "${remote_fileurl}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
+	fn_bootstrap_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${md5}"
 }
 
 # Installer menu.
@@ -332,7 +387,7 @@ else
 		fi
 		if [ ! -f "${configdirserver}/_default.cfg" ]; then
 			mkdir -p "${configdirserver}"
-			echo -en "    copying _default.cfg...\c"
+			echo -en "copying _default.cfg...\c"
 			cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 			exitcode=$?
 			if [ ${exitcode} -ne 0 ]; then
@@ -345,7 +400,7 @@ else
 			function_file_diff=$(diff -q "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg")
 			if [ "${function_file_diff}" != "" ]; then
 				fn_print_warn_nl "_default.cfg has been altered. reloading config."
-				echo -en "    copying _default.cfg...\c"
+				echo -en "copying _default.cfg...\c"
 				cp -R "${configdirdefault}/config-lgsm/${gameservername}/_default.cfg" "${configdirserver}/_default.cfg"
 				exitcode=$?
 				if [ ${exitcode} -ne 0 ]; then