[PATCH] cmd: Fixed invalid behavior of "C: && echo test"
Alexander Coffin
alexcoffin1999 at gmail.com
Fri Sep 15 02:02:26 CDT 2017
Fixes: https://bugs.winehq.org/show_bug.cgi?id=40694
Fixes the bug, what else is there to say? I also added some tests for
it to test_builtins.cmd, but they don't work on Wine since they
require the "subst" command. However they run on Windows and will be
useful when the "subst" command is added.
Tested on Linux Mint, and a Windows 10 VM
Signed-off-by: Alexander Coffin <alexcoffin1999 at gmail.com>
---
programs/cmd/tests/test_builtins.cmd | 60 +++++++++++++++++++++++++++++++
programs/cmd/tests/test_builtins.cmd.exp | 9 +++++
programs/cmd/wcmdmain.c | 62 ++++++++++++++++++--------------
3 files changed, 105 insertions(+), 26 deletions(-)
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 62334b1..58a9a71 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -2978,6 +2978,66 @@ path
set path=%WINE_backup_path%
set WINE_backup_path=
+echo ------------ Testing DRIVE PATH ------------
+rem Check if H:\ drive doesn't already exist
+set "removedrive=0"
+set "curdrive=%CD:~0,2%"
+if curdrive == "H:" (
+ echo This test is going to fail...
+ goto :drivepathfailed
+)
+if not exist .\TempDriveFolder\ (
+ mkdir .\TempDriveFolder\
+)
+if not exist H:\ (
+ set "removedrive=1"
+ subst H: .\TempDriveFolder
+)
+if not exist H:\tmpwinetestfolder\ (
+ H:
+ mkdir H:\tmpwinetestfolder\
+ %curdrive%
+)
+H:
+cd H:\tmpwinetestfolder\
+cd
+%curdrive%
+H: 2>nul
+cd
+%curdrive%
+H: C:
+cd
+%curdrive%
+@@H:
+cd
+%curdrive%
+ @@@h: /blahblah%^^!
+cd
+%curdrive%
+h: && echo test >nul
+cd
+%curdrive%
+h: || echo haha > nul
+cd
+
+%curdrive%
+rem Resets the errorlevel to 0
+ver >nul 2>nul
+h:fail 2>nul
+if not %ERRORLEVEL% == 0 (
+ echo Error
+) else (
+ echo Expected error, didn't get one Error: %ERRORLEVEL%
+)
+
+%curdrive%
+rmdir H:\tmpwinetestfolder\
+rmdir /S /Q .\TempDriveFolder\
+if %removedrive% == 1 (
+ subst H: /D
+)
+:drivepathfailed
+
echo ------------ Testing combined CALLs/GOTOs ------------
echo @echo off>foo.cmd
echo goto :eof>>foot.cmd
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 796550e..be6eff1 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -1571,6 +1571,15 @@ Correctly ignored trailing information
PATH=original
PATH=try2
PATH=try3
+------------ Testing DRIVE PATH ------------
+ at todo_wine@H:\tmpwinetestfolder
+ at todo_wine@H:\tmpwinetestfolder
+ at todo_wine@H:\tmpwinetestfolder
+ at todo_wine@H:\tmpwinetestfolder
+ at todo_wine@H:\tmpwinetestfolder
+ at todo_wine@H:\tmpwinetestfolder
+ at todo_wine@H:\tmpwinetestfolder
+Error
------------ Testing combined CALLs/GOTOs ------------
world
cheball
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index 102e485..55e2afa 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -1326,32 +1326,6 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
handleExpansion(new_redir, (context != NULL), delayedsubst);
cmd = new_cmd;
-/*
- * Changing default drive has to be handled as a special case.
- */
-
- if ((strlenW(cmd) == 2) && (cmd[1] == ':') && IsCharAlphaW(cmd[0])) {
- WCHAR envvar[5];
- WCHAR dir[MAX_PATH];
-
- /* According to MSDN CreateProcess docs, special env vars record
- the current directory on each drive, in the form =C:
- so see if one specified, and if so go back to it */
- strcpyW(envvar, equalW);
- strcatW(envvar, cmd);
- if (GetEnvironmentVariableW(envvar, dir, MAX_PATH) == 0) {
- static const WCHAR fmt[] = {'%','s','\\','\0'};
- wsprintfW(cmd, fmt, cmd);
- WINE_TRACE("No special directory settings, using dir of %s\n", wine_dbgstr_w(cmd));
- }
- WINE_TRACE("Got directory %s as %s\n", wine_dbgstr_w(envvar), wine_dbgstr_w(cmd));
- status = SetCurrentDirectoryW(cmd);
- if (!status) WCMD_print_error ();
- heap_free(cmd );
- heap_free(new_redir);
- return;
- }
-
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
@@ -1451,6 +1425,42 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
if (whichcmd[0] == '@') whichcmd++;
/*
+ * Changing default drive has to be handled as a special case.
+ *
+ * It appears it only matters if the first command is a letter
+ * followed by a colon. It could be "d: c:", "d: blahblabh", or
+ * even " @@@D: /blahblah%^^!"
+ */
+
+ if ((strlenW(cmd) >= 2) && (cmd[1] == ':') && IsCharAlphaW(cmd[0]) && !(strlenW(cmd) >= 3 && cmd[2] != ' ')) {
+ WCHAR envvar[5];
+ WCHAR dir[MAX_PATH];
+
+ /* According to MSDN CreateProcess docs, special env vars record
+ the current directory on each drive, in the form =C:
+ so see if one specified, and if so go back to it */
+ cmd[0] = toupperW(cmd[0]);
+ /*
+ * The following line is comment merely to help legibility
+ */
+ /*cmd[1] = cmd[1];*/
+ cmd[2] = '\0';
+ strcpyW(envvar, equalW);
+ strcatW(envvar, cmd);
+ if (GetEnvironmentVariableW(envvar, dir, MAX_PATH) == 0) {
+ static const WCHAR fmt[] = {'%','s','\\','\0'};
+ wsprintfW(cmd, fmt, cmd);
+ WINE_TRACE("No special directory settings, using dir of %s\n", wine_dbgstr_w(cmd));
+ }
+ WINE_TRACE("Got directory %s as %s\n", wine_dbgstr_w(envvar), wine_dbgstr_w(cmd));
+ status = SetCurrentDirectoryW(cmd);
+ if (!status) WCMD_print_error ();
+ heap_free(cmd);
+ heap_free(new_redir);
+ return;
+ }
+
+/*
* Check if the command entered is internal. If it is, pass the rest of the
* line down to the command. If not try to run a program.
*/
--
2.7.4
More information about the wine-patches
mailing list