- 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)

svn path=/trunk/; revision=35508
This commit is contained in:
Jeffrey Morlan 2008-08-21 15:33:59 +00:00
parent 4af7567008
commit 07912f2b23
9 changed files with 221 additions and 363 deletions

View file

@ -194,6 +194,9 @@ VOID ExitBatch (LPTSTR msg)
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 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
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 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
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 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
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;
}
/*

View file

@ -19,9 +19,7 @@ typedef struct tagBATCHCONTEXT
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 @@ LPTSTR BatchParams (LPTSTR, LPTSTR);
VOID ExitBatch (LPTSTR);
BOOL Batch (LPTSTR, LPTSTR, LPTSTR);
LPTSTR ReadBatchLine (LPBOOL);
VOID AddBatchRedirection(TCHAR *, TCHAR *, TCHAR *);
VOID AddBatchRedirection(REDIRECTION **);
#endif /* _BATCH_H_INCLUDED_ */

View file

@ -76,19 +76,8 @@ INT cmd_call (LPTSTR cmd, LPTSTR param)
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 */

View file

@ -690,21 +690,16 @@ VOID ParseCommandLine (LPTSTR cmd)
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 @@ VOID ParseCommandLine (LPTSTR cmd)
_tcscat (szTempPath, _T("\\"));
/* get the redirections from the command line */
num = GetRedirection (s, in, out, err, &nRedirFlags);
num = GetRedirection (s, &RedirList);
/* 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))
if (!PerformRedirection(RedirList))
{
nRedirFlags |= OUTPUT_APPEND;
_tcscpy(out, bc->Out);
}
if(bc && !_tcslen (err) && _tcslen (bc->Err))
{
nRedirFlags |= ERROR_APPEND;
_tcscpy(err, bc->Err);
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 @@ VOID ParseCommandLine (LPTSTR cmd)
}
/* 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;
}
if(bc)
bNewBatch = FALSE;
@ -982,7 +814,7 @@ VOID ParseCommandLine (LPTSTR cmd)
#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 @@ VOID ParseCommandLine (LPTSTR cmd)
}
}
/* 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 */
}

View file

@ -301,6 +301,7 @@ BOOL add_entry (LPINT ac, LPTSTR **arg, LPCTSTR entry);
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 @@ INT cmd_prompt (LPTSTR, LPTSTR);
/* 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 */

View file

@ -138,9 +138,7 @@ INT cmd_for (LPTSTR cmd, LPTSTR param)
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;

View file

@ -411,6 +411,18 @@ LPTSTR _stpcpy (LPTSTR dest, LPCTSTR src)
return (dest + _tcslen (src));
}
VOID
StripQuotes(TCHAR *in)
{
TCHAR *out = in;
for (; *in; in++)
{
if (*in != _T('"'))
*out++ = *in;
}
*out = _T('\0');
}
/*

View file

@ -51,11 +51,12 @@ IsRedirection (TCHAR c)
*
*/
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 @@ INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags
/*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 @@ INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags
while (*sp && *sp != qc);
*dp++ = *sp++;
continue;
}
else if ((*sp == _T('<')) || (*sp == _T('>')) ||
(*sp == _T('1')) || (*sp == _T('2')) || (*sp == _T('&')))
int NumberGiven = (*sp >= _T('0') && *sp <= _T('9')) ? 1 : 0;
if (sp[NumberGiven] == _T('<') || sp[NumberGiven] == _T('>'))
{
/* MS-DOS ignores multiple redirection symbols and uses the last */
/* redirection, so we'll emulate that and not check */
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('>'))
{
/* output redirection */
*lpnFlags |= OUTPUT_REDIRECTION;
Type = REDIR_READ;
sp++;
/* append request ? */
if (*sp == _T('>'))
{
*lpnFlags |= OUTPUT_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 */
sp++;
if (*sp == _T('>'))
{
/* 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++;
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;
/* output redirection */
Type = REDIR_WRITE;
sp++;
/* append request ? */
if (*sp == _T('>'))
{
*lpnFlags |= ERROR_APPEND;
Type = REDIR_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('&'))
while (*sp && (bInQuote || (!IsRedirection (*sp) && !_istspace (*sp))))
{
/* output AND error redirection */
sp++;
bInQuote ^= (*sp == _T('"'));
*fn++ = *sp++;
}
*fn++ = _T('\0');
if (*sp == _T('>'))
/* Delete any existing redirection for the same handle number */
ListPtr = RedirList;
while ((Redir = *ListPtr))
{
*lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION);
sp++;
/* append request ? */
if (*sp == _T('>'))
if (Redir->Number == HandleNumber)
{
*lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
sp++;
}
}
else
{
/* no redirection!! copy the '&' 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++ = *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 @@ INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags
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 */

View file

@ -34,17 +34,6 @@ static TCHAR *GetParameter(TCHAR **pPointer)
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)
{
TCHAR szFullName[CMDLINE_LENGTH];