Re: [PATCH] Bug #34671 Incorrect calling convention to cmd.exe
| From: | Wez Furlong | Date: | Mon, 06 Feb 2006 18:43:04 +0000 |
| Subject: | Re: [PATCH] Bug #34671 Incorrect calling convention to cmd.exe | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-21801@lists.php.net to get a copy of this message | ||
Is it possible that switching /S on will break existing scripts?
If so, it's probably better to make the comspec setting a PHP .ini
option that only the admin can change and allow /S to be set there.
--Wez.
On 2/5/06, Tim Starling <t.starling@physics.unimelb.edu.au> wrote:
> 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
>
>