Issue: Slash-prefixed arguments needs to be doubly escaped in msys64/Git Bash
musjj opened this issue · 4 comments
Issue Description
Built-in Windows tools like tasklist
, taskkill
, etc. uses slash-prefixed arguments like /A
, /B
, etc.
This is in conflict with Git Bash's parsing magic which converts them to Windows paths, so we need to escape it:
$ taskkill /?
ERROR: Invalid argument/option - 'C:/msys64/?'.
Type "TASKKILL /?" for usage.
$ taskkill //?
TASKKILL [/S system [/U username [/P [password]]]]
{ [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]
Description:
This tool is used to terminate tasks by process id (PID) or image name.
...
But when using sudo
, for some reason you need to escape it twice:
$ sudo tasklist /?
ERROR: Invalid argument/option - 'C:/msys64/?'.
Type "TASKLIST /?" for usage.
$ sudo tasklist //?
ERROR: Invalid argument/option - 'C:/msys64/?'.
Type "TASKLIST /?" for usage.
$ sudo tasklist ///?
TASKLIST [/S system [/U username [/P [password]]]]
[/M [module] | /SVC | /V] [/FI filter] [/FO format] [/NH]
Description:
This tool displays a list of currently running processes on
either a local or remote machine.
...
What is causing this to happen?
Steps to Reproduce
- Open a msys64/Git Bash shell
- Run
tasklist /?
andtasklist //?
and compare their output - Run
sudo tasklist /?
,sudo tasklist //?
, andsudo tasklist ///?
and compare their output
Context:
- Windows version: Microsoft Windows [Version 10.0.19043.2130]
- gsudo version: gsudo v1.3.0 (Branch.master.Sha.24fb735f547e1e5dd7aa22fdd77777fa8c923a1c)
It behaves differently on my machine. Please upgrade to latest gsudo and latest git.
If you have winget, do winget upgrade git.git
and winget upgrade gerardog.gsudo
The way I thought of using it from bash is to use it as gsudo
, to not confuse it with the original sudo... There is actually a gsudo
(no extension) bash wrapper in the gsudo installation folder, which sets
MSYS_NO_PATHCONV=1
.... hence disabling the path conversion...
You may want go to your gsudo folder and duplicate gsudo
into sudo
to feel how that feature would feel.
I'm busy right now to give you a perfect answer... The problem with Msys2 path mangling is that I couldn't find a way to ensure the path is mangled just once.
We have 2/3 tools at hand.
- The
gsudo
bash wrapper that definitely also exist assudo
- A possible
sudo/gsudo
profile function such assudo() { WSLENV=WSL_DISTRO_NAME:USER:$WSLENV MSYS_NO_PATHCONV=1 gsudo.exe "$@"; }
gsudo.exe
itself doing command line replacements.
There should be a combination of those 3 that should make gsudo prefix transparent to path mangling, but I couldn't find one. It's either making the conversion twice or none.
Thanks for the hint with the environment variable.
I'm using MSYS2, so MSYS_NO_PATHCONV=1
doesn't work for me (the variable only applies to the Git For Windows fork of MSYS), so I need to use MSYS2_ARG_CONV_EXCL="*"
instead.
It seems that setting the variable works immediately for the running command, so escaping slashes is not needed at all:
MSYS2_ARG_CONV_EXCL="*" sudo tasklist /?
Now all I need to do is to turn it into a function in my .bashrc
for convenience.
EDIT: Actually, thinking about it, this behaviour is undesirable. I would want the slashes to be parsed once, in case I actually want to pass MSYS paths to the program.
So I changed it to:
sudo() { sudo.exe MSYS2_ARG_CONV_EXCL="'*'" "$@"; }
And it seem to work the way I wanted it to, but for some reason it made the startup time really slow compared to:
sudo() { MSYS2_ARG_CONV_EXCL="*" sudo.exe "$@"; }
Do you have any idea what's causing the slowdown?
EDIT 2: It seems that there is an issue with Bash trying to expand the ?
.
For some reason the issue doesn't happen with a single slash (e.g. echo /?
), but with a double slash the command slows down or even downright freezes: (e.g. echo //?
)
Escaping it like this: //\?
seems to fix the issue.