Jason Edmeades : cmd.exe: Add support for stderr redirection to a
file.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Mar 13 07:56:05 CDT 2007
Module: wine
Branch: master
Commit: 085c0f4a3a367eb52721140c109343b47cee9170
URL: http://source.winehq.org/git/wine.git/?a=commit;h=085c0f4a3a367eb52721140c109343b47cee9170
Author: Jason Edmeades <us at edmeades.me.uk>
Date: Tue Mar 13 00:09:05 2007 +0000
cmd.exe: Add support for stderr redirection to a file.
---
programs/cmd/wcmdmain.c | 67 ++++++++++++++++++++++++++++++----------------
1 files changed, 44 insertions(+), 23 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index 11c2576..eaac82b 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -385,15 +385,20 @@ int main (int argc, char *argv[])
void WCMD_process_command (char *command)
{
- char *cmd, *p, *s, *t;
+ char *cmd, *p, *s, *t, *redir;
int status, i;
DWORD count, creationDisposition;
HANDLE h;
char *whichcmd;
SECURITY_ATTRIBUTES sa;
char *new_cmd;
- HANDLE old_stdin = INVALID_HANDLE_VALUE;
- HANDLE old_stdout = INVALID_HANDLE_VALUE;
+ char *first_redir = NULL;
+ HANDLE old_stdhandles[3] = {INVALID_HANDLE_VALUE,
+ INVALID_HANDLE_VALUE,
+ INVALID_HANDLE_VALUE};
+ DWORD idx_stdhandles[3] = {STD_INPUT_HANDLE,
+ STD_OUTPUT_HANDLE,
+ STD_ERROR_HANDLE};
/* Move copy of the command onto the heap so it can be expanded */
new_cmd = HeapAlloc( GetProcessHeap(), 0, MAXSTRING );
@@ -486,16 +491,16 @@ void WCMD_process_command (char *command)
return;
}
- /* Don't issue newline WCMD_output (newline); @JED*/
-
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
+
/*
- * Redirect stdin and/or stdout if required.
+ * Redirect stdin, stdout and/or stderr if required.
*/
if ((p = strchr(cmd,'<')) != NULL) {
+ if (first_redir == NULL) first_redir = p;
h = CreateFile (WCMD_parameter (++p, 0, NULL), GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
@@ -503,11 +508,24 @@ void WCMD_process_command (char *command)
HeapFree( GetProcessHeap(), 0, cmd );
return;
}
- old_stdin = GetStdHandle (STD_INPUT_HANDLE);
+ old_stdhandles[0] = GetStdHandle (STD_INPUT_HANDLE);
SetStdHandle (STD_INPUT_HANDLE, h);
}
- if ((p = strchr(cmd,'>')) != NULL) {
- *p++ = '\0';
+
+ /* Scan the whole command looking for > and 2> */
+ redir = cmd;
+ while (redir != NULL && ((p = strchr(redir,'>')) != NULL)) {
+ int handle = 0;
+
+ if (*(p-1)!='2') {
+ if (first_redir == NULL) first_redir = p;
+ handle = 1;
+ } else {
+ if (first_redir == NULL) first_redir = (p-1);
+ handle = 2;
+ }
+
+ p++;
if ('>' == *p) {
creationDisposition = OPEN_ALWAYS;
p++;
@@ -515,21 +533,24 @@ void WCMD_process_command (char *command)
else {
creationDisposition = CREATE_ALWAYS;
}
+ redir = p;
h = CreateFile (WCMD_parameter (p, 0, NULL), GENERIC_WRITE, 0, &sa, creationDisposition,
- FILE_ATTRIBUTE_NORMAL, NULL);
+ FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
- WCMD_print_error ();
+ WCMD_print_error ();
HeapFree( GetProcessHeap(), 0, cmd );
- return;
+ return;
}
if (SetFilePointer (h, 0, NULL, FILE_END) ==
- INVALID_SET_FILE_POINTER) {
+ INVALID_SET_FILE_POINTER) {
WCMD_print_error ();
}
- old_stdout = GetStdHandle (STD_OUTPUT_HANDLE);
- SetStdHandle (STD_OUTPUT_HANDLE, h);
+ old_stdhandles[handle] = GetStdHandle (idx_stdhandles[handle]);
+ SetStdHandle (idx_stdhandles[handle], h);
}
- if ((p = strchr(cmd,'<')) != NULL) *p = '\0';
+
+ /* Terminate the command string at <, or first 2> or > */
+ if (first_redir != NULL) *first_redir = '\0';
/*
* Strip leading whitespaces, and a '@' if supplied
@@ -681,13 +702,13 @@ void WCMD_process_command (char *command)
WCMD_run_program (whichcmd, 0);
}
HeapFree( GetProcessHeap(), 0, cmd );
- if (old_stdin != INVALID_HANDLE_VALUE) {
- CloseHandle (GetStdHandle (STD_INPUT_HANDLE));
- SetStdHandle (STD_INPUT_HANDLE, old_stdin);
- }
- if (old_stdout != INVALID_HANDLE_VALUE) {
- CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE));
- SetStdHandle (STD_OUTPUT_HANDLE, old_stdout);
+
+ /* Restore old handles */
+ for (i=0; i<3; i++) {
+ if (old_stdhandles[i] != INVALID_HANDLE_VALUE) {
+ CloseHandle (GetStdHandle (idx_stdhandles[i]));
+ SetStdHandle (idx_stdhandles[i], old_stdhandles[i]);
+ }
}
}
More information about the wine-cvs
mailing list