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…
==============================================================================
--- 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…
==============================================================================
--- 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=…
==============================================================================
--- 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=3…
==============================================================================
--- 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=3…
==============================================================================
--- 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=3…
==============================================================================
--- 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=…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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)