This is the mail archive of the
mailing list for the Cygwin project.
RE: Formatting command line arguments when starting a Cygwin process from a native process
- From: "Aaron Digulla" <digulla at hepe dot com>
- To: cygwin at cygwin dot com <cygwin at cygwin dot com>
- Date: Tue, 10 May 2016 15:30:00 +0200
- Subject: RE: Formatting command line arguments when starting a Cygwin process from a native process
- Authentication-results: sourceware.org; auth=none
Am Montag, 09. Mai 2016 17:19 CEST, David Allsopp <email@example.com> schrieb:
> Aaron Digulla wrote:
> > Am Samstag, 07. Mai 2016 09:45 CEST, "David Allsopp" <firstname.lastname@example.org>
> > schrieb:
> > > > Then all you need is a rudimentary quoting.
> > >
> > > Yes, but the question still remains what that rudimentary quoting is -
> > i.e.
> > > I can see how to quote spaces which appear in elements of argv, but I
> > > cannot see how to quote double quotes!
> > This should help:
> > https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/e
> > veryone-quotes-command-line-arguments-the-wrong-way/
> This provides documentation for how Microsoft implementations do it, not how Cygwin does it. The Cygwin DLL is responsible for determining how a Cygwin process gets argc and argv from GetCommandLineW.
That's correct but I read your question as "how do I start executables linked against Cygwin from another Windows process"
To do that, you need to convert the argument list/array into the stupid Windows format because that's what the Cygwin process will expect.
> > My line of thought is that Cygwin can't get anything which Windows can't
> > send it. So the first step to solve this mess is to make sure the
> > arguments which you send to CreateProcess() are correct.
> > The next step would be to write a small C utility which dumps it's
> > arguments, so you can properly debug all kinds of characters.
> See later email, but IMHO the conversion is something Cygwin should have precisely documented, not determined by brittle experimentation.
Ah... no. You're mixing two or three things. Let me enumerate:
1. You have to give your OS (Windows or Unix) the information which process you want to start and which arguments to pass. Unix has two ways (string array and single string), Windows has only single string.
2. The OS will put the information into a structure of some kind and pass that to the new process.
3. If you have a shell (CMD.exe, bash, etc), they will take the structure and parse it according to some rules. They will then convert the result again into an OS call.
4. The C runtime of your executable will know where to get the OS structure and how to turn the structure into char ** argv.
Where is Cygwin in all this? It's part of step #3. Cygwin emulates exec() and similar Unix OS functions which an emulated shell like BASH will use. Which means Cygwin code in the DLL is irrelevant if you don't have a Unix shell somewhere in your process chain.
If you just want to execute a Cygwin process (= Windows process which includes the Cygwin.dll), you need to know #1, #2 and #4.
> > PS: I always point people to string list/array type methods to create
> > processes which fix all the problems with spaces and odd characters
> > (quotes, umlauts, etc). It seems that Windows doesn't have such a method
> > to create processes. Which kind of makes sense; Windows is very, very
> > mouse centered.
> I fail to see the connection with mice! What Windows (NT) does have is a legacy where the decision on how to convert a command line to a list/array of arguments is determined per-process (and so not the responsibility of command line shells) vs Unix which puts the burden of converting a single command line to the array on the shell instead. Nominally, the Windows way is more flexible, though I don't think that flexibility is actually useful (especially if you look at the comments in the command line -> argv conversion in Microsoft's C Runtime library!).
Using single strings to run commands causes all kinds or problems. It's a brittle API, which you should avoid. It kind of feels more simple but it's the "too simple" kind which Einstein mentioned ("You should make things as simple as possible. But not more simle.")
Think of it that way: Your executable gets the arguments as a string array. On the parent process side, Unix allows you to create a process with an array of strings. That's a natural API which doesn't need any kind of conversion (maybe you need to copy the strings but that's it).
If you convert from and to a single string all the time, you need a way to quote and escape. So this is more error prone than the plain array solution.
And lastly: If everyone would always use arrays, we wouldn't have this long, tedious discussion.
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
Problem reports: http://cygwin.com/problems.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple