mirror of
				https://github.com/mintty/wsltty.git
				synced 2025-10-31 15:12:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			458 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			458 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #! /bin/sh
 | |
| 
 | |
| # dash built-in echo enforces interpretation of \t etc
 | |
| echoc () {
 | |
|   #cmd /c echo $*
 | |
|   printf '%s\n' "$*"
 | |
| }
 | |
| 
 | |
| copy () {
 | |
|   from="$1"
 | |
|   to="$2"
 | |
|   export from to
 | |
|   cmd /c cmd2.bat copy
 | |
| }
 | |
| 
 | |
| delete () {
 | |
|   from="$1"
 | |
|   to="$1"	# same again, to fill parameter
 | |
|   export from to
 | |
|   cmd /c cmd2.bat del/F
 | |
| }
 | |
| 
 | |
| compare () {
 | |
|   from="$1"
 | |
|   to="$2"
 | |
|   export from to
 | |
|   cmd /c cmd2.bat comp/M
 | |
| }
 | |
| 
 | |
| 
 | |
| case "$installdir" in
 | |
| ?*)	custominst=true;;
 | |
| "")	custominst=false;;
 | |
| esac
 | |
| 
 | |
| INSTDIR="${installdir:-$LOCALAPPDATA/wsltty}"
 | |
| echoc "Installing wsltty into $INSTDIR"
 | |
| INSTDIR=`cd "$INSTDIR"; pwd`
 | |
| installcop=${installdir:-"$LOCALAPPDATA\\wsltty"}
 | |
| installdir=${installdir:-'%LOCALAPPDATA%\wsltty'}
 | |
| 
 | |
| target="$installdir"'\bin\mintty.exe'
 | |
| case "$INSTDIR" in
 | |
| */)	TARGETPATH="$INSTDIR"bin/mintty.exe;;
 | |
| *)	TARGETPATH="$INSTDIR"/bin/mintty.exe;;
 | |
| esac
 | |
| 
 | |
| CONFDIR="${configdir:-$APPDATA/wsltty}"
 | |
| configdir=${configdir:-'%APPDATA%\wsltty'}
 | |
| 
 | |
| PATH=/bin:"$PATH":$SYSTEMROOT/System32
 | |
| 
 | |
| contextmenu=false
 | |
| remove=false
 | |
| alldistros=true
 | |
| config=true
 | |
| 
 | |
| case "/$0" in
 | |
| */wsl*)
 | |
|   config=false;;
 | |
| esac
 | |
| 
 | |
| case "$1" in
 | |
| -info)
 | |
|   config=false
 | |
|   shift;;
 | |
| -shortcuts)
 | |
|   shift;;
 | |
| -shortcuts-remove)
 | |
|   remove=true
 | |
|   shift;;
 | |
| -default)
 | |
|   alldistros=false
 | |
|   shift;;
 | |
| -contextmenu)
 | |
|   contextmenu=true
 | |
|   shift;;
 | |
| -contextmenu-default)
 | |
|   contextmenu=true
 | |
|   alldistros=false
 | |
|   shift;;
 | |
| -contextmenu-remove)
 | |
|   contextmenu=true
 | |
|   remove=true
 | |
|   direckey='/HKEY_CURRENT_USER/Software/Classes/Directory'
 | |
| 
 | |
|   regtool list "$direckey/shell" 2>/dev/null |
 | |
|   while read name
 | |
|   do
 | |
|     case `regtool get "$direckey/shell/$name/command/"` in
 | |
|     *bin\\mintty.exe*/bin/wslbridge*|*bin\\mintty.exe*--WSL*)
 | |
|       regtool remove "$direckey/shell/$name/command"
 | |
|       regtool remove "$direckey/shell/$name"
 | |
|       ;;
 | |
|     esac
 | |
|   done
 | |
| 
 | |
|   regtool list "$direckey/Background/shell" 2>/dev/null |
 | |
|   while read name
 | |
|   do
 | |
|     case `regtool get "$direckey/Background/shell/$name/command/"` in
 | |
|     *bin\\mintty.exe*/bin/wslbridge*|*bin\\mintty.exe*--WSL*)
 | |
|       regtool remove "$direckey/Background/shell/$name/command"
 | |
|       regtool remove "$direckey/Background/shell/$name"
 | |
|       ;;
 | |
|     esac
 | |
|   done
 | |
|   exit
 | |
|   shift;;
 | |
| esac
 | |
| 
 | |
| 
 | |
| if $config && ! $contextmenu
 | |
| then
 | |
|   # remove shortcut entries in Start menu and cmd-line bat shortcuts
 | |
|   (cd "$INSTDIR"
 | |
|    for lnk in *.lnk
 | |
|    do
 | |
|      if compare "$lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\$lnk"
 | |
|      then delete "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\$lnk"
 | |
|      fi
 | |
|    done
 | |
|    for bat in *.bat
 | |
|    do
 | |
|      if compare "$bat" "$LOCALAPPDATA\\Microsoft\\WindowsApps\\$bat"
 | |
|      then delete "$LOCALAPPDATA\\Microsoft\\WindowsApps\\$bat"
 | |
|      fi
 | |
|    done
 | |
|   )
 | |
| fi
 | |
| 
 | |
| # test w/o WSL: call this script with REGTOOLFAKE=true dash config-distros.sh
 | |
| if ${REGTOOLFAKE:-false}
 | |
| then
 | |
| regtool () {
 | |
|   case "$1" in
 | |
|   -*)  shift;;
 | |
|   esac
 | |
|   key=`echo $2 | sed -e 's,.*{\(.*\)}.*,\1,' -e t -e d`
 | |
|   case "$1.$2" in
 | |
|   list.*)
 | |
|         if $contextmenu
 | |
|         then  echo "{0}"
 | |
|         else  echo "{1}"; echo "{2}"
 | |
|         fi;;
 | |
|   get.*/DistributionName)
 | |
|         echo "distro$key";;
 | |
|   get.*/BasePath)
 | |
|         echo "C:\\Program\\{$key}\\State";;
 | |
|   get.*/PackageFamilyName)
 | |
|         echo "distro{$key}";;
 | |
|   get.*/PackageFullName)
 | |
|         echo "C:\\Program\\{$key}";;
 | |
|   esac
 | |
| }
 | |
| fi
 | |
| 
 | |
| mkbat () {
 | |
| 	echo Creating "$1.bat"
 | |
| 	while read line; do echo "$line"; done <<-\/EOB > "$1".bat
 | |
| 	@echo off
 | |
| 	rem Start mintty terminal for WSL
 | |
| 	
 | |
| 	rem get basename of this script file,
 | |
| 	rem use it to select WSL distribution and homedir flag
 | |
| 	set dist=%~n0
 | |
| 	
 | |
| 	rem start in current directory
 | |
| 	set cdir=
 | |
| 	rem if script name ends with ~, extract WSL distribution and param -~
 | |
| 	if "%dist:~-1%" == "~" set cdir=-~ && set dist=%dist:~0,-1%
 | |
| 	rem map WSL default distribution
 | |
| 	if "%dist%" == "WSL" set dist=
 | |
| 	
 | |
| 	rem check if we have an explicit -d DIST parameter
 | |
| 	if "%1" == "-d" set dist=%2 && shift && shift
 | |
| 	
 | |
| 	chcp 65001 > nul:
 | |
| 	
 | |
| 	if "%1" == "" goto login
 | |
| 	
 | |
| 	:cmd
 | |
| 	"%LOCALAPPDATA%/wsltty/bin/mintty.exe" -i "%LOCALAPPDATA%/wsltty/wsl.ico" --WSL="%dist%" --configdir="%APPDATA%/wsltty" %cdir% %*
 | |
| 	goto end
 | |
| 	
 | |
| 	:login
 | |
| 	"%LOCALAPPDATA%/wsltty/bin/mintty.exe" -i "%LOCALAPPDATA%/wsltty/wsl.ico" --WSL="%dist%" --configdir="%APPDATA%/wsltty" %cdir% -
 | |
| 	
 | |
| 	:end
 | |
| 	/EOB
 | |
| }
 | |
| 
 | |
| if $custominst && $config && ! $remove
 | |
| then
 | |
|   #mkshortcut.exe -n "add to context menu" -a "$installdir/config-distros.sh -contextmenu" "$installdir/bin/dash.exe" -i '%SystemRoot%\System32\filemgmt.dll' -s min -d "" -w "$installdir"
 | |
|   #mkshortcut.exe -n "add default to context menu" -a "$installdir/config-distros.sh -contextmenu-default" "$installdir/bin/dash.exe" -i '%SystemRoot%\System32\filemgmt.dll' -s min -d "" -w "$installdir"
 | |
|   #mkshortcut.exe -n "remove from context menu" -a "$installdir/config-distros.sh -contextmenu-remove" "$installdir/bin/dash.exe" -i '%SystemRoot%\System32\filemgmt.dll' -s min -d "" -w "$installdir"
 | |
|   #mkshortcut.exe -n "configure WSL shortcuts" -a "$installdir/config-distros.sh" "$installdir/bin/dash.exe" -i '%SystemRoot%\System32\filemgmt.dll' -s min -d "" -w "$installdir"
 | |
| 
 | |
|   icon='%SystemRoot%\System32\filemgmt.dll'
 | |
|   wdir="$installdir"
 | |
|   target="$installdir/bin/dash.exe"
 | |
|   minttyargs="/config-distros.sh"
 | |
|   bridgeargs=
 | |
|   export icon wdir target minttyargs bridgeargs
 | |
|   cscript /nologo mkshortcut.vbs "/name:configure WSL shortcuts" "/min:true"
 | |
|   bridgeargs=-contextmenu
 | |
|   cscript /nologo mkshortcut.vbs "/name:add to context menu" "/min:true"
 | |
|   bridgeargs=-contextmenu-default
 | |
|   cscript /nologo mkshortcut.vbs "/name:add default to context menu" "/min:true"
 | |
|   bridgeargs=-contextmenu-remove
 | |
|   cscript /nologo mkshortcut.vbs "/name:remove from context menu" "/min:true"
 | |
| 
 | |
|   copy "add to context menu.lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\WSLtty"
 | |
|   copy "add default to context menu.lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\WSLtty"
 | |
|   copy "remove from context menu.lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\WSLtty"
 | |
|   copy "configure WSL shortcuts.lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\WSLtty"
 | |
| 
 | |
|   # restore target
 | |
|   target="$installdir"'\bin\mintty.exe'
 | |
| fi
 | |
| 
 | |
| lxss="/HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Lxss"
 | |
| schema="/HKEY_CURRENT_USER/Software/Classes/Local Settings/Software/Microsoft/Windows/CurrentVersion/AppModel/SystemAppData"
 | |
| 
 | |
| appex () {
 | |
|   while read line
 | |
|   do
 | |
| 	case "$line" in
 | |
| 	*Application*Executable*)
 | |
| 		for item in $line
 | |
| 		do	case "$item" in
 | |
| 			Executable=*)
 | |
| 				eval $item
 | |
| 				echo "$Executable"
 | |
| 				break;;
 | |
| 			esac
 | |
| 		done
 | |
| 		break;;
 | |
| 	esac
 | |
|   done < $*
 | |
| }
 | |
| 
 | |
| config () {
 | |
|   guid="$1"
 | |
|   ok=false
 | |
|   case $guid in
 | |
|   {*)
 | |
|     distro=`regtool get "$lxss/$guid/DistributionName"`
 | |
|     case "$distro" in
 | |
|     Legacy)
 | |
|     	name="Bash on Windows"
 | |
|     	launcher="$SYSTEMROOT/System32/bash.exe"
 | |
|     	;;
 | |
|     *)	name="$distro"
 | |
|     	launcher="$LOCALAPPDATA/Microsoft/WindowsApps/$distro.exe"
 | |
|     	;;
 | |
|     esac
 | |
|     basepath=`regtool get "$lxss/$guid/BasePath"`
 | |
|     if package=`regtool -q get "$lxss/$guid/PackageFamilyName"`
 | |
|     then
 | |
|     	distrinst=`regtool get "$schema/$package/Schemas/PackageFullName"`
 | |
|     	# get actual executable path (may not match $distro) from app manifest
 | |
|     	manifest="$ProgramW6432/WindowsApps/$distrinst/AppxManifest.xml"
 | |
|     	psh_cmd='([xml]$(Get-Content '"\"$manifest\""')).Package.Applications.Application.Executable'
 | |
|     	executable=`appex "$manifest"`
 | |
|     	if [ -r "$ProgramW6432/WindowsApps/$distrinst/$executable" ]
 | |
|     	then	icon="$ProgramW6432/WindowsApps/$distrinst/$executable"
 | |
|     	elif [ -r "$ProgramW6432/WindowsApps/$distrinst/images/icon.ico" ]
 | |
|     	then	icon="$ProgramW6432/WindowsApps/$distrinst/images/icon.ico"
 | |
|     	else	icon="$installcop"'\wsl.ico'
 | |
|     	fi
 | |
|     	root="$basepath/rootfs"
 | |
|     elif [ -f "$basepath/$distro.exe" ]
 | |
|     then
 | |
|     	icon="$basepath/$distro.exe"
 | |
|     	root="$basepath/rootfs"
 | |
|     elif [ -d "$LOCALAPPDATA/lxss" ]
 | |
|     then
 | |
|     	# legacy "Bash on Windows"
 | |
|     	icon="$LOCALAPPDATA/lxss/bash.ico"
 | |
|     	root="$basepath"
 | |
|     else
 | |
|     	# imported distro? (#226, #236)
 | |
|     	icon="$installcop"'\wsl.ico'
 | |
|     	root="$basepath/rootfs"
 | |
|     fi
 | |
| 
 | |
|     # invocation parameters for mintty
 | |
|     minttyargs='--WSL="'"$distro"'" --configdir="'"$configdir"'"'
 | |
|     # MINTARGS deprecated; used for mkshortcut.exe rather than mkshortcut.vbs
 | |
|     MINTARGS='--WSL="'"$distro"'" --configdir="'"$CONFDIR"'"'
 | |
|     # invocation commands (deprecated for mintty, used for start menu scripts)
 | |
|     #bridgeargs='--distro-guid "'"$guid"'" -t'
 | |
| 
 | |
|     ok=true;;
 | |
|   DefaultDistribution|"")	# WSL default installation
 | |
|     distro=
 | |
|     name=WSL
 | |
|     icon="$installcop"'\wsl.ico'
 | |
|     minttyargs='--WSL= --configdir="'"$configdir"'"'
 | |
|     MINTARGS='--WSL= --configdir="'"$CONFDIR"'"'
 | |
|     #bridgeargs='-t'
 | |
| 
 | |
|     ok=true;;
 | |
|   esac
 | |
|   bridgeargs=" -"	# now used to request login mode
 | |
| 
 | |
|   echoc "distro '$distro'"
 | |
|   echoc "- name '$name'"
 | |
|   echoc "- guid $guid"
 | |
|   echoc "- (launcher $launcher)"
 | |
|   echoc "- icon $icon"
 | |
|   echoc "- root $root"
 | |
|   wdir=%USERPROFILE%
 | |
| 
 | |
|   case "$name" in
 | |
|   docker*)	echo skipping docker system
 | |
|   		return;;
 | |
|   esac
 | |
|   case "$root" in
 | |
|   *\\Docker*)	echo skipping docker system
 | |
|   		return;;
 | |
|   esac
 | |
| 
 | |
|   if $ok && ! $remove && [ -n "$distro" ]
 | |
|   then	# fix #163: backend missing +x with certain mount options
 | |
| 	echo Setting +x wslbridge2 backends for distro "'$distro'"
 | |
| 	(cd "$INSTDIR"; cd bin; PATH="${WINDIR}/Sysnative:${PATH}" wsl.exe -d "$distro" chmod +x wslbridge2-backend)
 | |
| #	(cd "$LOCALAPPDATA/wsltty/bin"; wsl.exe -d "$distro" chmod +x wslbridge2-backend)
 | |
| #	(cd ... ; "$SYSTEMROOT/System32/bash.exe" "$guid" -c chmod +x wslbridge2-backend)
 | |
|   fi
 | |
| 
 | |
|   if $ok && $config
 | |
|   then
 | |
|     export wdir name target minttyargs bridgeargs icon
 | |
| 
 | |
|     if $contextmenu
 | |
|     then
 | |
|       # context menu entries
 | |
|       direckey='HKEY_CURRENT_USER\Software\Classes\Directory'
 | |
|       keyname="${name}_Terminal"
 | |
|       if $remove
 | |
|       then
 | |
|         # obsolete; handled above
 | |
|         reg delete "$direckey\\shell\\$keyname" /f
 | |
|         reg delete "$direckey\\Background\\shell\\$keyname" /f
 | |
|       else
 | |
|         direckey='/HKEY_CURRENT_USER/Software/Classes/Directory'
 | |
|         echoc Registry setting "$direckey/[Background/]shell/$keyname"
 | |
|         target="$installcop"'\bin\mintty.exe'
 | |
| 
 | |
|         regtool add "$direckey/shell"
 | |
|         regtool add "$direckey/shell/$keyname"
 | |
|         regtool set "$direckey/shell/$keyname/" -s "$name Terminal"
 | |
|         regtool set "$direckey/shell/$keyname/Icon" -s "$icon"
 | |
|         regtool add "$direckey/shell/$keyname/command"
 | |
|         regtool set "$direckey/shell/$keyname/command/" -s "\"$target\" -i \"$icon\" --dir \"%1\" $MINTARGS $bridgeargs"
 | |
| 
 | |
|         regtool add "$direckey/Background/shell"
 | |
|         regtool add "$direckey/Background/shell/$keyname"
 | |
|         regtool set "$direckey/Background/shell/$keyname/" -s "$name Terminal"
 | |
|         regtool set "$direckey/Background/shell/$keyname/Icon" -s "$icon"
 | |
|         regtool add "$direckey/Background/shell/$keyname/command"
 | |
|         regtool set "$direckey/Background/shell/$keyname/command/" -s "\"$target\" -i \"$icon\" $MINTARGS $bridgeargs"
 | |
|       fi
 | |
|     else
 | |
|       # invocation shortcuts and scripts
 | |
|       if $remove
 | |
|       then
 | |
|         delete "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\$name Terminal.lnk"
 | |
|         delete "$LOCALAPPDATA\\Microsoft\\WindowsApps\\$name.bat"
 | |
|         delete "$LOCALAPPDATA\\Microsoft\\WindowsApps\\$name~.bat"
 | |
| 
 | |
|         if [ "$name" = "WSL" ]
 | |
|         then
 | |
|               # determine actual Desktop folder
 | |
|               desktopkey='\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Desktop'
 | |
|               desktop=`regtool get "$desktopkey"`
 | |
|               case "$desktop" in
 | |
|               %USERPROFILE%*)	desktop="$USERPROFILE${desktop#%USERPROFILE%}";;
 | |
|               esac
 | |
|               delete "$desktop\\$name Terminal.lnk"
 | |
|         fi
 | |
|       else
 | |
|         # desktop shortcut in %USERPROFILE% -> Start Menu - WSLtty
 | |
|         cscript /nologo mkshortcut.vbs "/name:$name Terminal %"
 | |
|         #mkshortcut.exe -n "$name Terminal %" -i "$icon" "$TARGETPATH" -a "$MINTARGS" -d "" -w %USERPROFILE%
 | |
|         copy "$name Terminal %.lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\WSLtty"
 | |
| 
 | |
|         # launch script in . -> WSLtty home, WindowsApps launch folder
 | |
|         #cmd /C mkbat.bat "$name"
 | |
|         mkbat "$name"
 | |
|         copy "$name.bat" "$LOCALAPPDATA\\Microsoft\\WindowsApps"
 | |
| 
 | |
|         # store backup copies in installation dir
 | |
|         if [ "$PWD" != "$INSTDIR" ]
 | |
|         then
 | |
|               copy "$name Terminal %.lnk" "$installcop"
 | |
|               copy "$name.bat" "$installcop"
 | |
|         fi
 | |
| 
 | |
|         # prepare versions to target WSL home directory
 | |
|         #bridgeargs="-C~ $bridgeargs"
 | |
|         minttyargs="$minttyargs -~"
 | |
|         MINTARGS="$MINTARGS -~"
 | |
| 
 | |
|         # desktop shortcut in ~ -> Start Menu
 | |
|         cscript /nologo mkshortcut.vbs "/name:$name Terminal"
 | |
|         #mkshortcut.exe -n "$name Terminal" -i "$icon" "$TARGETPATH" -a "$MINTARGS" -d "" -w %USERPROFILE%
 | |
|         copy "$name Terminal.lnk" "$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs"
 | |
| 
 | |
|         # default desktop shortcut in ~ -> Desktop
 | |
|         if [ "$name" = "WSL" ]
 | |
|         then
 | |
|               #copy "$name Terminal.lnk" "$USERPROFILE\\Desktop"
 | |
|               #copy "$name Terminal.lnk" "$APPDATA\\..\\Desktop\\"
 | |
|               # the above does not work reliably (see #166)
 | |
|               # determine actual Desktop folder
 | |
|               desktopkey='\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Desktop'
 | |
|               desktop=`regtool get "$desktopkey"`
 | |
|               case "$desktop" in
 | |
|               %USERPROFILE%*)	desktop="$USERPROFILE${desktop#%USERPROFILE%}";;
 | |
|               esac
 | |
|               copy "$name Terminal.lnk" "$desktop\\"
 | |
|         fi
 | |
| 
 | |
|         # launch script in ~ -> WSLtty home, WindowsApps launch folder
 | |
|         #cmd /C mkbat.bat "$name~"
 | |
|         mkbat "$name~"
 | |
|         copy "$name~.bat" "$LOCALAPPDATA\\Microsoft\\WindowsApps"
 | |
| 
 | |
|         # store backup copies in installation dir
 | |
|         if [ "$PWD" != "$INSTDIR" ]
 | |
|         then
 | |
|               copy "$name Terminal.lnk" "$installcop"
 | |
|               copy "$name~.bat" "$installcop"
 | |
|         fi
 | |
|       fi
 | |
| 
 | |
|     fi
 | |
|   fi
 | |
| }
 | |
| 
 | |
| # ensure proper parameter passing to cmd /C
 | |
| chcp.com 65001 # just in case; seems to work without as well
 | |
| 
 | |
| # configure for all distros, plus default distro
 | |
| for guid in `
 | |
|   if $alldistros
 | |
|   then  regtool list "$lxss" 2>/dev/null
 | |
|   else  echo DefaultDistribution
 | |
|   fi || echo "No WSL packages registered" >&2
 | |
| `
 | |
| do	config $guid
 | |
| done
 | |
| 
 |