The following series: - extends current test harness by adding interactive tests capability - fixes a couple of bugs (with tests in interactive mode)
A+
---
Eric Pouech (7): programs/cmd/tests: don't output more data than available programs/cmd/tests: added ability to run tests in interactive mode programs/cmd/tests: some interactive test about input echo programs/cmd/tests: added support for multi-line input programs/cmd: handle white space only lines within ( ) block programs/cmd: expand commandline before parsing it (interactive mode) programs/cmd: detect badly quoted operand in 'if' statement
programs/cmd/builtins.c | 10 ++ programs/cmd/tests/batch.c | 111 ++++++++++++++---- programs/cmd/tests/interactive_builtins.cmd | 42 +++++++ .../cmd/tests/interactive_builtins.cmd.exp | 67 +++++++++++ programs/cmd/tests/rsrc.rc | 10 ++ programs/cmd/wcmdmain.c | 34 ++++-- 6 files changed, 244 insertions(+), 30 deletions(-) create mode 100644 programs/cmd/tests/interactive_builtins.cmd create mode 100644 programs/cmd/tests/interactive_builtins.cmd.exp
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/tests/batch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/tests/batch.c b/programs/cmd/tests/batch.c index 162e9cfa151..0e8fbf89d6d 100644 --- a/programs/cmd/tests/batch.c +++ b/programs/cmd/tests/batch.c @@ -344,8 +344,10 @@ static void test_output(const char *out_data, DWORD out_size, const char *exp_da } }
- ok(exp_ptr >= exp_data+exp_size, "unexpected end of output in line %d, missing %s\n", line, exp_ptr); - ok(out_ptr >= out_data+out_size, "too long output, got additional %s\n", out_ptr); + ok(exp_ptr >= exp_data+exp_size, "unexpected end of output in line %d, missing %.*s\n", + line, exp_data + exp_size - exp_ptr, exp_ptr); + ok(out_ptr >= out_data+out_size, "too long output, got additional %.*s\n", + out_data + out_size - out_ptr, out_ptr); }
static void run_test(const char *cmd_data, DWORD cmd_size, const char *exp_data, DWORD exp_size)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/tests/batch.c | 58 +++++++++++++++-------- programs/cmd/tests/interactive_builtins.cmd | 1 programs/cmd/tests/interactive_builtins.cmd.exp | 1 programs/cmd/tests/rsrc.rc | 10 ++++ programs/cmd/wcmdmain.c | 2 - 5 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 programs/cmd/tests/interactive_builtins.cmd create mode 100644 programs/cmd/tests/interactive_builtins.cmd.exp
diff --git a/programs/cmd/tests/batch.c b/programs/cmd/tests/batch.c index 0e8fbf89d6d..0d6832df30f 100644 --- a/programs/cmd/tests/batch.c +++ b/programs/cmd/tests/batch.c @@ -74,32 +74,39 @@ static const char* convert_input_data(const char *data, DWORD size, DWORD *new_s return new_data; }
-static BOOL run_cmd(const char *cmd_data, DWORD cmd_size) +static BOOL run_cmd(const char *cmd_data, DWORD cmd_size, BOOL interactive) { SECURITY_ATTRIBUTES sa = {sizeof(sa), 0, TRUE}; char command[] = "test.cmd"; + char interactive_command[] = "cmd /k"; /* so that we don't get version info before interactive mode */ STARTUPINFOA si = {sizeof(si)}; PROCESS_INFORMATION pi; - HANDLE file,fileerr; + HANDLE filein,fileout,fileerr; DWORD size; BOOL bres;
- file = CreateFileA("test.cmd", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); - if(file == INVALID_HANDLE_VALUE) + filein = CreateFileA("test.cmd", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, + interactive ? &sa : NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + ok(filein != INVALID_HANDLE_VALUE, "CreateFile failed\n"); + if(filein == INVALID_HANDLE_VALUE) return FALSE;
- bres = WriteFile(file, cmd_data, cmd_size, &size, NULL); - CloseHandle(file); + bres = WriteFile(filein, cmd_data, cmd_size, &size, NULL); ok(bres, "Could not write to file: %u\n", GetLastError()); if(!bres) return FALSE; + if (interactive) + { + SetEndOfFile(filein); + SetFilePointer(filein, 0, NULL, FILE_BEGIN); + } + else + CloseHandle(filein);
- file = CreateFileA("test.out", GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, &sa, CREATE_ALWAYS, + fileout = CreateFileA("test.out", GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); - if(file == INVALID_HANDLE_VALUE) + ok(fileout != INVALID_HANDLE_VALUE, "CreateFile failed\n"); + if(fileout == INVALID_HANDLE_VALUE) return FALSE;
fileerr = CreateFileA("test.err", GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, &sa, CREATE_ALWAYS, @@ -109,9 +116,10 @@ static BOOL run_cmd(const char *cmd_data, DWORD cmd_size) return FALSE;
si.dwFlags = STARTF_USESTDHANDLES; - si.hStdOutput = file; + si.hStdInput = interactive ? filein : INVALID_HANDLE_VALUE; + si.hStdOutput = fileout; si.hStdError = fileerr; - bres = CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + bres = CreateProcessA(NULL, interactive ? interactive_command : command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); ok(bres, "CreateProcess failed: %u\n", GetLastError()); if(!bres) { DeleteFileA("test.out"); @@ -121,7 +129,9 @@ static BOOL run_cmd(const char *cmd_data, DWORD cmd_size) WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); - CloseHandle(file); + if (interactive) + CloseHandle(filein); + CloseHandle(fileout); CloseHandle(fileerr); DeleteFileA("test.cmd"); return TRUE; @@ -350,7 +360,7 @@ static void test_output(const char *out_data, DWORD out_size, const char *exp_da out_data + out_size - out_ptr, out_ptr); }
-static void run_test(const char *cmd_data, DWORD cmd_size, const char *exp_data, DWORD exp_size) +static void run_test(const char *cmd_data, DWORD cmd_size, const char *exp_data, DWORD exp_size, BOOL interactive) { const char *out_data, *actual_cmd_data; DWORD out_size, actual_cmd_size; @@ -359,7 +369,7 @@ static void run_test(const char *cmd_data, DWORD cmd_size, const char *exp_data, if(!actual_cmd_size || !actual_cmd_data) goto cleanup;
- if(!run_cmd(actual_cmd_data, actual_cmd_size)) + if(!run_cmd(actual_cmd_data, actual_cmd_size, interactive)) goto cleanup;
out_size = map_file("test.out", &out_data); @@ -394,7 +404,7 @@ static void run_from_file(const char *file_name) return; }
- run_test(test_data, test_size, out_data, out_size); + run_test(test_data, test_size, out_data, out_size, FALSE);
UnmapViewOfFile(test_data); UnmapViewOfFile(out_data); @@ -433,11 +443,11 @@ static BOOL WINAPI test_enum_proc(HMODULE module, LPCSTR type, LPSTR name, LONG_ return TRUE;
sprintf(res_name, "%s.exp", name); - out_size = load_resource(res_name, "TESTOUT", &out_data); + out_size = load_resource(res_name, param ? "INTERACTIVEOUT" : "TESTOUT", &out_data); if(!out_size) return TRUE;
- run_test(cmd_data, cmd_size, out_data, out_size); + run_test(cmd_data, cmd_size, out_data, out_size, param); return TRUE; }
@@ -483,7 +493,15 @@ START_TEST(batch)
argc = winetest_get_mainargs(&argv); if(argc > 2) - run_from_file(argv[2]); + { + if (!strcmp(argv[2], "--interactive")) + EnumResourceNamesA(NULL, "INTERACTIVECMD", test_enum_proc, 1); + else + run_from_file(argv[2]); + } else + { EnumResourceNamesA(NULL, "TESTCMD", test_enum_proc, 0); + EnumResourceNamesA(NULL, "INTERACTIVECMD", test_enum_proc, 1); + } } diff --git a/programs/cmd/tests/interactive_builtins.cmd b/programs/cmd/tests/interactive_builtins.cmd new file mode 100644 index 00000000000..546bad4eda5 --- /dev/null +++ b/programs/cmd/tests/interactive_builtins.cmd @@ -0,0 +1 @@ +@exit 0 diff --git a/programs/cmd/tests/interactive_builtins.cmd.exp b/programs/cmd/tests/interactive_builtins.cmd.exp new file mode 100644 index 00000000000..fe6f88e5414 --- /dev/null +++ b/programs/cmd/tests/interactive_builtins.cmd.exp @@ -0,0 +1 @@ +@pwd@>@exit 0 diff --git a/programs/cmd/tests/rsrc.rc b/programs/cmd/tests/rsrc.rc index affe04c2bdd..2d14bd25473 100644 --- a/programs/cmd/tests/rsrc.rc +++ b/programs/cmd/tests/rsrc.rc @@ -16,6 +16,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+/* the TEST(CMD|OUT) are run in batch mode, + * while the INTERACTIVE(CMD|OUT) are run in interactive mode. + */ + /* @makedep: test_builtins.cmd */ test_builtins.cmd TESTCMD "test_builtins.cmd"
@@ -27,3 +31,9 @@ test_cmdline.cmd TESTCMD "test_cmdline.cmd"
/* @makedep: test_cmdline.cmd.exp */ test_cmdline.cmd.exp TESTOUT "test_cmdline.cmd.exp" + +/* @makedep: interactive_builtins.cmd */ +interactive_builtins.cmd INTERACTIVECMD "interactive_builtins.cmd" + +/* @makedep: interactive_builtins.cmd.exp */ +interactive_builtins.cmd.exp INTERACTIVEOUT "interactive_builtins.cmd.exp" diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 65601348b05..4510b5e309f 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -2762,7 +2762,7 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) */
interactive = TRUE; - if (!opt_k) WCMD_version (); + if (!opt_k) WCMD_version (); else promptNewLine = FALSE; while (TRUE) {
/* Read until EOF (which for std input is never, but if redirect
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=106864
Your paranoid android.
=== debian11 (32 bit report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit Arabic:Morocco report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit German report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit French report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit Hebrew:Israel report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit Hindi:India report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit Japanese:Japan report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit Chinese:China report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (32 bit WoW report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
=== debian11 (64 bit WoW report) ===
cmd.exe: batch.c:320: Test failed: unexpected end of line 1 (got 'C:\users\winetest\Temp\wct>', wanted '@pwd@>@exit 0')
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/tests/interactive_builtins.cmd | 9 ++++++++- programs/cmd/tests/interactive_builtins.cmd.exp | 18 +++++++++++++++++- programs/cmd/wcmdmain.c | 7 +++++++ 3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/tests/interactive_builtins.cmd b/programs/cmd/tests/interactive_builtins.cmd index 546bad4eda5..d1e308f159a 100644 --- a/programs/cmd/tests/interactive_builtins.cmd +++ b/programs/cmd/tests/interactive_builtins.cmd @@ -1 +1,8 @@ -@exit 0 +@echo --------- testing echo +echo foo +@echo foo +echo off +echo foo +@echo foo +echo --------- done +exit 0 diff --git a/programs/cmd/tests/interactive_builtins.cmd.exp b/programs/cmd/tests/interactive_builtins.cmd.exp index fe6f88e5414..64482e85c04 100644 --- a/programs/cmd/tests/interactive_builtins.cmd.exp +++ b/programs/cmd/tests/interactive_builtins.cmd.exp @@ -1 +1,17 @@ -@pwd@>@exit 0 +@pwd@>@echo --------- testing echo +--------- testing echo + +@pwd@>echo foo +foo + +@pwd@>@echo foo +foo + +@pwd@>echo off +echo foo +foo +@echo foo +foo +echo --------- done +--------- done +exit 0 diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 4510b5e309f..ee863856ec9 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1897,6 +1897,13 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE WCMD_output_asis(L"\r\n"); }
+ /* echo input stream if naturally not echoed */ + if (!context && !optionalcmd && GetFileType(readFrom) != FILE_TYPE_CHAR) + { + WCMD_output_asis(curPos); + WCMD_output_asis(L"\r\n"); + /* FIXME: same quirk as above for trailing space? */ + } /* Skip repeated 'no echo' characters */ while (*curPos == '@') curPos++;
- added a @more@ keyword to detect the 'More?' localized string (first occurence is stored, when all subsequent occurences are compared against the stored value) - some basic tests
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/tests/batch.c | 47 +++++++++++++++++++++++ programs/cmd/tests/interactive_builtins.cmd | 24 ++++++++++++ programs/cmd/tests/interactive_builtins.cmd.exp | 36 ++++++++++++++++++ programs/cmd/wcmdmain.c | 7 +++ 4 files changed, 114 insertions(+)
diff --git a/programs/cmd/tests/batch.c b/programs/cmd/tests/batch.c index 0d6832df30f..bcaeb0190ac 100644 --- a/programs/cmd/tests/batch.c +++ b/programs/cmd/tests/batch.c @@ -30,6 +30,8 @@ static char path[MAX_PATH]; static DWORD path_len; static char shortpath[MAX_PATH]; static DWORD shortpath_len; +static char more[MAX_PATH]; +static DWORD more_len;
/* Convert to DOS line endings, and substitute escaped whitespace chars with real ones */ static const char* convert_input_data(const char *data, DWORD size, DWORD *new_size) @@ -164,6 +166,31 @@ static DWORD map_file(const char *file_name, const char **ret) return size; }
+static const char *compare_line(const char *out_line, const char *out_end, const char *exp_line, + const char *exp_end); + +static BOOL guess_string(const char *out_ptr, const char *out_end, + const char *exp_ptr, const char *exp_end, + char* storage, DWORD* storage_len) +{ + /* as some output depends on locale (like 'More? ', 'Are you sure (Y|N)? '...), try to guess its value from first input */ + const char* out_try = out_ptr; + if (exp_ptr == exp_end) + { + *storage_len = min(out_end - out_ptr, MAX_PATH); + memcpy(storage, out_ptr, *storage_len); + return TRUE; + } + while (out_try < out_end) + { + storage[(*storage_len)++] = *out_try++; + if (compare_line(out_try, out_end, exp_ptr, exp_end) == NULL) + return TRUE; + } + *storage_len = 0; + return FALSE; +} + static const char *compare_line(const char *out_line, const char *out_end, const char *exp_line, const char *exp_end) { @@ -174,6 +201,7 @@ static const char *compare_line(const char *out_line, const char *out_end, const static const char drive_cmd[] = {'@','d','r','i','v','e','@'}; static const char path_cmd[] = {'@','p','a','t','h','@'}; static const char shortpath_cmd[] = {'@','s','h','o','r','t','p','a','t','h','@'}; + static const char more_cmd[] = {'@','m','o','r','e','@'}; static const char space_cmd[] = {'@','s','p','a','c','e','@'}; static const char spaces_cmd[] = {'@','s','p','a','c','e','s','@'}; static const char tab_cmd[] = {'@','t','a','b','@'}; @@ -225,6 +253,25 @@ static const char *compare_line(const char *out_line, const char *out_end, const out_ptr += shortpath_len; continue; } + } else if(exp_ptr+sizeof(more_cmd) <= exp_end + && !memcmp(exp_ptr, more_cmd, sizeof(more_cmd))) { + exp_ptr += sizeof(more_cmd); + if (!more_len) + { + if (guess_string(out_ptr, out_end, exp_ptr, exp_end, more, &more_len)) + { + trace("match @more@ with [%.*s]\n", more_len, more); + return NULL; + } + err = out_ptr; + }else if(out_end-out_ptr < more_len + || (CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, + out_ptr, more_len, more, more_len) != CSTR_EQUAL)) { + err = out_ptr; + }else { + out_ptr += more_len; + continue; + } }else if(exp_ptr+sizeof(space_cmd) <= exp_end && !memcmp(exp_ptr, space_cmd, sizeof(space_cmd))) { exp_ptr += sizeof(space_cmd); diff --git a/programs/cmd/tests/interactive_builtins.cmd b/programs/cmd/tests/interactive_builtins.cmd index d1e308f159a..f5ab45d7bb1 100644 --- a/programs/cmd/tests/interactive_builtins.cmd +++ b/programs/cmd/tests/interactive_builtins.cmd @@ -1,8 +1,32 @@ @echo --------- testing echo echo foo @echo foo +if exist c:\windows ( + echo bar +) +@if exist c:\windows ( + echo bar +) +if exist c:\windows ( + @echo bar +) +@if exist c:\windows ( + @echo bar +) echo off echo foo @echo foo +if exist c:\windows ( + echo bar +) +@if exist c:\windows ( + echo bar +) +if exist c:\windows ( + @echo bar +) +@if exist c:\windows ( + @echo bar +) echo --------- done exit 0 diff --git a/programs/cmd/tests/interactive_builtins.cmd.exp b/programs/cmd/tests/interactive_builtins.cmd.exp index 64482e85c04..4280ec186c9 100644 --- a/programs/cmd/tests/interactive_builtins.cmd.exp +++ b/programs/cmd/tests/interactive_builtins.cmd.exp @@ -7,11 +7,47 @@ foo @pwd@>@echo foo foo
+@pwd@>if exist c:\windows ( +@more@ echo bar +@more@) +bar + +@pwd@>@if exist c:\windows ( +@more@ echo bar +@more@) +bar + +@pwd@>if exist c:\windows ( +@more@ @echo bar +@more@) +bar + +@pwd@>@if exist c:\windows ( +@more@ @echo bar +@more@) +bar + @pwd@>echo off echo foo foo @echo foo foo +if exist c:\windows ( +@more@ echo bar +@more@) +bar +@if exist c:\windows ( +@more@ echo bar +@more@) +bar +if exist c:\windows ( +@more@ @echo bar +@more@) +bar +@if exist c:\windows ( +@more@ @echo bar +@more@) +bar echo --------- done --------- done exit 0 diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index ee863856ec9..286dc6b9ff0 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -2315,6 +2315,13 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE if (!WCMD_fgets(extraData, MAXSTRING, readFrom)) break;
+ /* echo input stream if naturally not echoed */ + if (!context && !optionalcmd && GetFileType(readFrom) != FILE_TYPE_CHAR) + { + WCMD_output_asis(extraData); + WCMD_output_asis(L"\r\n"); + } + /* Edge case for carets - a completely blank line (i.e. was just CRLF) is oddly added as an LF but then more data is received (but only once more!) */
Wine-bugs: https://bugs.winehq.org/show_bug.cgi?id=51599 Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/tests/interactive_builtins.cmd | 5 +++++ programs/cmd/tests/interactive_builtins.cmd.exp | 7 +++++++ programs/cmd/wcmdmain.c | 8 ++++++-- 3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/tests/interactive_builtins.cmd b/programs/cmd/tests/interactive_builtins.cmd index f5ab45d7bb1..1a06c29d103 100644 --- a/programs/cmd/tests/interactive_builtins.cmd +++ b/programs/cmd/tests/interactive_builtins.cmd @@ -28,5 +28,10 @@ if exist c:\windows ( @if exist c:\windows ( @echo bar ) +echo --------- testing syntax errors +if exist c:\windows ( + echo bar + +) echo --------- done exit 0 diff --git a/programs/cmd/tests/interactive_builtins.cmd.exp b/programs/cmd/tests/interactive_builtins.cmd.exp index 4280ec186c9..331e9b54b38 100644 --- a/programs/cmd/tests/interactive_builtins.cmd.exp +++ b/programs/cmd/tests/interactive_builtins.cmd.exp @@ -48,6 +48,13 @@ bar @more@ @echo bar @more@) bar +echo --------- testing syntax errors +--------- testing syntax errors +if exist c:\windows ( +@more@ echo bar +@more@ +@more@) +bar echo --------- done --------- done exit 0 diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 286dc6b9ff0..bfd72953639 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1840,6 +1840,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE BOOL lastWasCaret = FALSE; BOOL ignoreBracket = FALSE; /* Some expressions after if (set) require */ /* handling brackets as a normal character */ + BOOL atEOF = FALSE; int lineCurDepth; /* Bracket depth when line was read in */ BOOL resetAtEndOfLine = FALSE; /* Do we need to reset curdepth at EOL */
@@ -2297,8 +2298,8 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
/* If we have reached the end of the string, see if bracketing or final caret is outstanding */ - if (*curPos == 0x00 && (curDepth > 0 || lastWasCaret) && - readFrom != INVALID_HANDLE_VALUE) { + while (*curPos == 0x00 && (curDepth > 0 || lastWasCaret) && + readFrom != INVALID_HANDLE_VALUE && !atEOF) { WCHAR *extraData;
WINE_TRACE("Need to read more data as outstanding brackets or carets\n"); @@ -2313,7 +2314,10 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE WINE_TRACE("Read more input\n"); if (!context) WCMD_output_asis( WCMD_LoadMessage(WCMD_MOREPROMPT)); if (!WCMD_fgets(extraData, MAXSTRING, readFrom)) + { + atEOF = TRUE; break; + }
/* echo input stream if naturally not echoed */ if (!context && !optionalcmd && GetFileType(readFrom) != FILE_TYPE_CHAR)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52344 Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/tests/interactive_builtins.cmd | 3 +++ programs/cmd/tests/interactive_builtins.cmd.exp | 5 +++++ programs/cmd/wcmdmain.c | 10 +++++----- 3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/programs/cmd/tests/interactive_builtins.cmd b/programs/cmd/tests/interactive_builtins.cmd index 1a06c29d103..96d53f371fd 100644 --- a/programs/cmd/tests/interactive_builtins.cmd +++ b/programs/cmd/tests/interactive_builtins.cmd @@ -28,6 +28,9 @@ if exist c:\windows ( @if exist c:\windows ( @echo bar ) +echo --------- testing expansion for variables +set myownecho=echo +%myownecho% foo echo --------- testing syntax errors if exist c:\windows ( echo bar diff --git a/programs/cmd/tests/interactive_builtins.cmd.exp b/programs/cmd/tests/interactive_builtins.cmd.exp index 331e9b54b38..81114ccbd86 100644 --- a/programs/cmd/tests/interactive_builtins.cmd.exp +++ b/programs/cmd/tests/interactive_builtins.cmd.exp @@ -48,6 +48,11 @@ bar @more@ @echo bar @more@) bar +echo --------- testing expansion for variables +--------- testing expansion for variables +set myownecho=echo +%myownecho% foo +foo echo --------- testing syntax errors --------- testing syntax errors if exist c:\windows ( diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index bfd72953639..b79c9361fc1 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1309,6 +1309,11 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects, new_redir = heap_xalloc(MAXSTRING * sizeof(WCHAR)); redir = new_redir;
+ /* Expand variables in command line mode only (batch mode will + be expanded as the line is read in, except for 'for' loops) */ + handleExpansion(new_cmd, (context != NULL), delayedsubst); + handleExpansion(new_redir, (context != NULL), delayedsubst); + /* Strip leading whitespaces, and a '@' if supplied */ whichcmd = WCMD_skip_leading_spaces(cmd); WINE_TRACE("Command: '%s'\n", wine_dbgstr_w(cmd)); @@ -1359,11 +1364,6 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects, lstrcpyW(new_redir, redirects); }
- /* Expand variables in command line mode only (batch mode will - be expanded as the line is read in, except for 'for' loops) */ - handleExpansion(new_cmd, (context != NULL), delayedsubst); - handleExpansion(new_redir, (context != NULL), delayedsubst); - /* * Changing default drive has to be handled as a special case, anything * else if it exists after whitespace is ignored
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52345 Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/builtins.c | 10 ++++++++++ programs/cmd/tests/interactive_builtins.cmd | 2 ++ programs/cmd/tests/interactive_builtins.cmd.exp | 2 ++ 3 files changed, 14 insertions(+)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 2fc7e07f7aa..84befa9fc43 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -2704,6 +2704,12 @@ void WCMD_popd (void) { LocalFree (temp); }
+/* check that operand is either unquoted, or with opening and ending quotes */ +static BOOL is_properly_quoted(const WCHAR* str) +{ + return str[0] != '"' || (str[1] && str[wcslen(str) - 1] == '"'); +} + /******************************************************************* * evaluate_if_comparison * @@ -2729,8 +2735,12 @@ static int evaluate_if_comparison(const WCHAR *leftOperand, const WCHAR *operato
/* == is a special case, as it always compares strings */ if (!lstrcmpiW(operator, L"==")) + { + if (!is_properly_quoted(leftOperand) || !is_properly_quoted(rightOperand)) + return -1; return caseInsensitive ? lstrcmpiW(leftOperand, rightOperand) == 0 : lstrcmpW (leftOperand, rightOperand) == 0; + }
/* Check if we have plain integers (in decimal, octal or hexadecimal notation) */ leftOperand_int = wcstol(leftOperand, &endptr_leftOp, 0); diff --git a/programs/cmd/tests/interactive_builtins.cmd b/programs/cmd/tests/interactive_builtins.cmd index 96d53f371fd..91d62ed6959 100644 --- a/programs/cmd/tests/interactive_builtins.cmd +++ b/programs/cmd/tests/interactive_builtins.cmd @@ -36,5 +36,7 @@ if exist c:\windows ( echo bar
) +if x == " echo f +rem " echo --------- done exit 0 diff --git a/programs/cmd/tests/interactive_builtins.cmd.exp b/programs/cmd/tests/interactive_builtins.cmd.exp index 81114ccbd86..df4c278ca39 100644 --- a/programs/cmd/tests/interactive_builtins.cmd.exp +++ b/programs/cmd/tests/interactive_builtins.cmd.exp @@ -60,6 +60,8 @@ if exist c:\windows ( @more@ @more@) bar +if x == " echo f +rem " echo --------- done --------- done exit 0