[ros-diffs] [jmorlan] 35508: - Implement X>&Y redirections. Hold redirections in a linked list structure, because order matters (>x 2>&1 is not the same as 2>&1 >x). Allow redirection of any handle number from 0 to 9. - Allow quotes around the redirection file name. - Batch: Fix buffer overflow bug (incorrect size for bc->BatchFilePath)

jmorlan at svn.reactos.org jmorlan at svn.reactos.org
Thu Aug 21 17:33:59 CEST 2008


Author: jmorlan
Date: Thu Aug 21 10:33:59 2008
New Revision: 35508

URL: http://svn.reactos.org/svn/reactos?rev=35508&view=rev
Log:
- Implement X>&Y redirections. Hold redirections in a linked list structure, because order matters (>x 2>&1 is not the same as 2>&1 >x). Allow redirection of any handle number from 0 to 9. 
- Allow quotes around the redirection file name.
- Batch: Fix buffer overflow bug (incorrect size for bc->BatchFilePath)

Modified:
    trunk/reactos/base/shell/cmd/batch.c
    trunk/reactos/base/shell/cmd/batch.h
    trunk/reactos/base/shell/cmd/call.c
    trunk/reactos/base/shell/cmd/cmd.c
    trunk/reactos/base/shell/cmd/cmd.h
    trunk/reactos/base/shell/cmd/for.c
    trunk/reactos/base/shell/cmd/misc.c
    trunk/reactos/base/shell/cmd/redir.c
    trunk/reactos/base/shell/cmd/start.c

Modified: trunk/reactos/base/shell/cmd/batch.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -193,6 +193,9 @@
 
 		if (bc->ffind)
 			cmd_free(bc->ffind);
+
+		UndoRedirection(bc->RedirList, NULL);
+		FreeRedirection(bc->RedirList);
 
 		/* Preserve echo state across batch calls */
 		bEcho = bc->bEcho;
@@ -248,9 +251,7 @@
 
 		n->prev = bc;
 		bc = n;
-		bc->In[0] = _T('\0');
-		bc->Out[0] = _T('\0');
-		bc->Err[0] = _T('\0');
+		bc->RedirList = NULL;
 	}
 	else if (bc->hBatchFile != INVALID_HANDLE_VALUE)
 	{
@@ -263,7 +264,7 @@
 			cmd_free (bc->raw_params);
 	}
 
-	GetFullPathName(fullname, sizeof(bc->BatchFilePath), bc->BatchFilePath, &tmp);
+	GetFullPathName(fullname, sizeof(bc->BatchFilePath) / sizeof(TCHAR), bc->BatchFilePath, &tmp);
 	*tmp = '\0';
 
 	bc->hBatchFile = hFile;
@@ -300,17 +301,23 @@
 	return TRUE;
 }
 
-VOID AddBatchRedirection(TCHAR * ifn, TCHAR * ofn, TCHAR * efn)
+VOID AddBatchRedirection(REDIRECTION **RedirList)
 {
+	REDIRECTION **ListEnd;
+
 	if(!bc)
 		return;
-	if(_tcslen(ifn))
-		_tcscpy(bc->In,ifn);
-	if(_tcslen(ofn))
-		_tcscpy(bc->Out,ofn);
-	if(_tcslen(efn))
-		_tcscpy(bc->Err,efn);
-
+
+	/* Prepend the list to the batch context's list */
+	ListEnd = RedirList;
+	while (*ListEnd)
+		ListEnd = &(*ListEnd)->Next;
+	*ListEnd = bc->RedirList;
+	bc->RedirList = *RedirList;
+
+	/* Null out the pointer so that the list will not be cleared prematurely.
+	 * These redirections should persist until the batch file exits. */
+	*RedirList = NULL;
 }
 
 /*

Modified: trunk/reactos/base/shell/cmd/batch.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.h?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -19,9 +19,7 @@
 	INT    shiftlevel;
 	BOOL   bEcho;        /* Preserve echo flag across batch calls */
 	HANDLE hFind;        /* Preserve find handle when doing a for */
-	TCHAR In[MAX_PATH];
-	TCHAR Out[MAX_PATH];
-	TCHAR Err[MAX_PATH];
+	REDIRECTION *RedirList;
 	TCHAR forvar;
 	INT   bCmdBlock;
 	BOOL  bExecuteBlock[MAX_PATH];
@@ -47,6 +45,6 @@
 VOID   ExitBatch (LPTSTR);
 BOOL   Batch (LPTSTR, LPTSTR, LPTSTR);
 LPTSTR ReadBatchLine (LPBOOL);
-VOID AddBatchRedirection(TCHAR *, TCHAR *, TCHAR *);
+VOID AddBatchRedirection(REDIRECTION **);
 
 #endif /* _BATCH_H_INCLUDED_ */

Modified: trunk/reactos/base/shell/cmd/call.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/call.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/call.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/call.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -76,19 +76,8 @@
 	bc->shiftlevel = 0;
 	bc->forvar = 0;        /* HBP004 */
 	bc->forproto = NULL;   /* HBP004 */
+	bc->RedirList = NULL;
 	ParseCommandLine (param);
-	if (bc->prev)
-	{
-		_tcscpy(bc->In, bc->prev->In);
-		_tcscpy(bc->Out, bc->prev->Out);
-		_tcscpy(bc->Err, bc->prev->Err);
-	}
-	else
-	{
-		bc->In[0] = _T('\0');
-		bc->Out[0] = _T('\0');
-		bc->Err[0] = _T('\0');
-	}
 
 
 	/* Wasn't a batch file so remove conext */

Modified: trunk/reactos/base/shell/cmd/cmd.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -690,21 +690,16 @@
 	TCHAR cmdline[CMDLINE_LENGTH];
 	LPTSTR s;
 #ifdef FEATURE_REDIRECTION
-	TCHAR in[CMDLINE_LENGTH] = _T("");
-	TCHAR out[CMDLINE_LENGTH] = _T("");
-	TCHAR err[CMDLINE_LENGTH] = _T("");
+	REDIRECTION *RedirList = NULL;
 	TCHAR szTempPath[MAX_PATH] = _T(".\\");
 	TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
 	HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
-	LPTSTR t = NULL;
 	INT  num = 0;
-	INT  nRedirFlags = 0;
 	INT  Length;
 	UINT Attributes;
 	BOOL bNewBatch = TRUE;
 	HANDLE hOldConIn;
 	HANDLE hOldConOut;
-	HANDLE hOldConErr;
 #endif /* FEATURE_REDIRECTION */
 
 	_tcscpy (cmdline, cmd);
@@ -732,65 +727,18 @@
 		_tcscat (szTempPath, _T("\\"));
 
 	/* get the redirections from the command line */
-	num = GetRedirection (s, in, out, err, &nRedirFlags);
-
-	/* more efficient, but do we really need to do this? */
-	for (t = in; _istspace (*t); t++)
-		;
-	_tcscpy (in, t);
-
-	for (t = out; _istspace (*t); t++)
-		;
-	_tcscpy (out, t);
-
-	for (t = err; _istspace (*t); t++)
-		;
-	_tcscpy (err, t);
-
-	if(bc && !_tcslen (in) && _tcslen (bc->In))
-		_tcscpy(in, bc->In);
-	if(bc && !out[0] && _tcslen(bc->Out))
-	{
-		nRedirFlags |= OUTPUT_APPEND;
-		_tcscpy(out, bc->Out);
-	}
-	if(bc && !_tcslen (err) && _tcslen (bc->Err))
-	{
-		nRedirFlags |= ERROR_APPEND;
-		_tcscpy(err, bc->Err);
+	num = GetRedirection (s, &RedirList);
+
+	if (!PerformRedirection(RedirList))
+	{
+		FreeRedirection(RedirList);
+		return;
 	}
 
 	/* Set up the initial conditions ... */
-	/* preserve STDIN, STDOUT and STDERR handles */
+	/* preserve STDIN and STDOUT handles */
 	hOldConIn  = GetStdHandle (STD_INPUT_HANDLE);
 	hOldConOut = GetStdHandle (STD_OUTPUT_HANDLE);
-	hOldConErr = GetStdHandle (STD_ERROR_HANDLE);
-
-	/* redirect STDIN */
-	if (in[0])
-	{
-		HANDLE hFile;
-		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
-
-	/* we need make sure the LastError msg is zero before calling CreateFile */
-		SetLastError(0);
-
-	/* Set up pipe for the standard input handler */
-		hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
-		                    FILE_ATTRIBUTE_NORMAL, NULL);
-		if (hFile == INVALID_HANDLE_VALUE)
-		{
-			ConErrResPrintf(STRING_CMD_ERROR1, in);
-			return;
-		}
-
-		if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
-		{
-			ConErrResPrintf(STRING_CMD_ERROR1, in);
-			return;
-		}
-		TRACE ("Input redirected from: %s\n", debugstr_aw(in));
-	}
 
 	/* Now do all but the last pipe command */
 	*szFileName[0] = _T('\0');
@@ -855,123 +803,7 @@
 	}
 
 	/* Now set up the end conditions... */
-	/* redirect STDOUT */
-	if (out[0])
-	{
-		/* Final output to here */
-		HANDLE hFile;
-		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
-
-		/* we need make sure the LastError msg is zero before calling CreateFile */
-		SetLastError(0);
-
-		hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
-		                    (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
-		                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
-
-		if (hFile == INVALID_HANDLE_VALUE)
-		{
-			INT size = _tcslen(out)-1;
-
-			if (out[size] != _T(':'))
-			{
-				ConErrResPrintf(STRING_CMD_ERROR3, out);
-				return;
-			}
-
-			out[size]=_T('\0');
-			hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
-			                    (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
-			                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
-
-			if (hFile == INVALID_HANDLE_VALUE)
-			{
-				ConErrResPrintf(STRING_CMD_ERROR3, out);
-				return;
-			}
-
-		}
-
-		if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
-		{
-			ConErrResPrintf(STRING_CMD_ERROR3, out);
-			return;
-		}
-
-		if (nRedirFlags & OUTPUT_APPEND)
-		{
-			LONG lHighPos = 0;
-
-			if (GetFileType (hFile) == FILE_TYPE_DISK)
-				SetFilePointer (hFile, 0, &lHighPos, FILE_END);
-		}
-		TRACE ("Output redirected to: %s\n", debugstr_aw(out));
-	}
-	else if (hOldConOut != INVALID_HANDLE_VALUE)
-	{
-		/* Restore original stdout */
-		HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
-		SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
-		if (hOldConOut != hOut)
-			CloseHandle (hOut);
-		hOldConOut = INVALID_HANDLE_VALUE;
-	}
-
-	/* redirect STDERR */
-	if (err[0])
-	{
-		/* Final output to here */
-		HANDLE hFile;
-		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
-
-		if (!_tcscmp (err, out))
-		{
-			TRACE ("Stdout and stderr will use the same file!!\n");
-			DuplicateHandle (GetCurrentProcess (),
-			                 GetStdHandle (STD_OUTPUT_HANDLE),
-			                 GetCurrentProcess (),
-			                 &hFile, 0, TRUE, DUPLICATE_SAME_ACCESS);
-		}
-		else
-		{
-			hFile = CreateFile (err,
-			                    GENERIC_WRITE,
-			                    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
-			                    &sa,
-			                    (nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
-			                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
-			                    NULL);
-			if (hFile == INVALID_HANDLE_VALUE)
-			{
-				ConErrResPrintf(STRING_CMD_ERROR3, err);
-				return;
-			}
-		}
-
-		if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
-		{
-			ConErrResPrintf(STRING_CMD_ERROR3, err);
-			return;
-		}
-
-		if (nRedirFlags & ERROR_APPEND)
-		{
-			LONG lHighPos = 0;
-
-			if (GetFileType (hFile) == FILE_TYPE_DISK)
-				SetFilePointer (hFile, 0, &lHighPos, FILE_END);
-		}
-		TRACE ("Error redirected to: %s\n", debugstr_aw(err));
-	}
-	else if (hOldConErr != INVALID_HANDLE_VALUE)
-	{
-		/* Restore original stderr */
-		HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
-		SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
-		if (hOldConErr != hErr)
-			CloseHandle (hErr);
-		hOldConErr = INVALID_HANDLE_VALUE;
-	}
+	SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
 
 	if(bc)
 		bNewBatch = FALSE;
@@ -982,7 +814,7 @@
 
 #ifdef FEATURE_REDIRECTION
 	if(bNewBatch && bc)
-		AddBatchRedirection(in, out, err);
+		AddBatchRedirection(&RedirList);
 	/* close old stdin file */
 #if 0  /* buggy implementation */
 	SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
@@ -1039,26 +871,8 @@
 		}
 	}
 
-
-	/* Restore original STDOUT */
-	if (hOldConOut != INVALID_HANDLE_VALUE)
-	{
-		HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
-		SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
-		if (hOldConOut != hOut)
-			CloseHandle (hOut);
-		hOldConOut = INVALID_HANDLE_VALUE;
-	}
-
-	/* Restore original STDERR */
-	if (hOldConErr != INVALID_HANDLE_VALUE)
-	{
-		HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
-		SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
-		if (hOldConErr != hErr)
-			CloseHandle (hErr);
-		hOldConErr = INVALID_HANDLE_VALUE;
-	}
+	UndoRedirection(RedirList, NULL);
+	FreeRedirection(RedirList);
 #endif /* FEATURE_REDIRECTION */
 }
 

Modified: trunk/reactos/base/shell/cmd/cmd.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -301,6 +301,7 @@
 LPTSTR *split (LPTSTR, LPINT, BOOL);
 VOID   freep (LPTSTR *);
 LPTSTR _stpcpy (LPTSTR, LPCTSTR);
+VOID   StripQuotes(LPTSTR);
 BOOL   IsValidPathName (LPCTSTR);
 BOOL   IsExistingFile (LPCTSTR);
 BOOL   IsExistingDirectory (LPCTSTR);
@@ -335,12 +336,19 @@
 
 
 /* Prototypes for REDIR.C */
-#define INPUT_REDIRECTION    1
-#define OUTPUT_REDIRECTION   2
-#define OUTPUT_APPEND        4
-#define ERROR_REDIRECTION    8
-#define ERROR_APPEND        16
-INT GetRedirection (LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPINT);
+enum { REDIR_READ, REDIR_WRITE, REDIR_APPEND };
+typedef struct _REDIRECTION
+{
+	struct _REDIRECTION *Next;
+	HANDLE OldHandle;
+	BYTE Number;
+	BYTE Type;
+	TCHAR Filename[];
+} REDIRECTION;
+BOOL PerformRedirection(REDIRECTION *);
+VOID UndoRedirection(REDIRECTION *, REDIRECTION *End);
+INT GetRedirection(LPTSTR, REDIRECTION **);
+VOID FreeRedirection(REDIRECTION *);
 
 
 /* Prototypes for REN.C */

Modified: trunk/reactos/base/shell/cmd/for.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/for.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/for.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/for.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -138,9 +138,7 @@
 		bc->bEcho = bc->prev->bEcho;
 	else
 		bc->bEcho = bEcho;
-		bc->In[0] = _T('\0');
-		bc->Out[0] = _T('\0');
-		bc->Err[0] = _T('\0');
+	bc->RedirList = NULL;
 
 
 	return 0;

Modified: trunk/reactos/base/shell/cmd/misc.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/misc.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/misc.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/misc.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -411,6 +411,18 @@
 	return (dest + _tcslen (src));
 }
 
+VOID
+StripQuotes(TCHAR *in)
+{
+	TCHAR *out = in;
+	for (; *in; in++)
+	{
+		if (*in != _T('"'))
+			*out++ = *in;
+	}
+	*out = _T('\0');
+}
+
 
 
 /*

Modified: trunk/reactos/base/shell/cmd/redir.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/redir.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/redir.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/redir.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -51,11 +51,12 @@
  *
  */
 
-INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags)
+INT GetRedirection (LPTSTR s, REDIRECTION **RedirList)
 {
 	INT num = 1;
 	LPTSTR dp = s;
 	LPTSTR sp = s;
+	TCHAR Filename[MAX_PATH];
 
 #ifdef INCLUDE_CMD_REM
 
@@ -68,10 +69,6 @@
 	/*first thing first.  check to see if this is "rem" and hope out*/
 	if(!_tcsncmp (line, _T("rem "), 4))
 	{
-		lpnFlags = 0;
-		*ifn=('\0');
-		*ofn=('\0');
-		*efn=_T('\0');
 		return 1;
 	}
 #endif
@@ -94,148 +91,74 @@
 			while (*sp && *sp != qc);
 
 			*dp++ = *sp++;
-		}
-		else if ((*sp == _T('<')) || (*sp == _T('>')) ||
-				 (*sp == _T('1')) || (*sp == _T('2')) || (*sp == _T('&')))
-		{
-			/* MS-DOS ignores multiple redirection symbols and uses the last */
-			/* redirection, so we'll emulate that and not check */
+			continue;
+		}
+
+		int NumberGiven = (*sp >= _T('0') && *sp <= _T('9')) ? 1 : 0;
+		if (sp[NumberGiven] == _T('<') || sp[NumberGiven] == _T('>'))
+		{
+			BYTE HandleNumber;
+			BYTE Type;
+			BOOL bInQuote = FALSE;
+			TCHAR *fn = Filename;
+			REDIRECTION *Redir, **ListPtr;
+
+			if (NumberGiven)
+				HandleNumber = *sp++ - _T('0');
+			else
+				HandleNumber = *sp == _T('<') ? 0 : 1;
 
 			if (*sp == _T('<'))
 			{
 				/* input redirection */
-				*lpnFlags |= INPUT_REDIRECTION;
-				do sp++;
-				while( _istspace (*sp) );
-
-				/* copy file name */
-				while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
-					*ifn++ = *sp++;
-				*ifn = _T('\0');
-			}
-			else if (*sp == _T('>'))
+				Type = REDIR_READ;
+				sp++;
+			}
+			else
 			{
 				/* output redirection */
-				*lpnFlags |= OUTPUT_REDIRECTION;
+				Type = REDIR_WRITE;
 				sp++;
 
 				/* append request ? */
 				if (*sp == _T('>'))
 				{
-					*lpnFlags |= OUTPUT_APPEND;
+					Type = REDIR_APPEND;
 					sp++;
 				}
-
-				while (_istspace (*sp))
-					sp++;
-
-				/* copy file name */
-				while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
-					*ofn++ = *sp++;
-				*ofn = _T('\0');
-			}
-
-                        else if (*sp == _T('1'))
-			{
-				/* output redirection */
+			}
+
+			while (_istspace(*sp))
 				sp++;
 
-				if (*sp == _T('>'))
+			/* copy file name */
+			while (*sp && (bInQuote || (!IsRedirection (*sp) && !_istspace (*sp))))
+			{
+				bInQuote ^= (*sp == _T('"'));
+				*fn++ = *sp++;
+			}
+			*fn++ = _T('\0');
+
+			/* Delete any existing redirection for the same handle number */
+			ListPtr = RedirList;
+			while ((Redir = *ListPtr))
+			{
+				if (Redir->Number == HandleNumber)
 				{
-					/* output redirection */
-				        *lpnFlags |= OUTPUT_REDIRECTION;
-				        sp++;
-
-				        /* append request ? */
-				        if (*sp == _T('>'))
-				        {
-					        *lpnFlags |= OUTPUT_APPEND;
-					        sp++;
-				        }
-				}
-				else
-				{
-					/* no redirection!! copy the '1' character! */
-					sp--;
-					*dp++ = *sp++;
+					*ListPtr = Redir->Next;
+					cmd_free(Redir);
 					continue;
 				}
-
-				while (_istspace (*sp))
-					sp++;
-
-				/* copy file name */
-				while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
-					*ofn++ = *sp++;
-				*ofn = _T('\0');
-			}
-
-			else if (*sp == _T('2'))
-			{
-				/* error redirection */
-				sp++;
-
-				if (*sp == _T('>'))
-				{
-					*lpnFlags |= ERROR_REDIRECTION;
-					sp++;
-
-					/* append request ? */
-					if (*sp == _T('>'))
-					{
-						*lpnFlags |= ERROR_APPEND;
-						sp++;
-					}
-				}
-				else
-				{
-					/* no redirection!! copy the '2'  character! */
-					sp--;
-					*dp++ = *sp++;
-					continue;
-				}
-
-				while (_istspace (*sp))
-					sp++;
-
-				/* copy file name */
-				while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
-					*efn++ = *sp++;
-				*efn = _T('\0');
-			}
-			else if (*sp == _T('&'))
-			{
-				/* output AND error redirection */
-				sp++;
-
-				if (*sp == _T('>'))
-				{
-					*lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION);
-					sp++;
-
-					/* append request ? */
-					if (*sp == _T('>'))
-					{
-						*lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
-						sp++;
-					}
-				}
-				else
-				{
-					/* no redirection!! copy the '&' character! */
-					sp--;
-					*dp++ = *sp++;
-					continue;
-				}
-
-				while (_istspace (*sp))
-					sp++;
-
-				/* copy file name */
-				while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
-					*ofn++ = *efn++ = *sp++;
-				*ofn = *efn = _T('\0');
-			}
+				ListPtr = &Redir->Next;
+			}
+
+			Redir = cmd_alloc(FIELD_OFFSET(REDIRECTION, Filename[fn - Filename]));
+			Redir->Next = NULL;
+			Redir->OldHandle = INVALID_HANDLE_VALUE;
+			Redir->Number = HandleNumber;
+			Redir->Type = Type;
+			_tcscpy(Redir->Filename, Filename);
+			*ListPtr = Redir;
 		}
 		else
 			*dp++ = *sp++;
@@ -276,4 +199,124 @@
 	return num;
 }
 
+/* cmd allows redirection of handles numbered 3-9 even though these don't
+ * correspond to any STD_ constant. */
+static HANDLE ExtraHandles[10 - 3];
+
+static HANDLE GetHandle(UINT Number)
+{
+	if (Number < 3)
+		return GetStdHandle(STD_INPUT_HANDLE - Number);
+	else
+		return ExtraHandles[Number - 3];
+}
+
+static VOID SetHandle(UINT Number, HANDLE Handle)
+{
+	if (Number < 3)
+		SetStdHandle(STD_INPUT_HANDLE - Number, Handle);
+	else
+		ExtraHandles[Number - 3] = Handle;
+}
+
+BOOL
+PerformRedirection(REDIRECTION *RedirList)
+{
+	REDIRECTION *Redir;
+	TCHAR Filename[MAX_PATH];
+	HANDLE hNew;
+	UINT DupNumber;
+	static SECURITY_ATTRIBUTES SecAttr = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+
+	/* Some parameters used for read, write, and append, respectively */
+	static const DWORD dwAccess[] = {
+		GENERIC_READ, 
+		GENERIC_WRITE,
+		GENERIC_WRITE
+	};
+	static const DWORD dwShareMode[] = {
+		FILE_SHARE_READ | FILE_SHARE_WRITE,
+		FILE_SHARE_READ,
+		FILE_SHARE_READ
+	};
+	static const DWORD dwCreationDisposition[] = {
+		OPEN_EXISTING,
+		CREATE_ALWAYS,
+		OPEN_ALWAYS
+	};
+
+	for (Redir = RedirList; Redir; Redir = Redir->Next)
+	{
+		*Filename = _T('\0');
+		_tcsncat(Filename, Redir->Filename, MAX_PATH - 1);
+		StripQuotes(Filename);
+
+		if (*Filename == _T('&'))
+		{
+			DupNumber = Filename[1] - _T('0');
+			if (DupNumber >= 10 ||
+			    !DuplicateHandle(GetCurrentProcess(),
+			                     GetHandle(DupNumber),
+			                     GetCurrentProcess(),
+			                     &hNew,
+			                     0,
+			                     TRUE,
+			                     DUPLICATE_SAME_ACCESS))
+			{
+				hNew = INVALID_HANDLE_VALUE;
+			}
+		}
+		else
+		{
+			hNew = CreateFile(Filename,
+			                  dwAccess[Redir->Type],
+			                  dwShareMode[Redir->Type],
+			                  &SecAttr,
+			                  dwCreationDisposition[Redir->Type],
+			                  0,
+			                  NULL);
+		}
+
+		if (hNew == INVALID_HANDLE_VALUE)
+		{
+			ConErrResPrintf(Redir->Type == REDIR_READ ? STRING_CMD_ERROR1 : STRING_CMD_ERROR3,
+			                Filename);
+			/* Undo all the redirections before this one */
+			UndoRedirection(RedirList, Redir);
+			return FALSE;
+		}
+
+		if (Redir->Type == REDIR_APPEND)
+			SetFilePointer(hNew, 0, NULL, FILE_END);
+		Redir->OldHandle = GetHandle(Redir->Number);
+		SetHandle(Redir->Number, hNew);
+
+		TRACE("%d redirected to: %s\n", Redir->Number, debugstr_aw(Filename));
+	}
+	return TRUE;
+}
+
+VOID
+UndoRedirection(REDIRECTION *Redir, REDIRECTION *End)
+{
+	for (; Redir != End; Redir = Redir->Next)
+	{
+		CloseHandle(GetHandle(Redir->Number));
+		SetHandle(Redir->Number, Redir->OldHandle);
+		Redir->OldHandle = INVALID_HANDLE_VALUE;
+	}
+}
+
+VOID
+FreeRedirection(REDIRECTION *Redir)
+{
+	REDIRECTION *Next;
+	for (; Redir; Redir = Next)
+	{
+		Next = Redir->Next;
+		ASSERT(Redir->OldHandle == INVALID_HANDLE_VALUE);
+		cmd_free(Redir);
+	}
+}
+
 #endif /* FEATURE_REDIRECTION */

Modified: trunk/reactos/base/shell/cmd/start.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/start.c?rev=35508&r1=35507&r2=35508&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/start.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/start.c [iso-8859-1] Thu Aug 21 10:33:59 2008
@@ -32,17 +32,6 @@
 	p[-1] = _T('\0');
 	*pPointer = p;
 	return start - 1;
-}
-
-static void StripQuotes(TCHAR *in)
-{
-	TCHAR *out = in;
-	for (; *in; in++)
-	{
-		if (*in != _T('"'))
-			*out++ = *in;
-	}
-	*out = _T('\0');
 }
 
 INT cmd_start (LPTSTR First, LPTSTR Rest)



More information about the Ros-diffs mailing list