#!/bin/bash export DEBUG="${DEBUG:-0}"; export KEIL_URL="${KEIL_URL:-https://armkeil.blob.core.windows.net/eval/MDK537.EXE}"; export PACK_URL="${PACK_URL:-https://ennis.zhaw.ch/pack/InES.CTBoard14_DFP.4.0.3.pack}"; installerExtension=".exe"; installer="$(mktemp --suffix="$installerExtension")"; installerName="$(basename "$installer" | sed "s/$installerExtension$//")"; export DISPLAY=:90; mkdir -p --mode=777 /tmp/.X11-unix; # Create a job for waiting for Xvfb to start watchStarting="$(mktemp)"; { 2>&1 inotifywait -e create /tmp/.X11-unix/ > /dev/null; } | { sed -u -e "/^Watches established.$/e rm \"$watchStarting\""; } & displayResolver="$!"; # Wait for `inotifywait` to start while [ -f "$watchStarting" ]; do sleep 0.5; done; { # Improve arguments for screenshots ARGS="$([ "$DEBUG" -eq 1 ] && echo "-screen 0 640x480x24 -dpi 192" || echo "")"; Xvfb "${DISPLAY}" ${ARGS} & }; displayPID="$!"; wget "${KEIL_URL}" --progress=bar:force:noscroll -O "$installer"; # Preparations for Debug Logs if [ "$DEBUG" -eq 1 ] then dir="$(mktemp -d)"; TIV="$(mktemp)"; logDir="log"; screenDir="$logDir/screens"; git clone https://github.com/stefanhaustein/TerminalImageViewer.git "$dir"; git checkout "v1.1.1"; cd "$dir/src/main/cpp"; make; mv tiv "$TIV"; cd -; rm -rf "$dir"; mkdir -p "$logDir"; mkdir -p "$screenDir"; fi function printHeading() { local heading; heading="====================================================="; echo "$heading"; if [ -z "$1" ] then cat; else echo "$1"; fi; echo "$heading"; } function kill_installer() { pkill -9 "$installerName" > /dev/null 2>&1; } function handle_output() { # Pattern that is supposed to indicate that wine got stuck pattern="fixme:win:NtUserLockWindowUpdate ((nil))"; # The number of occurences of the pattern which have to occur to assume wine got stuck patternCount=2; sed \ -u \ `# Handle the pattern and the chosen pattern count` \ -e "/$pattern/{ x; s/^x\{$(expr "$patternCount" - 1)\}$/\0/; x; t stuck; x; s/^\(x*\)$/\1x/; x; };" \ `# Return to start` \ -e "b;" \ `# Branch "stuck": delete output and exit with code 42` \ -e ":stuck q42;" \ `# Branch "end": exit with code 0` \ -e ":end q;"; exitCode="$?"; # Kill installer if it got stuck (based on the console output and the pattern) if [ "$exitCode" -ne 0 ] then kill_installer; return "$exitCode"; fi; return 0; } # Install Keil uVision function install_keil() { try="$1"; logFile="$(mktemp)"; printHeading "Starting ARM Keil Installation"; # Run installer asynchronously { { local exitCode; exitCodeFile="$(mktemp)"; { 2>&1 WINEDEBUG=+all,trace-all,warn-all wine "$installer" --batch-install; echo "$?" > "$exitCodeFile"; } | \ # Write output to a log file when debugging { [ "$DEBUG" -eq 1 ] && { tee "$logFile"; } || cat; } | \ # Pipe stdout and stderr to `handle_output` function handle_output; outputHandlerCode="$?"; exitCode="$(cat "$exitCodeFile")"; rm "$exitCodeFile"; if [ "$outputHandlerCode" -ne 0 ] then exitCode="$outputHandlerCode"; fi; bash -c "exit $exitCode"; } & }; pid="$!"; # Continuously display screenshots and iteration number when debugging if [ "$DEBUG" -eq 1 ] then { { x=0; maxCount=120; while ps -p "$pid" > /dev/null && [ "$x" -ne "$maxCount" ] do # Create screenshot and print it to the console fileName="$screenDir/install-try$try-$x.png"; import -window root "$fileName"; "$TIV" -w 10000 -h 10000 "$fileName"; x="$(expr "$x" + 1)"; echo "Frame #$x"; sleep 1; done; # Kill the installer once `maxCount` has been reached if [ "$x" -eq "$maxCount" ] then kill_installer; mv "$logFile" "./$logDir/log-timeout-try$try.log"; fi; } & }; fi; wait "$pid"; exitCode="$?"; if [ "$DEBUG" -eq 1 ] && [ -f "$logFile" ] then if [ "$exitCode" -eq 0 ] then mv "$logFile" "./$logDir/success-try$try.log"; elif [ "$exitCode" -eq 42 ] then mv "$logFile" "./$logDir/timeout-handled-try$try.log"; else mv "$logFile" "./$logDir§/fail-try$try.txt"; fi; fi; { if [ "$exitCode" -ne 0 ] then if [ "$exitCode" -eq 42 ] then echo "The Installation Got Stuck"; else echo "The Installation Failed"; fi; else echo "The Installation Was Successul"; fi; echo "The Installation Process Exited With Code $exitCode"; } | printHeading; return "$exitCode"; } # Wait for Xvfb to start wait "$displayResolver"; y=0; while ! install_keil "$y" do printHeading "Restarting Installation"; y="$(expr "$y" + 1)"; done; kill -9 "$displayPID" > /dev/null 2>&1; # Delete unfinished installations rm -rf "$(winepath 'C:\Keil_v5')/Backup."*; rm "$installer"; rm -rf /tmp/.X*-lock; # Fix incorrect `RTEPATH` setting keilConfig="$(winepath 'C:\Keil_v5\TOOLS.INI')"; winAppData="$(wine cmd.exe /c 'echo %LOCALAPPDATA%' | tr -d '\r' | sed 's/\\/\\\\/g')"; packDir="$winAppData"'\Arm\Packs'; sed -i '/^RTEPATH=/d' "$keilConfig"; echo 'RTEPATH="'"$packDir"'"' | sed -i '/\[UV2\]/ r /dev/stdin' "$keilConfig"; # Install additional package if [ ! -z "$PACK_URL" ] then packFile="$(mktemp)"; wget "${PACK_URL}" --progress=bar:force:noscroll --no-check-certificate -O "$packFile"; xvfb-run wine "C:\Keil_v5\UV4\PackUnzip.exe" --embedded --agree-license "$packFile" & pid="$!"; \ wait "$pid"; \ rm "$packFile"; fi;