🐛 fix(server): Final touches (#66)

## Description

**What issue are you solving (or what feature are you adding) and how
are you doing it?**

This is a catch all PR that tries to smooth out the creases found while
playing using Netris.
What i have found so far:
1. Change `NAME` environment to `SESSION_ID` for warp server.
2. Run `entrypoint.sh` and `warp-input` as user `netris`
3. Netris-proton is broken, it quits prematurely. I think it has to be a
problem with a missing wine installation
This commit is contained in:
Wanjohi
2024-05-30 01:53:07 +03:00
committed by GitHub
parent 9a11f459cb
commit 674124e819
4 changed files with 572 additions and 320 deletions

View File

@@ -64,37 +64,34 @@ sudo /etc/init.d/dbus start
netris-proton -i
# Install NVIDIA userspace driver components including X graphic libraries
if ! command -v nvidia-xconfig &>/dev/null; then
if ! command -v nvidia-xconfig &> /dev/null; then
# Driver version is provided by the kernel through the container toolkit
export DRIVER_ARCH="$(dpkg --print-architecture | sed -e 's/arm64/aarch64/' -e 's/armhf/32bit-ARM/' -e 's/i.*86/x86/' -e 's/amd64/x86_64/' -e 's/unknown/x86_64/')"
export DRIVER_VERSION="$(head -n1 </proc/driver/nvidia/version | awk '{for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+\.[0-9\.]+/) {print $i; exit}}' )"
export DRIVER_VERSION="$(head -n1 </proc/driver/nvidia/version | awk '{for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+\.[0-9\.]+/) {print $i; exit}}')"
cd /tmp
# If version is different, new installer will overwrite the existing components
if [ ! -f "/tmp/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" ]; then
# Check multiple sources in order to probe both consumer and datacenter driver versions
curl -fsSL -O "https://international.download.nvidia.com/XFree86/Linux-${DRIVER_ARCH}/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || curl -fsSL -O "https://international.download.nvidia.com/tesla/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || {
echo "$(date +"[%Y-%m-%d %H:%M:%S]") Failed NVIDIA GPU driver download. Exiting."
exit 1
}
curl -fsSL -O "https://international.download.nvidia.com/XFree86/Linux-${DRIVER_ARCH}/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || curl -fsSL -O "https://international.download.nvidia.com/tesla/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || { echo "Failed NVIDIA GPU driver download. Exiting."; exit 1; }
fi
# Extract installer before installing
sudo sh "NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" -x
cd "NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}"
# Run installation without the kernel modules and host components
sudo ./nvidia-installer --silent \
--no-kernel-module \
--install-compat32-libs \
--no-nouveau-check \
--no-nvidia-modprobe \
--no-rpms \
--no-backup \
--no-check-for-alternate-installs
--no-kernel-module \
--install-compat32-libs \
--no-nouveau-check \
--no-nvidia-modprobe \
--no-rpms \
--no-backup \
--no-check-for-alternate-installs
sudo rm -rf /tmp/NVIDIA* && cd ~
fi
# Allow starting Xorg from a pseudoterminal instead of strictly on a tty console
if [ ! -f /etc/X11/Xwrapper.config ]; then
echo -e "allowed_users=anybody\nneeds_root_rights=yes" | sudo tee /etc/X11/Xwrapper.config >/dev/null
echo -e "allowed_users=anybody\nneeds_root_rights=yes" | sudo tee /etc/X11/Xwrapper.config > /dev/null
fi
if grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then
sudo sed -i "s/allowed_users=console/allowed_users=anybody/;$ a needs_root_rights=yes" /etc/X11/Xwrapper.config
@@ -117,7 +114,7 @@ else
fi
if [ -z "$GPU_SELECT" ]; then
echo "$(date +"[%Y-%m-%d %H:%M:%S]") No NVIDIA GPUs detected or nvidia-container-toolkit not configured. Exiting."
echo "No NVIDIA GPUs detected or nvidia-container-toolkit not configured. Exiting."
exit 1
fi
@@ -143,30 +140,32 @@ sudo sed -i '/Driver\s\+"nvidia"/a\ Option "ModeValidation" "NoMaxPCl
# Add custom generated modeline to the configuration
sudo sed -i '/Section\s\+"Monitor"/a\ '"$MODELINE" /etc/X11/xorg.conf
# Prevent interference between GPUs, add this to the host or other containers running Xorg as well
echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | sudo tee -a /etc/X11/xorg.conf >/dev/null
echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | sudo tee -a /etc/X11/xorg.conf > /dev/null
# Default display is :0 across the container
export DISPLAY=":0"
# Run Xorg server with required extensions
/usr/bin/Xorg vt7 -noreset -novtswitch -sharevts -dpi "${DPI}" +extension "COMPOSITE" +extension "DAMAGE" +extension "GLX" +extension "RANDR" +extension "RENDER" +extension "MIT-SHM" +extension "XFIXES" +extension "XTEST" "${DISPLAY}" &
# Wait for X11 to start
echo "Waiting for X socket"
until [ -S "/tmp/.X11-unix/X${DISPLAY/:/}" ]; do sleep 1; done
echo "X socket is ready"
# Wait for X11 to start
echo "$(date +"[%Y-%m-%d %H:%M:%S]") Waiting for X socket"
until [ -S "/tmp/.X11-unix/X${DISPLAY/:/}" ]; do sleep 1; done
echo "$(date +"[%Y-%m-%d %H:%M:%S]") X socket is ready"
if [[ -z "${NAME}" ]]; then
if [[ -z "${SESSION_ID}" ]]; then
echo "$(date +"[%Y-%m-%d %H:%M:%S]") No stream name was found, did you forget to set the env variable NAME?" && exit 1
else
/usr/bin/gpu-screen-recorder -w screen -c flv -f 60 -a "$(pactl get-default-sink).monitor" | ffmpeg -hide_banner -v quiet -i pipe:0 -c copy -f mp4 -movflags empty_moov+frag_every_frame+separate_moof+omit_tfhd_offset - | /usr/bin/warp --name "${NAME}" https://fst.so:4443 &
/usr/bin/gpu-screen-recorder -w screen -c flv -f 60 -a "$(pactl get-default-sink).monitor" | ffmpeg -hide_banner -v quiet -i pipe:0 -c copy -f mp4 -movflags empty_moov+frag_every_frame+separate_moof+omit_tfhd_offset - | /usr/bin/warp --name "${SESSION_ID}" https://fst.so:4443 &
fi
openbox-session &
#Now we can safely run our input server without permission errors
sudo /inputtino/input-server &
/usr/games/gamescope -- mangohud glxgears > /dev/null &
# /usr/games/gamescope -- mangohud glxgears > /dev/null &
echo "$(date +"[%Y-%m-%d %H:%M:%S]") Session Running. Press [Return] to exit."
read

View File

@@ -1,49 +1,371 @@
#!/bin/bash
# Version 0.0.1
# Version 1.1
#Copied from https://github.com/noabody/unibuild/blob/master/data/wstart
#Big thanks to github/@noabody
#For his wmstart script https://github.com/noabody/unibuild/blob/master/data/wstart
# WINEARCH win32/win64 not as good as binary wine/wine64"
# WINEDEBUG="-all" not as good as dev/null
#Dependencies: git, jq, curl, vulkan & wget
# complex command line builder to simplify command objects
# vars bin, pfx set to wine binary, prefix dirs initially
# menus will dynamically set bin pfx to specific targets
# menu shows gui based 32/64-bit pe header exe via pev
# var 'x' for unified cross-functionality
# ${@:2} skips 'wstart' and 1st arg
# top level linux steam dir
# manjaro 21.2.1
#sudo pacman -S bash binutils findutils gendesk grep icoutils pcre2 perl yay winetricks; yay -S pev
# wnbin needs wine dir with: bin lib lib64 share
# manjaro default path is /usr
# can symlink various wnbin="$HOME/.local/opt"
#mkdir "$HOME"/.local/opt
#ln -sf /usr "$HOME"/.local/opt/wine
#ln -sf /usr/share/steam/compatibilitytools.d/proton-ge-custom/files "$HOME"/.local/opt/proton
wnbin="/usr"
# top level wine dir, symlink into "$HOME/.local/opt" to flatten paths
wnpfx="$HOME"
# top level wine prefix dir
pntop="$HOME/.steam"
# steamapps subdir
# top level linux steam dir
pnapp="$pntop/steam/steamapps"
# proton subdir normally under top/app
# steamapps subdir
pnbin="$pnapp/common"
# proton prefix subdir normally under top/app
# proton subdir normally under top/app
pnpfx="$pnapp/compatdata"
# proton ge
# proton prefix subdir normally under top/app
pnpge="$pntop/root/compatibilitytools.d"
# Program Files standard subdir
# proton ge
progs="drive_c/Program Files"
# windows steam client subdir under progs
# Program Files standard subdir
stcmn="Steam/steamapps/common"
# temp folder
# windows steam client subdir under progs
desk="$HOME/Desktop"
# desktop entry folder
icon="applications-other"
# default icon
temp="$HOME/Downloads"
# store cmdline args minus first option
# temp folder
clprm=("${@:2}")
# store cmdline args minus first option
x="$(echo "$1" | grep -Pio '(?<=-)[wp]')"
# 1st letter of 1st cmd line arg determines wine/proton
if [[ -n "$x" ]]; then
xarg="$(echo "$1" | perl -pe 's/-[wp]/-x/gi')"
else
xarg="$(echo "$1" | perl -pe 's/-x+/-/gi')"
fi
# drop 1st letter x or change to it
xcmd=()
i_mnus=()
myprnt=()
i_syms=()
# scalable built-in programs menu
pmenu=("Command Prompt/wineconsole.exe" "Control Panel/control.exe" "Registry Editor/regedit.exe" "Task Manager/taskmgr.exe" "Windows Explorer/explorer.exe" "Wine Configuration/winecfg.exe")
# prevent shell inheritance of env vars we use
# scalable built-in programs menu
unset WINEARCH WINEDLLPATH WINEPREFIX STEAM_COMPAT_CLIENT_INSTALL_PATH STEAM_COMPAT_DATA_PATH
# prevent shell inheritance of env vars we use
xarg="$1"
xnint() {
xnbin="$pnbin"
xnpfx="$pnpfx"
dpth=(4 3)
w_menu () {
PS3="Please enter your choice: "
select answer in "${i_mnus[@]}"; do
for item in "${i_mnus[@]}"; do
if [[ $item == "$answer" ]]; then
break 2
fi
done
done
# repeating menu requires valid selection from array
if [[ "$answer" = "quit" ]]; then
# pop quit from end of array for menu option
exit
else
xmrtn="$answer"
fi
unset i_mnus
clear
}
xpge() {
# Path ordering: wine64 x64/x32 or wine32 x32 then standard
# Order critical to proper operation
xn64 () {
xstrt="wine64"
xnldl="$xnbin/lib64:$xnbin/lib"
xndll="$xnbin/lib64/wine:$xnbin/lib/wine"
}
xn32 () {
xstrt="wine"
xnldl="$xnbin/lib"
xndll="$xnbin/lib/wine"
}
xnint () {
if [[ "$x" = "p" ]]; then
xnbin="$pnbin"
xnpfx="$pnpfx"
dpth=(4 3)
else
xnbin="$wnbin"
xnpfx="$wnpfx"
dpth=(3 2)
fi
}
xnexe () {
# menu installed wine/proton or exit
readarray -t i_mnus < <(find -L "$xnbin" -maxdepth "${dpth[0]}" -type f -iname 'wine' ! \( -ipath '*/sbin*' \) 2>/dev/null | perl -pe "s|\Q$xnbin\E/(.*)[/]*bin/wine|\1| ; s|/$||" | sort ; echo "quit")
if [[ ${#i_mnus[@]} -gt 2 ]]; then
clear
w_menu
xnbin="$(realpath "$xnbin/$xmrtn")"
unset xmrtn
elif [[ ${#i_mnus[@]} -eq 2 ]]; then
xnbin="$(realpath "$xnbin/${i_mnus[0]}")"
else
echo "No installed Wine/Proton found."
exit 1
fi
}
xndef () {
# create default prefix cross-function
if [[ "$x" = "p" ]]; then
if [[ ! -d "$xnpfx/0" ]]; then
# always create default 0 prefix
xnpfx="$xnpfx/0"
echo "Creating default prefix: $xnpfx"
mkdir -p "$xnpfx"
STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" run > /dev/null 2>&1 &
xnpfx="$xnpfx/pfx"
fi
else
if [[ ! -d "$xnpfx/.wine" ]]; then
# always create default wine prefix
xnpfx="$xnpfx/.wine"
echo "Creating default prefix: $xnpfx"
WINEPREFIX="$xnpfx" "$xnbin"/bin/winecfg > /dev/null 2>&1 &
if [[ -d "$HOME/.wine" && "$HOME/.wine" != "$xnpfx" ]]; then
rm -rf "$HOME"/.wine
ln -sf "$xnpfx" "$HOME"/.wine
fi
fi
fi
}
xnpre () {
# menu wine/proton prefix
readarray -t i_mnus < <(find "$xnpfx" -maxdepth "${dpth[1]}" -type f -iname 'system.reg' 2>/dev/null | perl -pe "s|\Q$xnpfx\E/(.*)/system.reg|\1|" | sort ; echo "quit")
# use perl escaped Q/E to preserve special characters in path variable
if [[ ${#i_mnus[@]} -gt 2 ]]; then
# display menu with min two options plus quit
# guard proton cross-function
if [[ "$x" = "p" ]]; then
# shellcheck disable=SC2044
for value in $(find "$xnpfx" -maxdepth 1 -type d -ipath '*/[0-9]*' -printf "${xnpfx///compatdata}/appmanifest_%P.acf\n" 2>/dev/null); do
test -f "$value" && myprnt+=("$(grep -Pio '^\s+\"(appid|name)\"\s+\"(.*)\"' "$value" | perl -pe 's/.*appid.+?\"(.*)\"\v|.*name.+?\"(.*)\"/\1 \2/')")
done
if [[ ${#myprnt[@]} -gt 0 ]]; then
printf '%s\n' "${myprnt[@]}" | sort
fi
# correlate appmanifest to proton prefix and list before menu
unset myprnt
fi
w_menu
xnpfx="$xnpfx/$xmrtn"
unset xmrtn
elif [[ ${#i_mnus[@]} -eq 2 ]]; then
# don't menu if only one option plus quit
xnpfx="$xnpfx/${i_mnus[0]}"
fi
if [[ -d "$xnpfx/$progs (x86)" ]]; then
xn64
else
xn32
fi
}
xnenv () {
# core env vars allow proper targetting of wine/proton
xpath="$xnbin/bin:$PATH"
xcmd=(env PATH="$xpath" WINEDLLPATH="$xndll" LD_LIBRARY_PATH="$xnldl" WINEPREFIX="$xnpfx")
# guard proton cross-function which adds on to core env vars
if [[ "$x" = "p" ]]; then
xcmd+=(STEAM_COMPAT_DATA_PATH="${xnpfx///pfx}" STEAM_COMPAT_CLIENT_INSTALL_PATH="$pntop")
fi
}
xnldr () {
# loader default to proton as applicable, otherwise wine
if [[ "$x" = "p" ]]; then
read -r -p 'wine loader? [y/N] ' chse
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
xcmd+=("$xstrt")
else
xcmd+=("${xnbin%/*}/proton" "run")
fi
else
xcmd+=("$xstrt")
fi
}
xnset () {
# set cross-fuction
xnint
# wine/proton menu
xnexe
# create default prefix as required
xndef
# wine/proton prefix
xnpre
# wine/proton env vars
xnenv
}
xlnch () {
# cross-function command line launcher
if [[ -z "$dbg" ]]; then
("${xcmd[@]}" > /dev/null 2>&1 &)
else
echo "${xcmd[@]}"
if [[ "$dbg" = "1" ]]; then
("${xcmd[@]}" &)
elif [[ "$dbg" = "2" ]]; then
(WINEDEBUG="warn+all" "${xcmd[@]}" &)
fi
fi
# prepend cmd with dbg=1 to see command and default debug output
# dbg=2 to see command and all debug output, dbg=? for command only
}
allexe () {
# unfiltered list of exe in specified path
if [[ -n "$(stat --file-system --format=%T "$(stat --format=%m "$pedir" 2>/dev/null)" 2>/dev/null | grep -Pio 'fuse')" ]]; then
readarray -t i_mnus < <(find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname '*.exe' 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort ; echo "quit")
# skip exe validity tests if file is on network drive
else
readarray -t i_mnus < <(env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname '*.exe' -exec sh -c '(readpe -h optional "$1" 2>/dev/null | grep -Piq '0x2.*gui') && (wrestool "$1" 2>/dev/null | grep -Piq 'type=icon') && echo "$1" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|"' -- {} \; 2>/dev/null | sort ; echo "quit")
# perform exe validity tests if file is on local drive
fi
}
fewexe () {
# filtered list of exe in standard paths
readarray -t i_mnus < <(env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended ! \( -ipath '*cache*' -o -ipath '*/microsoft*' -o -ipath '*/windows*' -o -ipath '*/temp*' \) ! \( -iregex '.*(capture|clokspl|helper|iexplore|install|internal|kernel|[^ ]launcher|legacypm|overlay|proxy|redist|renderer|(crash|error)reporter|serv(er|ice)|setup|streaming|tutorial|unins|update).*' \) -iname '*.exe' -exec sh -c '(readpe -h optional "$1" 2>/dev/null | grep -Piq '0x2.*gui') && (wrestool "$1" 2>/dev/null | grep -Piq 'type=icon') && echo "$1" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|"' -- {} \; 2>/dev/null | sort ; echo "quit")
# valid exe will have gui and icon
}
alloth () {
# unfiltered list of variable type in specified path
readarray -t i_mnus < <(find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname "$xflt" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort ; echo "quit")
}
fewoth () {
# filtered list of variable type in standard paths
readarray -t i_mnus < <(env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended ! \( -ipath '*cache*' -o -ipath '*/microsoft*' -o -ipath '*/windows*' -o -ipath '*/temp*' \) ! \( -iregex '.*(capture|clokspl|helper|iexplore|install|internal|kernel|[^ ]launcher|legacypm|overlay|proxy|redist|renderer|(crash|error)reporter|serv(er|ice)|setup|streaming|tutorial|unins|update).*' \) -iname "$xflt" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort ; echo "quit")
}
xbld () {
# cross-function custom prefix builder
pnpfx="$pnpfx/${clprm[0]}"
wnpfx="$wnpfx/${clprm[0]}"
xnint
if [[ -z "${clprm[0]}" ]]; then
echo "Wine/Proton prefix name required: (e.g. .wine, 0 )"
elif [[ -d "$xnpfx" ]]; then
echo "Wine/Proton Prefix exists: $xnpfx"
else
xnexe
echo "Creating Wine/Proton Prefix: ${clprm[0]}"
if [[ "$x" = "p" ]]; then
xnenv
mkdir -p "$xnpfx"
xcmd+=(STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" "run")
else
read -r -p '32-bit only? [y/N] ' chse
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
xn32
xnenv
xcmd+=(WINEARCH="win32" "$xstrt" "winecfg.exe")
else
xn64
xnenv
xcmd+=(WINEARCH="win64" "$xstrt" "winecfg.exe")
fi
fi
xlnch
fi
}
xpmn () {
# use specified exe, menu specified folder, or menu system
if [[ -f "${clprm[0]}" ]]; then
# parse 1st cmdline arg, queue if valid file
pedir="$(realpath "${clprm[0]}")"
xmrtn="$(basename "$pedir")"
pedir="$(dirname "$pedir")"
else
if [[ -d "${clprm[0]}" ]]; then
# parse 1st cmdline arg, use as path if valid
pedir="$(realpath "${clprm[0]}")"
test -z "$xflt" && allexe || alloth
else
# if no cmdline path, use prefix drive_c
pedir="$xnpfx/drive_c"
test -z "$xflt" && fewexe || fewoth
fi
# create menu, from path, of file
test ${#i_mnus[@]} -gt 1 && w_menu
fi
}
xlyt() {
# pe layout for launch
# 64-bit prefix, 32-bit pe header, reset env to 32
if [[ -n "$(readpe -h optional "$pedir/$xmrtn" 2>/dev/null | grep -Pi 'magic number.*0x10b')" && -d "$xnpfx/$progs (x86)" ]]; then
xn32
xnenv
fi
xnldr
# if 1st arg is file/folder, skip it and run selection + remaining args
if [[ -e "${clprm[0]}" ]];then
xcmd+=("$pedir/$xmrtn" "${clprm[@]:1}")
else
xcmd+=("$pedir/$xmrtn" "${clprm[@]}")
fi
}
xstm() {
if [[ "$x" = "p" ]]; then
sstrt="$(realpath "$(which steam)" 2>/dev/null)"
else
xnset
sstrt="$(find "$xnpfx/drive_c" -maxdepth 3 -iname 'steam.exe' 2>/dev/null)"
if [[ -f "$sstrt" ]]; then
pnapp="$(dirname "$sstrt")/steamapps"
xcmd+=("$xstrt")
fi
fi
# find wine/proton steam binary path, normally subdir of program files
if [[ -f "$sstrt" ]]; then
test -d "$pnapp" && readarray -t i_mnus < <(find "$pnapp" -maxdepth 1 -type f -iname 'appmanifest_*.acf' -exec grep -Pio '^\s+\"(appid|name)\"\s+\"(.*)\"' "{}" \; 2>/dev/null | perl -pe 's/.*appid.+?\"(.*)\"\v|.*name.+?\"(.*)\"/\1 \2/' | sort ; echo -e "steam\nquit")
# read appmanifests to create menu entries
test ${#i_mnus[@]} -gt 2 && w_menu && xmrtn="$(expr "$xmrtn" : '\([0-9]*\)')"
if [[ -n "$xmrtn" ]]; then
# lauch selection with steam
xcmd+=("$sstrt" "-no-browser" "-applaunch" "$xmrtn")
xlnch
else
# launch steam was selected
# minigamelist (short game list) for no-browser (disabled chrome) to save memory
xcmd+=("$sstrt" "-no-browser" "steam://open/minigameslist")
xlnch
fi
else
echo -e "Steam not found."
fi
}
xpge () {
test -d "$pnpge" || mkdir -p "$pnpge"
test -d "$pnbin" || mkdir -p "$pnbin"
@@ -79,280 +401,210 @@ xpge() {
fi
}
xn64() {
xstrt="wine64"
xnldl="$xnbin/lib64:$xnbin/lib"
xndll="$xnbin/lib64/wine:$xnbin/lib/wine"
}
xn32() {
xstrt="wine"
xnldl="$xnbin/lib"
xndll="$xnbin/lib/wine"
}
w_menu() {
PS3="Please enter your choice: "
select answer in "${i_mnus[@]}"; do
for item in "${i_mnus[@]}"; do
if [[ $item == "$answer" ]]; then
break 2
fi
done
done
# repeating menu requires valid selection from array
if [[ "$answer" = "quit" ]]; then
# pop quit from end of array for menu option
exit
else
xmrtn="$answer"
fi
unset i_mnus
clear
}
xnexe() {
# menu installed wine/proton or exit
readarray -t i_mnus < <(
find -L "$xnbin" -maxdepth "${dpth[0]}" -type f -iname 'wine' ! \( -ipath '*/sbin*' \) 2>/dev/null | perl -pe "s|\Q$xnbin\E/(.*)[/]*bin/wine|\1| ; s|/$||" | sort
echo "quit"
)
if [[ ${#i_mnus[@]} -gt 2 ]]; then
clear
w_menu
xnbin="$(realpath "$xnbin/$xmrtn")"
unset xmrtn
elif [[ ${#i_mnus[@]} -eq 2 ]]; then
xnbin="$(realpath "$xnbin/${i_mnus[0]}")"
else
echo "No installed Wine/Proton found."
exit 1
fi
}
xnenv() {
# core env vars allow proper targetting of wine/proton
xpath="$xnbin/bin:$PATH"
xcmd=(env PATH="$xpath" WINEDLLPATH="$xndll" LD_LIBRARY_PATH="$xnldl" WINEPREFIX="$xnpfx")
xcmd+=(STEAM_COMPAT_DATA_PATH="${xnpfx///pfx}" STEAM_COMPAT_CLIENT_INSTALL_PATH="$pntop")
}
xlnch() {
#command line launcher
if [[ -z "$dbg" ]]; then
("${xcmd[@]}" >/dev/null 2>&1 &)
else
if [[ "$dbg" = "1" ]]; then
("${xcmd[@]}" &)
elif [[ "$dbg" = "2" ]]; then
(WINEDEBUG="warn+all" "${xcmd[@]}" &)
fi
fi
# prepend cmd with dbg=1 to see command and default debug output
# dbg=2 to see command and all debug output, dbg=? for command only
}
xbld() {
# cross-function custom prefix builder
pnpfx="$pnpfx/${clprm[0]}"
xnint
if [[ -z "${clprm[0]}" ]]; then
echo -e "\n Proton prefix name required, use an appid from Steam: (e.g. 0, 730 ) \n"
elif [[ -d "$xnpfx" ]]; then
echo -e "\n Proton Prefix exists: $xnpfx \n"
else
xnexe
echo "Creating Proton Prefix: ${clprm[0]}"
xnenv
mkdir -p "$xnpfx"
xcmd+=(STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" "run")
xlnch
fi
}
xnpre() {
if [[ -d "$xnpfx/$progs (x86)" ]]; then
xn64
else
xn32
fi
}
xndef() {
# create default prefix cross-function
if [[ -z "$prfx" ]]; then
echo "INFO: to use a specific prefix, append prfx='your prefix' to this command"
if [[ ! -d "$xnpfx/0" ]]; then
# always create default 0 prefix
xnpfx="$xnpfx/0"
echo "Creating default prefix: $xnpfx"
mkdir -p "$xnpfx"
STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" run >/dev/null 2>&1 &
xnpfx="$xnpfx/pfx"
else
xnpfx="$xnpfx/0"
xnpfx="$xnpfx/pfx"
fi
else
xnpfx="$xnpfx/$prfx"
if [[ ! -d "$xnpfx" ]]; then
echo "Creating default prefix: $xnpfx"
mkdir -p "$xnpfx"
STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" run >/dev/null 2>&1 &
xnpfx="$xnpfx/pfx"
else
xnpfx="$xnpfx/pfx"
fi
fi
}
fewoth() {
# filtered list of variable type in standard paths
readarray -t i_mnus < <(
env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended ! \( -ipath '*cache*' -o -ipath '*/microsoft*' -o -ipath '*/windows*' -o -ipath '*/temp*' \) ! \( -iregex '.*(capture|clokspl|helper|iexplore|install|internal|kernel|[^ ]launcher|legacypm|overlay|proxy|redist|renderer|(crash|error)reporter|serv(er|ice)|setup|streaming|tutorial|unins|update).*' \) -iname "$xflt" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort
echo "quit"
)
}
fewexe() {
# filtered list of exe in standard paths
readarray -t i_mnus < <(
env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended ! \( -ipath '*cache*' -o -ipath '*/microsoft*' -o -ipath '*/windows*' -o -ipath '*/temp*' \) ! \( -iregex '.*(capture|clokspl|helper|iexplore|install|internal|kernel|[^ ]launcher|legacypm|overlay|proxy|redist|renderer|(crash|error)reporter|serv(er|ice)|setup|streaming|tutorial|unins|update).*' \) -iname '*.exe' -exec sh -c '(readpe -h optional "$1" 2>/dev/null | grep -Piq '0x2.*gui') && (wrestool "$1" 2>/dev/null | grep -Piq 'type=icon') && echo "$1" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|"' -- {} \; 2>/dev/null | sort
echo "quit"
)
# valid exe will have gui and icon
}
alloth() {
# unfiltered list of variable type in specified path
readarray -t i_mnus < <(
find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname "$xflt" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort
echo "quit"
)
}
allexe() {
# unfiltered list of exe in specified path
if [[ -n "$(stat --file-system --format=%T "$(stat --format=%m "$pedir" 2>/dev/null)" 2>/dev/null | grep -Pio 'fuse')" ]]; then
readarray -t i_mnus < <(
find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname '*.exe' 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort
echo "quit"
)
# skip exe validity tests if file is on network drive
else
readarray -t i_mnus < <(
env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname '*.exe' -exec sh -c '(readpe -h optional "$1" 2>/dev/null | grep -Piq '0x2.*gui') && (wrestool "$1" 2>/dev/null | grep -Piq 'type=icon') && echo "$1" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|"' -- {} \; 2>/dev/null | sort
echo "quit"
)
# perform exe validity tests if file is on local drive
fi
}
xpmn() {
# use specified exe, menu specified folder, or menu system
if [[ -f "${clprm[0]}" ]]; then
# parse 1st cmdline arg, queue if valid file
pedir="$(realpath "${clprm[0]}")"
xmrtn="$(basename "$pedir")"
pedir="$(dirname "$pedir")"
else
if [[ -d "${clprm[0]}" ]]; then
# parse 1st cmdline arg, use as path if valid
pedir="$(realpath "${clprm[0]}")"
test -z "$xflt" && allexe || alloth
else
# if no cmdline path, use prefix drive_c
pedir="$xnpfx/drive_c"
test -z "$xflt" && fewexe || fewoth
fi
# create menu, from path, of file
test ${#i_mnus[@]} -gt 1 && w_menu
fi
}
xnldr() {
# loader default to proton as applicable, otherwise wine
if [[ -z "$wn" ]]; then
xcmd+=("${xnbin%/*}/proton" "run")
else
if [[ "$wn" = "true" ]]; then
xcmd+=("$xstrt")
else
echo "unrecognised run option"
exit 1
fi
fi
}
xlyt() {
# prepare layout for launch
# 64-bit prefix, 32-bit prefix header, reset env to 32
if [[ -n "$(readpe -h optional "$pedir/$xmrtn" 2>/dev/null | grep -Pi 'magic number.*0x10b')" && -d "$xnpfx/$progs (x86)" ]]; then
xn32
xnenv
fi
xnldr
# if 1st arg is file/folder, skip it and run selection + remaining args
if [[ -e "${clprm[0]}" ]]; then
xcmd+=("$pedir/$xmrtn" "${clprm[@]:1}")
else
xcmd+=("$pedir/$xmrtn" "${clprm[@]}")
fi
}
xnset() {
# set cross-fuction
xnint
# proton menu
xnexe
# create default prefix as required
xndef
# proton prefix
xnpre
# proton env vars
xnenv
xwn () {
export WINE_BRANCH=staging
sudo mkdir -pm755 /etc/apt/keyrings && sudo curl -fsSL -o /etc/apt/keyrings/winehq-archive.key "https://dl.winehq.org/wine-builds/winehq.key" \
&& sudo curl -fsSL -o "/etc/apt/sources.list.d/winehq-$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"').sources" "https://dl.winehq.org/wine-builds/ubuntu/dists/$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"')/winehq-$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"').sources" \
&& sudo apt-get update && sudo apt-get install --install-recommends -y winehq-${WINE_BRANCH} \
&& sudo curl -fsSL -o /usr/bin/winetricks "https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks" \
&& sudo chmod 755 /usr/bin/winetricks \
&& sudo curl -fsSL -o /usr/share/bash-completion/completions/winetricks "https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks.bash-completion"
}
usage() {
echo -e "\n$(basename $0): ERROR - $*" 1>&2
echo -e "\nusage: $(basename $0)\n [-i,--install] [-b,--build] [-r,--run] \n \n (install) install proton-ge \n (build) build a custom proton prefix \n (run) run an .exe program \n \n" 1>&2
echo -e "\n$(basename $0): ERROR - $*" 1>&2
echo -e "\nusage: $(basename $0)\n [-?a,--?add] [-?b,--?bld] [-?c,--?cmd] [-?d,--?dsk]\n [-?i,--?inf] [-?k,--?kil] [-?o,--?ovr] [-?p,--?prg]\n [-?s,--?stm] [-?t,--?trk] [-?u,--?cut] [-?v,--?ver]\n\n[?] = (p)roton, (w)ine\n (add) exe path to reg, (bld) build prefix,\n (cmd) prog menu, (dsk) desktop, (inf) exe info,\n (kil) kill wine, (ovr) overrides, (prg) exe list,\n (stm) steam, (trk) winetricks, (cut) shortcut,\n (ver) wine version\n" 1>&2
}
if [[ $# -lt 1 ]]; then
usage "one option required!"
usage "one option required!"
else
case $xarg in
-i | --install)
# proton ge
xpge
;;
-p | --prefix)
# prefix builder
xbld
;;
-r | --run)
# second arg should be the prefix to use.
# run program - 1st arg valid file to run, folder to menu,
# neither (sys menu), 2nd arg... passed to exe
case $xarg in
-xa|--xadd)
# cross-fuction path add to registry based on exe
xnint
xnpre
xpmn
if [[ -n "$xmrtn" ]]; then
ptadd="$(dirname "$pedir/$xmrtn")"
ptadd="z:${ptadd////\\\\}"
read -r -p 'prepend to system path? [y/N] ' chse
clear
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
xnreg='System\\CurrentControlSet\\Control\\Session Manager\\Environment'
xmrtn='system.reg'
else
xnreg='Environment'
xmrtn='user.reg'
fi
if [[ -z "$(pcre2grep -Mio "\[\Q${xnreg,,}\E\](?s).+?\"PATH\"=str\(2\):\".+?(?=\[.+?\])(?-s)" "$xnpfx/$xmrtn")" ]]; then
perl -0777 -pi -e "s|(\[\Q${xnreg,,}\E\](?s).+?#time=(?-s).*)(?s)(.+?)(?=\[.+?\])(?-s)|\\1\n\"PATH\"=str\(2\):\"${ptadd//\\/\\\\}\"\\2|gi" "$xnpfx/$xmrtn"
echo -e "$( (echo "$xnreg" | grep -Pioq '\\Environment') && echo 'HKLM\\' || echo 'HKCU\\')$xnreg:\n\n $ptadd\n\nPATH created successfully\n"
elif [[ -z "$(pcre2grep -Mio "\[\Q${xnreg,,}\E\](?s).+?\"PATH\"=str\(2\):\"(?-s).*\Q${ptadd,,}\E[\;\"](?s).+?(?=\[.+?\])(?-s)" "$xnpfx/$xmrtn")" ]]; then
perl -0777 -pi -e "s|(\[\Q${xnreg,,}\E\](?s).+?\"PATH\"=str\(2\):\")(?-s)(.*)(?s)(.+?)(?=\[.+?\])(?-s)|\\1${ptadd//\\/\\\\}\;\\2\\3|gi" "$xnpfx/$xmrtn"
echo -e "$( (echo "$xnreg" | grep -Pioq '\\Environment') && echo 'HKLM\\' || echo 'HKCU\\')$xnreg:\n\n $ptadd\n\nPATH added successfully\n"
else
echo -e "$( (echo "$xnreg" | grep -Pioq '\\Environment') && echo 'HKLM\\' || echo 'HKCU\\')$xnreg:\n\n $ptadd\n\nalready in PATH\n"
fi
# \Q \E adds \ to non alphanums but variable with \E ends \Q
# lowercase ${var,,} to avoid since path/reg not case sensitive
# linux path is case sensitive so user must not create duplicates
fi
;;
-xb|--xbld)
# cross-function prefix builder
xbld
;;
-xc|--xcmd)
# cross-function standard tools menu
xnset
readarray -t i_mnus < <(printf '%s\n' "${pmenu[@]}" | perl -pe 's|/.*||gi' ; echo "quit")
w_menu
xmrtn="$(printf '%s\n' "${pmenu[@]}" | grep -Pio "(?<=$xmrtn/).*")"
xnldr
if [[ -f "${clprm[0]}" ]];then
pedir="$(realpath "${clprm[0]}")"
cd "$(dirname "$pedir")" || exit
xcmd+=("$xmrtn" "$pedir" "${clprm[@]:1}")
else
xcmd+=("$xmrtn" "${clprm[@]}")
fi
xlnch
;;
-xd|--xdsk)
# cross-function wine desktop
xnset
xnldr
xcmd+=("explorer.exe" "/desktop=shell,1024x768" "explorer.exe")
xlnch
;;
-i|--install)
# proton ge
xpge
xwn
;;
-xi|--xinf)
# cross-fuction program info
if [[ ! -f "${clprm[0]}" && ! -d "${clprm[0]}" ]]; then
# don't menu prefix on supplied file or folder
xnint
xnpre
fi
if [[ ! -f "${clprm[0]}" ]]; then
# offer to menu dll if no file given
read -r -p 'query dll? [y/N] ' chse
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
xflt="*.dll"
fi
fi
xpmn
IFS=$'\n'
if [[ -n "$xmrtn" ]]; then
if [[ $(readpe "$pedir/$xmrtn" 2>/dev/null) ]]; then
# if file is PE print 32/64-bit and dll references
myprnt+=("$(readpe -h optional "$pedir/$xmrtn" 2>/dev/null | grep -Piq 'PE32\+' && echo -e "FILE:\n$xmrtn\n \nPE HEADER:\n64-bit" || echo -e "FILE:\n$xmrtn\n \nPE HEADER:\n32-bit")")
myprnt+=("$(echo -e ' \nVersion:' ; peres -v "$pedir/$xmrtn" 2>/dev/null | grep -Pio '(?<=Product Version:).*' | tr -d ' ')")
# find dll references, filenames without spaces
myprnt+=("$(echo -e ' \nREFERENCES:' ; strings "$pedir/$xmrtn" | grep -Pio '[^<>:"/\\|?*\s]+\.dll' | perl -pe 's|([^/]*\Z)|lc($1)|e' | sort -u ; echo ' ')")
else
myprnt+=("$(echo -e ' \nNot a 32/64-bit program, no information to provide\n ')")
fi
else
myprnt+=("$(echo -e ' \nNo file found\n ')")
fi
printf '%s\n' "${myprnt[@]}"
unset IFS myprnt
;;
-xk|--xkil)
# cross-function wine kill, must select same as running
xnset
xcmd+=("wineserver" "-k")
xlnch
;;
-xo|--xovr)
# cross-function prefix override list
xnint
xnpre
read -r -p 'per application? [y/N] ' chse
clear
IFS=$'\n'
myprnt+=("$(echo -e "Prefix:\n$xnpfx\n ")")
if [[ "$chse" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
# show existing per-application overrides
myprnt+=("$(echo -e 'Per-application overrides:' ; pcre2grep -Mio '\[\Qsoftware\\wine\\appdefaults\\\E[^\\]+\Q\\dlloverrides\E\](?s).+?(?=\[.+?\])(?-s)' "$xnpfx/user.reg" | grep -Pio '(?<=appdefaults..).*(?=..dlloverrides)|\".*\"' && echo ' ' || echo -e 'None found\n ')")
else
# show existing prefix overrides
myprnt+=("$(echo -e 'Global overrides:' ; pcre2grep -Mio '\[\Qsoftware\\wine\\dlloverrides\E\](?s).+?(?=\[.+?\])(?-s)' "$xnpfx/user.reg" | grep -Pio '\".*\"' && echo ' ' || echo -e 'None found\n ')")
fi
printf '%s\n' "${myprnt[@]}"
unset IFS myprnt
# A command like:
# perl -pi -e 's/(\".*msvc.*\"=\")(.*),(.*)(")/\1\3,\2\4/g' user.reg
# Swaps msvc entries (native,builtin) to (builtin,native)
;;
-xr|--xrun)
# cross-fuction run program - 1st arg valid file to run, folder to menu,
# neither (sys menu), 2nd arg... passed to exe
xnset
xpmn
if [[ -n "$xmrtn" ]]; then
xlyt
# change to exe dir before run
cd "$(dirname "$pedir/$xmrtn")" || exit
xlnch
fi
;;
-xs|--xstm)
# cross-function steam launcher
xstm
;;
-xt|--xtrk)
# cross-function winetricks
xnset
# winetricks for selected wine/proton prefix
if [[ ${#clprm[@]} -gt 0 ]]; then
xcmd+=("winetricks" "${clprm[@]}")
dbg="1"
# use args if supplied, otherwise gui
else
xcmd+=("winetricks" "--gui")
# protontricks may work better
fi
xlnch
;;
-xu|--xcut)
# cross-function desktop shortcut
if [[ -d "$desk" ]]; then
xnset
xpmn
if [[ -n "$xmrtn" ]]; then
xlyt
# change to exe dir before run
cd "$(dirname "$pedir/$xmrtn")"
xlnch
xlyt
# change to desktop dir before create icon
cd "$desk" || exit
read -r -e -p $'Shortcut Name?\x0a' -i "$(basename "${xmrtn/.*}")" chse
# create desktop entry
gendesk -f -n --name="$chse" --comment='created by wstart' --custom='Keywords=wine;proton;launcher;' --exec="bash -c 'cd \"$(dirname "$pedir/$xmrtn")\" ; $(printf '"%s" ' "${xcmd[@]}")'" --icon="$icon" --terminal=false --categories='Emulator;Game' --startupnotify=false --pkgname="$chse"
chmod 755 "$chse".desktop
fi
;;
-* | \* | *)
# do_usage
usage "invalid option $1"
exit 1
;;
esac
fi
#FIXME: it won't run anything AAAArgh!
else
echo -e "Invalid desktop location: $desk\nPlease edit the script"
fi
;;
-xv|--xver)
# cross-function wine version
xnint
xnexe
xnenv
xcmd+=("wine" "--version")
("${xcmd[@]}" &)
;;
-h|--help)
echo -e "\n General usage: netris-proton -w? args\n -w? options for wine and -p? for proton.\n Type wstart by itself for command list.\n\n Edit script path variables as needed.\n bash, find, gendesk, grep, readpe,\n strings, winetricks, wrestool,\n pcre2grep, peres, perl needed by\n certain items.\n"
;;
-*|\*|*)
# do_usage
usage "invalid option $1"
exit 1
;;
esac
fi

View File

@@ -10,6 +10,7 @@ files = /etc/supervisord.d/*.ini
[program:entrypoint]
command=/etc/entrypoint.sh
user=netris
logfile=/tmp/entrypoint.log
pidfile=/tmp/entrypoint.pid
stopsignal=INT
@@ -35,7 +36,7 @@ command=bash -c "until [ -S \"/tmp/.X11-unix/X${DISPLAY/:/}\" ]; do sleep 1; don
logfile=/tmp/warp-input.log
pidfile=/tmp/warp-input.pid
stopsignal=INT
user=%(ENV_USER)s
user=netris
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY=":0",SESSION_ID="%(ENV_SESSION_ID)s"
autostart=true
autorestart=true

View File

@@ -24,13 +24,13 @@ RUN apt-get update -y \
&& rm -rf /var/lib/apt/lists/*
#Install wine
ARG WINE_BRANCH=staging
RUN mkdir -pm755 /etc/apt/keyrings && curl -fsSL -o /etc/apt/keyrings/winehq-archive.key "https://dl.winehq.org/wine-builds/winehq.key" \
&& curl -fsSL -o "/etc/apt/sources.list.d/winehq-$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"').sources" "https://dl.winehq.org/wine-builds/ubuntu/dists/$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"')/winehq-$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"').sources" \
&& apt-get update && apt-get install --install-recommends -y winehq-${WINE_BRANCH} \
&& curl -fsSL -o /usr/bin/winetricks "https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks" \
&& chmod 755 /usr/bin/winetricks \
&& curl -fsSL -o /usr/share/bash-completion/completions/winetricks "https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks.bash-completion"
# ARG WINE_BRANCH=staging
# RUN mkdir -pm755 /etc/apt/keyrings && curl -fsSL -o /etc/apt/keyrings/winehq-archive.key "https://dl.winehq.org/wine-builds/winehq.key" \
# && curl -fsSL -o "/etc/apt/sources.list.d/winehq-$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"').sources" "https://dl.winehq.org/wine-builds/ubuntu/dists/$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"')/winehq-$(grep UBUNTU_CODENAME= /etc/os-release | cut -d= -f2 | tr -d '\"').sources" \
# && apt-get update && apt-get install --install-recommends -y winehq-${WINE_BRANCH} \
# && curl -fsSL -o /usr/bin/winetricks "https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks" \
# && chmod 755 /usr/bin/winetricks \
# && curl -fsSL -o /usr/share/bash-completion/completions/winetricks "https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks.bash-completion"
#Install Proton
COPY .scripts/proton /usr/bin/netris-proton