This is the mail archive of the
mailing list for the Cygwin project.
Re: Strange cygpath behavior.
On 6/27/2011 9:38 AM, Andrey Repin wrote:
>> As you are apparently using the cmd "shell", the correct way to quote
>> arguments in order to preserve spaces etc, is to use double quotes
>> and escape all backslashes with an extra backslash.
> Ok, please explain, how could I escape backslashes in, say, Explorer?
> It could only quote the string.
> I can't even write my own conversion utility :/
> No amount of external conversion would help using diff or patch freely.
Well, here's the thing: on win32, GUI apps (those compiled for the GUI
subsystem) have a different "entry point" than command line ones (those
compiled for the CUI subsystem.
The GUI ones actually use 'WinMain' as an entry point, while the CUI
ones follow the tradition 'int main(int argc, char * argv)' entry
point (actually, thanks to a quirk of the C, it is
int main(int argc, char * argv, char * envp)
but usually the third argument is null).
Anyway, since the signature of WinMain is
int CALLBACK WinMain(
__in HINSTANCE hInstance,
__in HINSTANCE hPrevInstance,
__in LPSTR lpCmdLine,
__in int nCmdShow
the "command line arguments" are passed in as one giant command line,
and parsing it is up the program itself.
Now, *cygwin* programs are usually CUI, but their actual entry point is
mainCRTStartup, regardless of whether they are compiled for the CUI or
GUI subsystem. This function is defined in cygwin1.dll; it does a lot of
stuff, but eventually converts the "big cmd line string" to an argv
array, and calls the user's main() function. This process of converting
"the big cmd line string" is done according to *unix* quoting rules.
There's also a 'stub' main() that does the opposite: if your app defines
a WinMain but no main(), then the stub main gets the "big cmd line
string" via GetCommandLine (e.g. it ignores whatever argv was passed
in) and invokes your WinMain using that big string.
for more info.
So, what's the point?
I think ONE way of solving your problem is to write a wrapper program,
that will *ignore* argv. It should grab the full cmd line using
GetCommandLine(), properly quote it using *win32* quoting rules -- and
then invoke the cygwin program you want to run (*) using main(argc,
argv). Then, cygwin's parsing routines will Do The Right Thing for you.
Here's some code to get you started:
(*) In order to bypass the cygwin parsing rules, this wrapper program
should be a native (that is, non cygwin) application.
Now, why is this so hard?
Well, you've got to realize, what you are trying to do is WAY outside
the normal usage pattern for cygwin tools. In general, we try to make
sure that cygwin tools work "in the unix way" -- and often, that means
they need to be invoked via a unix style shell. Sometimes, invoking
directly from the Win32 GUI point-n-click arena just doesn't work as
expected -- as you have discovered.
That's why so few cygwin apps install GUI-style shortcuts into the Start
Menu. If you look, most of the one that do fall into three categories:
(1) shells - like Cygwin.bat or bash (2) terminals, like rxvt or mintty
(3) X apps that take no cmd line arguments.
Problem reports: http://cygwin.com/problems.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple