This patch is untested, my apologies for that. I don't have a working Visual C++ environment in which to compile PHP at the moment. I have, however, tested the concepts involved. I can also provide test cases and expected output if that would help.
The problem is PHP's incorrect invocation of cmd.exe, which causes no end of trouble to those developing PHP applications on Windows systems. You can find many workarounds for it in the manual comments, but a permanent, robust fix is actually quite simple, at least for NT-based versions of Windows. Here is an extract of the output of "help cmd" on Windows XP: CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF] [[/S] [/C | /K] string] /C Carries out the command specified by string and then terminates /K Carries out the command specified by string but remains [...] If /C or /K is specified, then the remainder of the command line after the switch is processed as a command line, where the following logic is used to process quote (") characters: 1. If all of the following conditions are met, then quote characters on the command line are preserved: - no /S switch - exactly two quote characters - no special characters between the two quote characters, where special is one of: &<>()@^| - there are one or more whitespace characters between the the two quote characters - the string between the two quote characters is the name of an executable file. 2. Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preserving any text after the last quote character. [end quote] This provides a simple, robust means to execute a command via cmd.exe: cmd.exe /s /c "...command goes here..." Otherwise, the programmer risks being plunged into a world of heuristic pain that only a Microsoft developer could love. Some instructive examples: C:\>cmd /c "C:\Program Files\ImageMagick-6.2.6-Q16\convert.exe" Version: ImageMagick 6.2.6 01/27/06 Q16 http://www.imagemagick.org Copyright: Copyright (C) 1999-2006 ImageMagick Studio LLC Usage: convert.exe [options ...] file [ [options ...] file ...] [options ...] file [...] C:\>cmd /c "C:\Program Files\ImageMagick-6.2.6-Q16\convert.exe" -version Version: ImageMagick 6.2.6 01/27/06 Q16 http://www.imagemagick.org Copyright: Copyright (C) 1999-2006 ImageMagick Studio LLC C:\>cmd /c "C:\Program Files\ImageMagick-6.2.6-Q16\convert.exe" "some file" 'C:\Program' is not recognized as an internal or external command, operable program or batch file. C:\>cd "C:\Program Files\ImageMagick-6.2.6-Q16" C:\Program Files\ImageMagick-6.2.6-Q16>cmd /c "convert source dest" convert: unable to open image `source': No such file or directory. convert: missing an image filename `dest'. C:\Program Files\ImageMagick-6.2.6-Q16>echo @echo G'day > "convert source dest.bat" C:\Program Files\ImageMagick-6.2.6-Q16>cmd /c "convert source dest" G'day Positively scary. /s restores sanity to the situation: C:\Program Files\ImageMagick-6.2.6-Q16>cmd /s /c "convert source dest" convert: unable to open image `source': No such file or directory. convert: missing an image filename `dest'. Users of COMMAND.COM are not so blessed. There's no handling for double quotes at all, so if you want to execute a program with spaces in the name, you just have to use the 8.3 alias. In my patch, this is the responsibility of the application. C:\>command.com /s /c "echo hello" Invalid switch Bad command or file name The problem as it manifests itself in PHP was reported as Bug #34671, and closed as bogus by a trigger-happy admin. You can't work around it properly in application-level code, because you can't specify /s. -- Tim Starling
Index: TSRM/tsrm_win32.c =================================================================== RCS file: /repository/TSRM/tsrm_win32.c,v retrieving revision 1.28 diff -u -r1.28 tsrm_win32.c --- TSRM/tsrm_win32.c 1 Jan 2006 13:09:48 -0000 1.28 +++ TSRM/tsrm_win32.c 6 Feb 2006 01:53:29 -0000 @@ -209,8 +209,15 @@ startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); } - cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")); - sprintf(cmd, "%s /c %s", TWG(comspec), command); + if (GetVersion()<0x80000000) { + /* NT calling convention: quotes around everything, /s to disable heuristics */ + cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /s /c \"\"")); + sprintf(cmd, "%s /s /c \"%s\"", TWG(comspec), command); + } else { + /* 95/98/Me calling convention. Long names need to be converted to short names by the application. */ + cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")); + sprintf(cmd, "%s /c %s", TWG(comspec), command); + } if (!CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, NORMAL_PRIORITY_CLASS, env, cwd, &startup, &process)) { return NULL; }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php