Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57795
Closes #57795
-- v3: cmd: add support for right-to-left handle redirection (2<&1)
From: Damjan Jovanovic damjan.jov@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57795 --- programs/cmd/tests/test_builtins.cmd | 5 +++++ programs/cmd/tests/test_builtins.cmd.exp | 3 +++ programs/cmd/wcmdmain.c | 18 +++++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 8552d51930a..a38456d95c5 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -176,6 +176,11 @@ del foo echo foo> foo echo foo7 7>> foo || (echo not supported & del foo) if exist foo (type foo) else echo not supported +echo --- right-to-left redirection +echo foo 1>foo-out 2>foo-err 1<&2 +findstr foo foo-out >nul 2>nul & if errorlevel 1 (echo not in foo-out) else echo in foo-out +findstr foo foo-err >nul 2>nul & if errorlevel 1 (echo not in foo-err) else echo in foo-err +erase /q foo-out foo-err echo --- redirect at beginning of line
foo (echo foo)
type foo diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 292c24985e8..42cd415e147 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -204,6 +204,9 @@ food2 food21 foo7@space@@space@@or_broken@not supported@space@ foo@or_broken@not supported +--- right-to-left redirection +not in foo-out +in foo-err --- redirect at beginning of line foo foo1 diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index b19f8453438..3e248a6d36a 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -2627,8 +2627,20 @@ static void lexer_push_command(struct node_builder *builder,
if (*p == L'<') { - filename = WCMD_parameter(p + 1, 0, NULL, FALSE, FALSE); - tkn_pmt.redirection = redirection_create_file(REDIR_READ_FROM, 0, filename); + unsigned fd = 0; + + if (p > redirs && p[-1] >= L'0' && p[-1] <= L'9') fd = p[-1] - L'0'; + p++; + if (*p == L'&' && (p[1] >= L'0' && p[1] <= L'9')) + { + tkn_pmt.redirection = redirection_create_clone(fd, p[1] - L'0'); + p++; + } + else + { + filename = WCMD_parameter(p + 1, 0, NULL, FALSE, FALSE); + tkn_pmt.redirection = redirection_create_file(REDIR_READ_FROM, 0, filename); + } } else { @@ -2984,7 +2996,7 @@ enum read_parse_line WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **
/* If a redirect is immediately followed by '&' (ie. 2>&1) then do not process that ampersand as an AND operator */ - if (thisChar == '>' && *(curPos+1) == '&') { + if ((thisChar == '>' || thisChar == '<') && *(curPos+1) == '&') { curCopyTo[(*curLen)++] = *(curPos+1); curPos++; }
On Tue Feb 4 17:02:04 2025 +0000, eric pouech wrote:
we could perhaps test that the cloning of the handle actually took place your test just shows that the parsing succeeds but nothing is actually written to 2 something like would do `dir /Z > foo 2<&1` `findstr . foo > NUL & if errorlevel 1 (echo not redirected) else echo redirected`
Thank you, I've updated the test to check whether redirection to stderr happens.
thanks for the update, your new first test is way cleaner...
(just trying to simplify at most the tests and avoid calling external findstr, you could do
`type foo-out 2> NUL || echo good`
`type foo-err 2> NUL || echo bad`
should output
`good`
`foo`
(does work on native, should work on wine but didn't test it though)