forked from Mirrors/wine-wine
cmd: Ignore quotes when parsing command line parameters.
This fixes a hang in the WinTV 8.5 installer. Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
16c938cb66
commit
2e45fdb194
|
@ -183,12 +183,19 @@ echo ------- Testing CMD /C qualifier treatment ------------
|
||||||
rem no need for space after /c
|
rem no need for space after /c
|
||||||
cmd /csay one
|
cmd /csay one
|
||||||
cmd /c"say one"
|
cmd /c"say one"
|
||||||
rem ignore quote before qualifier
|
cmd /c"say one
|
||||||
rem FIXME the next command in wine starts a sub-CMD
|
cmd /c=say one
|
||||||
echo THIS FAILS: cmd "/c"say one
|
cmd /c,say one
|
||||||
rem ignore anything before /c
|
cmd /c;say one
|
||||||
rem FIXME the next command in wine starts a sub-CMD
|
rem non-options are ignored before /c; quotes are not treated specially
|
||||||
echo THIS FAILS: cmd ignoreme/c say one
|
cmd "/c"say one
|
||||||
|
cmd ignoreme/c say one
|
||||||
|
cmd abc "def ghi/c say one"
|
||||||
|
cmd -\@$*'"/c say one
|
||||||
|
echo echo bar > foo.bat
|
||||||
|
cmd /qq/c foo
|
||||||
|
cmd /q "xyz /c foo"
|
||||||
|
del foo.bat
|
||||||
|
|
||||||
echo --------- Testing special characters --------------
|
echo --------- Testing special characters --------------
|
||||||
echo @echo amp > "say&.bat"
|
echo @echo amp > "say&.bat"
|
||||||
|
|
|
@ -90,8 +90,16 @@ Passed
|
||||||
------- Testing CMD /C qualifier treatment ------------
|
------- Testing CMD /C qualifier treatment ------------
|
||||||
0@space@
|
0@space@
|
||||||
1@space@
|
1@space@
|
||||||
THIS FAILS: cmd "/c"say one
|
0@space@
|
||||||
THIS FAILS: cmd ignoreme/c say one
|
0@space@
|
||||||
|
0@space@
|
||||||
|
0@space@
|
||||||
|
0@space@
|
||||||
|
0@space@
|
||||||
|
0@space@
|
||||||
|
0@space@
|
||||||
|
bar@space@
|
||||||
|
bar@space@
|
||||||
--------- Testing special characters --------------
|
--------- Testing special characters --------------
|
||||||
0@space@
|
0@space@
|
||||||
0@space@
|
0@space@
|
||||||
|
|
|
@ -2421,10 +2421,8 @@ void WCMD_free_commands(CMD_LIST *cmds) {
|
||||||
|
|
||||||
int __cdecl wmain (int argc, WCHAR *argvW[])
|
int __cdecl wmain (int argc, WCHAR *argvW[])
|
||||||
{
|
{
|
||||||
int args;
|
|
||||||
WCHAR *cmdLine = NULL;
|
WCHAR *cmdLine = NULL;
|
||||||
WCHAR *cmd = NULL;
|
WCHAR *cmd = NULL;
|
||||||
WCHAR *argPos = NULL;
|
|
||||||
WCHAR string[1024];
|
WCHAR string[1024];
|
||||||
WCHAR envvar[4];
|
WCHAR envvar[4];
|
||||||
BOOL promptNewLine = TRUE;
|
BOOL promptNewLine = TRUE;
|
||||||
|
@ -2440,6 +2438,7 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
|
||||||
RTL_OSVERSIONINFOEXW osv;
|
RTL_OSVERSIONINFOEXW osv;
|
||||||
char osver[50];
|
char osver[50];
|
||||||
STARTUPINFOW startupInfo;
|
STARTUPINFOW startupInfo;
|
||||||
|
const WCHAR *arg;
|
||||||
|
|
||||||
if (!GetEnvironmentVariableW(comspecW, comspec, ARRAY_SIZE(comspec)))
|
if (!GetEnvironmentVariableW(comspecW, comspec, ARRAY_SIZE(comspec)))
|
||||||
{
|
{
|
||||||
|
@ -2467,57 +2466,55 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
|
||||||
*/
|
*/
|
||||||
cmdLine = GetCommandLineW();
|
cmdLine = GetCommandLineW();
|
||||||
WINE_TRACE("Full commandline '%s'\n", wine_dbgstr_w(cmdLine));
|
WINE_TRACE("Full commandline '%s'\n", wine_dbgstr_w(cmdLine));
|
||||||
args = 0;
|
|
||||||
|
while (*cmdLine && *cmdLine != '/') ++cmdLine;
|
||||||
|
|
||||||
opt_c = opt_k = opt_q = opt_s = FALSE;
|
opt_c = opt_k = opt_q = opt_s = FALSE;
|
||||||
WCMD_parameter(cmdLine, args, &argPos, TRUE, TRUE);
|
|
||||||
while (argPos && argPos[0] != 0x00)
|
for (arg = cmdLine; *arg; ++arg)
|
||||||
{
|
{
|
||||||
WCHAR c;
|
if (arg[0] != '/')
|
||||||
WINE_TRACE("Command line parm: '%s'\n", wine_dbgstr_w(argPos));
|
continue;
|
||||||
if (argPos[0]!='/' || argPos[1]=='\0') {
|
|
||||||
args++;
|
|
||||||
WCMD_parameter(cmdLine, args, &argPos, TRUE, TRUE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
c=argPos[1];
|
switch (towlower(arg[1]))
|
||||||
if (towlower(c)=='c') {
|
{
|
||||||
opt_c = TRUE;
|
case 'a':
|
||||||
} else if (towlower(c)=='q') {
|
unicodeOutput = FALSE;
|
||||||
opt_q = TRUE;
|
break;
|
||||||
} else if (towlower(c)=='k') {
|
case 'c':
|
||||||
opt_k = TRUE;
|
opt_c = TRUE;
|
||||||
} else if (towlower(c)=='s') {
|
break;
|
||||||
opt_s = TRUE;
|
case 'k':
|
||||||
} else if (towlower(c)=='a') {
|
opt_k = TRUE;
|
||||||
unicodeOutput = FALSE;
|
break;
|
||||||
} else if (towlower(c)=='u') {
|
case 'q':
|
||||||
unicodeOutput = TRUE;
|
opt_q = TRUE;
|
||||||
} else if (towlower(c)=='v' && argPos[2]==':') {
|
break;
|
||||||
delayedsubst = wcsnicmp(&argPos[3], offW, 3);
|
case 's':
|
||||||
if (delayedsubst) WINE_TRACE("Delayed substitution is on\n");
|
opt_s = TRUE;
|
||||||
} else if (towlower(c)=='t' && argPos[2]==':') {
|
break;
|
||||||
opt_t=wcstoul(&argPos[3], NULL, 16);
|
case 't':
|
||||||
} else if (towlower(c)=='x' || towlower(c)=='y') {
|
if (arg[2] == ':')
|
||||||
/* Ignored for compatibility with Windows */
|
opt_t = wcstoul(&arg[3], NULL, 16);
|
||||||
}
|
break;
|
||||||
|
case 'u':
|
||||||
|
unicodeOutput = TRUE;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
if (arg[2] == ':')
|
||||||
|
delayedsubst = wcsnicmp(&arg[3], L"OFF", 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (argPos[2]==0 || argPos[2]==' ' || argPos[2]=='\t' ||
|
if (opt_c || opt_k)
|
||||||
towlower(c)=='v') {
|
{
|
||||||
args++;
|
arg += 2;
|
||||||
WCMD_parameter(cmdLine, args, &argPos, TRUE, TRUE);
|
break;
|
||||||
}
|
}
|
||||||
else /* handle `cmd /cnotepad.exe` and `cmd /x/c ...` */
|
|
||||||
{
|
|
||||||
/* Do not step to next parameter, instead carry on parsing this one */
|
|
||||||
argPos+=2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_c || opt_k) /* break out of parsing immediately after c or k */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (*arg && wcschr(L" \t,=;", *arg)) arg++;
|
||||||
|
|
||||||
if (opt_q) {
|
if (opt_q) {
|
||||||
WCMD_echo(offW);
|
WCMD_echo(offW);
|
||||||
}
|
}
|
||||||
|
@ -2531,12 +2528,8 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
|
||||||
int len;
|
int len;
|
||||||
WCHAR *q1 = NULL,*q2 = NULL,*p;
|
WCHAR *q1 = NULL,*q2 = NULL,*p;
|
||||||
|
|
||||||
/* Handle very edge case error scenario, "cmd.exe /c" ie when there are no
|
|
||||||
* parameters after the /C or /K by pretending there was a single space */
|
|
||||||
if (argPos == NULL) argPos = (WCHAR *)spaceW;
|
|
||||||
|
|
||||||
/* Take a copy */
|
/* Take a copy */
|
||||||
cmd = heap_strdupW(argPos);
|
cmd = heap_strdupW(arg);
|
||||||
|
|
||||||
/* opt_s left unflagged if the command starts with and contains exactly
|
/* opt_s left unflagged if the command starts with and contains exactly
|
||||||
* one quoted string (exactly two quote characters). The quoted string
|
* one quoted string (exactly two quote characters). The quoted string
|
||||||
|
@ -2545,7 +2538,7 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
|
||||||
|
|
||||||
if (!opt_s) {
|
if (!opt_s) {
|
||||||
/* 1. Confirm there is at least one quote */
|
/* 1. Confirm there is at least one quote */
|
||||||
q1 = wcschr(argPos, '"');
|
q1 = wcschr(arg, '"');
|
||||||
if (!q1) opt_s=1;
|
if (!q1) opt_s=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue