Linda Walsh wrote: > or the nocyg, it will try to edit 3 files. When I am invoking > the redirector, I'm using 1 set of double quotes: > gvim "file with space" > in both versions w/cyg & w/o-cyg. cmd.exe also requires quoting filenames > with > spaces the same as bash.
When you use plain unadorned double quotes, they tell the shell that you're typing the command into how to group arguments, but they do not exist past there. In other words, bash uses the quotes to reconstruct that you want argv[1] to equal 'file with space' but argv[1] itself does not contain any quotes. So if you then turn around and pass that argv[1] on to the MSVCRT exec() which does no quoting, the grouping is lost. > For some reason, the multiple args in the redirector are being merged -- I > I can get the quoting to work in the no-cyg case by using 2 sets of quotes: > gvim '"file with space"' When you quote quotes, that means the shell sees them as integral parts of the command rather than metacharacters that are to be interpreted and discarded. So the invoked program will have them in its argv. You could also use \""file with space"\" if you wanted to expand variables inside the string. > So cygwin pays attention, and my re-passing the args via "execv" > preserves the quoting of filenames, but the no-cyg version appears > to take the argv[1..#] arguments and merge them into 1 argument. > To do the same in the no-cyg version, I'd have to peel each arg > off, put quotes around it, then call execv with everything requoted. Or just link your MinGW version with the MinGW -lexecwrap library. > So you are saying that when I call execv in cygwin, it unpacks > my 'argv', and makes a new 'argv' with quotes around each string? > and that is what gets passed to create process? Does it use > single or double quotes? Not quite. What Cygwin does depends on whether it's exec()ing a Cygwin binary or a non-Cygwin binary. In the case of a Cygwin binary this is all moot because the argv is handed directly to the child through internal communications, bypassing Windows, so there is no need for any quoting at all. When a Cygwin binary exec()s a non-Cygwin binary it first constructs an approproate command line that concatenates argv, inserting quotes around any elements that contain whitespace. Note again that it does not create a new argv because there is no such thing as an argv in Windows: what a child gets is a command line, and if it wants it in the form of argv it has to synthesize it from that. > But the executed program, with or without cygwin, already has the > arguments parsed when main is invoked. > I.e. when either the cygwin or no-cyg program is invoked, they both > have the same view of the arguments in 'argv'. main() is a fiction that is invented by the CRT startup to support the C language. It is by no means the actual entrypoint of the program. One of the functions of the CRT startup code is to retrieve the command line from the operating system and parse it into words to populate argv. That doesn't mean argv was passed to the process, it just means that it will be synthesized for code that expects to have one. This is optional by the way. If you want to write a traditional Win32 app the entrypoint is WinMain: #include <windows.h> #include <stdio.h> int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow) { puts ("Hello world."); return 0; } You can compile this both with Cygwin and MinGW and it will work fine. Note that the parameters passed to the program are nothing like the C argc/argv. lpCmd is a pointer to a null terminated string containing the command line, there is no array of arguments anywhere. > It's execv that's falling down, not doing it's job. My arguments > are already parsed and separated, but the no-cyg version of execv > is mushing them all back together, while cygwin invokes the > next program, apparently with quotes of some sort, around the > contents of each, separate, argv[] string. It would not be the first time that someone found MSVCRT less than adequate. Again, the MinGW project has a convenient set of wrappers for just this reason. > Isn't MSVCRT the startup code? No, it's just the opposite: it is the C library minus the startup code. The startup code is linked in with each binary, whereas MSVCRT.DLL is the common library code. When you use MinGW (= use -mno-cygwin) you are using the MinGW project's startup code but everything else is MSVCRT. Including execv(). > I don't think it is a MS problem exactly -- it appears to be a > broken implementation of execv. When I call execv, the different And whose implementation of execv() do you think that is exactly? It's not Cygwin's. It's not MinGW's. It's certainly not gcc's. It's Microsoft's. Again, this is the whole point of MinGW, to use the existing Microsoft C library of the operating system so that the program can run without any accompanying libraries. > I'd say that the no-cyg version of execv isn't maintaining the separation > of the arguments. It's just mushing them all together and not passing > the correct argument separation to "createprocess". > Am I missing something? No, that's what I've been trying to say the whole time -- MS's exec() doesn't do any quoting. > I've also run into another unexpected behavior difference. > The no-cyg version of _my_ gcc wrapper, is automatically detaching > from the terminal and going into the background (running under bash). > Is there some reason cygwin waits around until my wrapper is finished, > but the no-cyg version (same code) doesn't?....I suppose it is > easier when launching another program with createprocess -- to hmmm... > shouldn't the exec call "end" or terminate the execution of the wrapper? > > Since I'm not forking -- I'm exec'ing, the redirector should > cease to exist (exit), but under cygwin, it does not. That seems more > of a bug in the cygwin implementation, no? Sigh. No. Aaaaaargh! The *whole* *point* of making the wrapper a MinGW app is so that it will exit and the the thing its wrapping will appear to run in the background. This is because the defintion of exec() for a native program is spawn+exit. The waiting parent will see that the child has terminated and continue. exec() for a Cygwin program means replace, not spawn+exit, as per the *nix semantics. A parent that is waiting on a child is waiting for it to terminate, which the POSIX exec() most certainly is not. A child that has exec()d is still that same child, it is the same process, same PID, etc. Please go back and read that lengthy description of the differences between Win32 exec() and POSIX exec() that I typed out several messages back because this is exactly the aspect in which they are different, and Cygwin goes to great pains to make that distinction. If you wanted your wrapper to be a Cygwin wrapper you'd have to fork() and exec() which is where this whole mess started, which is why I suggested using a *MINGW* wrapper because it could simply exec(). That doesn't mean the Cygwin wrapper doesn't have to fork(). In essence a Cygwin wrapper that only calls exec() is a big no-op, the parent will still be waiting on the wrapped program to terminate, even though there has been an extra process thrown in there. Brian -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/