EVALUATION
The fix (see also comments) seems to be to add '"' if the user supplied
arguments has a whitespace character.
anand.palaniswamy@Eng 1997-09-08
I discussed this extensively with Dac and others, and this turns out to be
a rathole. On Win32 an application is free to choose how it will handle
command line arguments (it has three choices:
- do nothing (no Unix like globbing).
- do Unix like globbing with MS VC++'s setargv.obj
- do Unix like globbing on its own).
1. Say we add quotes to exec'ing { "prog1", "a", "x y" } like this:
"prog1 a \"x y\""
this would screw up prog1 if it was not linked with Microsoft's
setargv.obj. Prog1 will now see random quotes, and this is
difficult to debug, unless you write your own Echo that treats
command line arguments just like Prog1.
2. The quoting in (1) also has a problem in that you can't write regular
expression of the form _a *b_ (note: _ is just for clarity). Consider
the above algorithm on ls:
"ls \"a *b\""
Now this will fail to find files such as 'a 1b', 'a 2b'. So a more
correct thing would be to quote around the spaces.
"ls a\" \"*b"
Tied in with this algorithm is that if you are already in quotes,
don't quote whitespaces -- that way you don't break people that are
already working around this bug.
3. Algorithm (2) becomes a nightmare to implement because you have to
take care of mismatched quotes, and nested quotes.
4. Dac suggested a simpler algorithm that we first see if there are
any quotes at all in the argument. If there are not any quotes,
but there are spaces, then we quote the spaces. This sounds like
the most reasonable thing to do. However it still does break
programs that don't do any globbing, but understand single
quotes (rare), and programs that don't grok any kind of quotes
at all.
Bottom line, anything we do has the risk of breaking code that
is already out there. And Runtime.exec() is used pretty heavily -- the
JCK harness relies on it, Marimba relies on it, and we really don't know
how people are using this method.
So if anything can be done, it has to be done in a major release such
as 1.2, and not in a minor release like 1.1.5.
Even if we want to "fix" this in 1.2, we will have to document it.
Which means the specification of Runtime.exec() will have to talk
about its behavior on Win32 -- something we want to avoid at all
costs.
In sum, I am somewhat inclined to mark this will-not-fix -- to argue
this another way -- if you are doing a Runtime.exec(), then you are
calling a program that is _not_ under Java's control, and at that point
it is _your_ responsibility to figure out how to pass arguments to that
application. I will get some more opinions on this before I change the
state though.
In the interim a workaround of figuring out which platform you are on
(System.getProperty("os.name")) and then putting quotes appropriately
yourself seems to be the right thing to do.
anand.palaniswamy@Eng 1997-09-10
After doing some tests on win32, I found some of the above arguments
are correct.
1. On unix, if we want to execute, say, "cat a*b", it is the responsible of
shell to parse this single command line into argc and argv;
On win32, the same "cat a*b" to be passed through to child process. And
you can get it back using API GetCommandLine(); The C runtime will capture
the single string and parse to argc and argv;
This is the fundimental difference behind the problem;
2. The main() function application must use unix style globbing in c runtime;
The WinMain() does not use any globbing, it gets the straight comamndline;
3. The #1 worry(see above) does not exist anyway. All crt on win32 must be able
parse command line to argc and argv for all normal cases. Otherwise we will
not even get main() to run. For example, if the above if we pass command line
"prog a \"x y\"", any correct CRT MUST let main() function get "prog", "a"
and "x y". Otherwise it is CRT bug, not ours.
4. The #2 worry(see above) will not appear on winnt 4.0 with microsoft crt.
I run the test and pass "prog \"a *b\"", and the child process do get the
"prog" and "a *b". I believe the CRT will pass through meta character like
'?' and '*', because it has no way to understand it.
5. The bottom line is Runtime.exec() is to run a native application. Such an
application may even does not have a main function(). It is a worthless
effort to achieve the unix style and syntax.
My suggested fix is we simply quote all arguements with space and tab. If people
really want to pass meta character, like " ' \ / etc we need to use platform
specific routine. On win32, we should recomment user to use Runtime.exec(
String s), that is native windows application should expects. Documentation
the difference will really help the user, though I know it is not good to
add platform specific documentation.)
###@###.### 1998-02-03
|