mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:42:57 +00:00
- 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:
parent
4af7567008
commit
07912f2b23
9 changed files with 221 additions and 363 deletions
|
@ -194,6 +194,9 @@ VOID ExitBatch (LPTSTR msg)
|
||||||
if (bc->ffind)
|
if (bc->ffind)
|
||||||
cmd_free(bc->ffind);
|
cmd_free(bc->ffind);
|
||||||
|
|
||||||
|
UndoRedirection(bc->RedirList, NULL);
|
||||||
|
FreeRedirection(bc->RedirList);
|
||||||
|
|
||||||
/* Preserve echo state across batch calls */
|
/* Preserve echo state across batch calls */
|
||||||
bEcho = bc->bEcho;
|
bEcho = bc->bEcho;
|
||||||
|
|
||||||
|
@ -248,9 +251,7 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
|
||||||
|
|
||||||
n->prev = bc;
|
n->prev = bc;
|
||||||
bc = n;
|
bc = n;
|
||||||
bc->In[0] = _T('\0');
|
bc->RedirList = NULL;
|
||||||
bc->Out[0] = _T('\0');
|
|
||||||
bc->Err[0] = _T('\0');
|
|
||||||
}
|
}
|
||||||
else if (bc->hBatchFile != INVALID_HANDLE_VALUE)
|
else if (bc->hBatchFile != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +264,7 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
|
||||||
cmd_free (bc->raw_params);
|
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';
|
*tmp = '\0';
|
||||||
|
|
||||||
bc->hBatchFile = hFile;
|
bc->hBatchFile = hFile;
|
||||||
|
@ -300,17 +301,23 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID AddBatchRedirection(TCHAR * ifn, TCHAR * ofn, TCHAR * efn)
|
VOID AddBatchRedirection(REDIRECTION **RedirList)
|
||||||
{
|
{
|
||||||
|
REDIRECTION **ListEnd;
|
||||||
|
|
||||||
if(!bc)
|
if(!bc)
|
||||||
return;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -19,9 +19,7 @@ typedef struct tagBATCHCONTEXT
|
||||||
INT shiftlevel;
|
INT shiftlevel;
|
||||||
BOOL bEcho; /* Preserve echo flag across batch calls */
|
BOOL bEcho; /* Preserve echo flag across batch calls */
|
||||||
HANDLE hFind; /* Preserve find handle when doing a for */
|
HANDLE hFind; /* Preserve find handle when doing a for */
|
||||||
TCHAR In[MAX_PATH];
|
REDIRECTION *RedirList;
|
||||||
TCHAR Out[MAX_PATH];
|
|
||||||
TCHAR Err[MAX_PATH];
|
|
||||||
TCHAR forvar;
|
TCHAR forvar;
|
||||||
INT bCmdBlock;
|
INT bCmdBlock;
|
||||||
BOOL bExecuteBlock[MAX_PATH];
|
BOOL bExecuteBlock[MAX_PATH];
|
||||||
|
@ -47,6 +45,6 @@ LPTSTR BatchParams (LPTSTR, LPTSTR);
|
||||||
VOID ExitBatch (LPTSTR);
|
VOID ExitBatch (LPTSTR);
|
||||||
BOOL Batch (LPTSTR, LPTSTR, LPTSTR);
|
BOOL Batch (LPTSTR, LPTSTR, LPTSTR);
|
||||||
LPTSTR ReadBatchLine (LPBOOL);
|
LPTSTR ReadBatchLine (LPBOOL);
|
||||||
VOID AddBatchRedirection(TCHAR *, TCHAR *, TCHAR *);
|
VOID AddBatchRedirection(REDIRECTION **);
|
||||||
|
|
||||||
#endif /* _BATCH_H_INCLUDED_ */
|
#endif /* _BATCH_H_INCLUDED_ */
|
||||||
|
|
|
@ -76,19 +76,8 @@ INT cmd_call (LPTSTR cmd, LPTSTR param)
|
||||||
bc->shiftlevel = 0;
|
bc->shiftlevel = 0;
|
||||||
bc->forvar = 0; /* HBP004 */
|
bc->forvar = 0; /* HBP004 */
|
||||||
bc->forproto = NULL; /* HBP004 */
|
bc->forproto = NULL; /* HBP004 */
|
||||||
|
bc->RedirList = NULL;
|
||||||
ParseCommandLine (param);
|
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 */
|
/* Wasn't a batch file so remove conext */
|
||||||
|
|
|
@ -690,21 +690,16 @@ VOID ParseCommandLine (LPTSTR cmd)
|
||||||
TCHAR cmdline[CMDLINE_LENGTH];
|
TCHAR cmdline[CMDLINE_LENGTH];
|
||||||
LPTSTR s;
|
LPTSTR s;
|
||||||
#ifdef FEATURE_REDIRECTION
|
#ifdef FEATURE_REDIRECTION
|
||||||
TCHAR in[CMDLINE_LENGTH] = _T("");
|
REDIRECTION *RedirList = NULL;
|
||||||
TCHAR out[CMDLINE_LENGTH] = _T("");
|
|
||||||
TCHAR err[CMDLINE_LENGTH] = _T("");
|
|
||||||
TCHAR szTempPath[MAX_PATH] = _T(".\\");
|
TCHAR szTempPath[MAX_PATH] = _T(".\\");
|
||||||
TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
|
TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
|
||||||
HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
|
HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
|
||||||
LPTSTR t = NULL;
|
|
||||||
INT num = 0;
|
INT num = 0;
|
||||||
INT nRedirFlags = 0;
|
|
||||||
INT Length;
|
INT Length;
|
||||||
UINT Attributes;
|
UINT Attributes;
|
||||||
BOOL bNewBatch = TRUE;
|
BOOL bNewBatch = TRUE;
|
||||||
HANDLE hOldConIn;
|
HANDLE hOldConIn;
|
||||||
HANDLE hOldConOut;
|
HANDLE hOldConOut;
|
||||||
HANDLE hOldConErr;
|
|
||||||
#endif /* FEATURE_REDIRECTION */
|
#endif /* FEATURE_REDIRECTION */
|
||||||
|
|
||||||
_tcscpy (cmdline, cmd);
|
_tcscpy (cmdline, cmd);
|
||||||
|
@ -732,65 +727,18 @@ VOID ParseCommandLine (LPTSTR cmd)
|
||||||
_tcscat (szTempPath, _T("\\"));
|
_tcscat (szTempPath, _T("\\"));
|
||||||
|
|
||||||
/* get the redirections from the command line */
|
/* 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? */
|
if (!PerformRedirection(RedirList))
|
||||||
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;
|
FreeRedirection(RedirList);
|
||||||
_tcscpy(out, bc->Out);
|
return;
|
||||||
}
|
|
||||||
if(bc && !_tcslen (err) && _tcslen (bc->Err))
|
|
||||||
{
|
|
||||||
nRedirFlags |= ERROR_APPEND;
|
|
||||||
_tcscpy(err, bc->Err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the initial conditions ... */
|
/* Set up the initial conditions ... */
|
||||||
/* preserve STDIN, STDOUT and STDERR handles */
|
/* preserve STDIN and STDOUT handles */
|
||||||
hOldConIn = GetStdHandle (STD_INPUT_HANDLE);
|
hOldConIn = GetStdHandle (STD_INPUT_HANDLE);
|
||||||
hOldConOut = GetStdHandle (STD_OUTPUT_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 */
|
/* Now do all but the last pipe command */
|
||||||
*szFileName[0] = _T('\0');
|
*szFileName[0] = _T('\0');
|
||||||
|
@ -855,123 +803,7 @@ VOID ParseCommandLine (LPTSTR cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now set up the end conditions... */
|
/* Now set up the end conditions... */
|
||||||
/* redirect STDOUT */
|
SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
|
||||||
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)
|
if(bc)
|
||||||
bNewBatch = FALSE;
|
bNewBatch = FALSE;
|
||||||
|
@ -982,7 +814,7 @@ VOID ParseCommandLine (LPTSTR cmd)
|
||||||
|
|
||||||
#ifdef FEATURE_REDIRECTION
|
#ifdef FEATURE_REDIRECTION
|
||||||
if(bNewBatch && bc)
|
if(bNewBatch && bc)
|
||||||
AddBatchRedirection(in, out, err);
|
AddBatchRedirection(&RedirList);
|
||||||
/* close old stdin file */
|
/* close old stdin file */
|
||||||
#if 0 /* buggy implementation */
|
#if 0 /* buggy implementation */
|
||||||
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
|
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
|
||||||
|
@ -1039,26 +871,8 @@ VOID ParseCommandLine (LPTSTR cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UndoRedirection(RedirList, NULL);
|
||||||
/* Restore original STDOUT */
|
FreeRedirection(RedirList);
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif /* FEATURE_REDIRECTION */
|
#endif /* FEATURE_REDIRECTION */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,7 @@ BOOL add_entry (LPINT ac, LPTSTR **arg, LPCTSTR entry);
|
||||||
LPTSTR *split (LPTSTR, LPINT, BOOL);
|
LPTSTR *split (LPTSTR, LPINT, BOOL);
|
||||||
VOID freep (LPTSTR *);
|
VOID freep (LPTSTR *);
|
||||||
LPTSTR _stpcpy (LPTSTR, LPCTSTR);
|
LPTSTR _stpcpy (LPTSTR, LPCTSTR);
|
||||||
|
VOID StripQuotes(LPTSTR);
|
||||||
BOOL IsValidPathName (LPCTSTR);
|
BOOL IsValidPathName (LPCTSTR);
|
||||||
BOOL IsExistingFile (LPCTSTR);
|
BOOL IsExistingFile (LPCTSTR);
|
||||||
BOOL IsExistingDirectory (LPCTSTR);
|
BOOL IsExistingDirectory (LPCTSTR);
|
||||||
|
@ -335,12 +336,19 @@ INT cmd_prompt (LPTSTR, LPTSTR);
|
||||||
|
|
||||||
|
|
||||||
/* Prototypes for REDIR.C */
|
/* Prototypes for REDIR.C */
|
||||||
#define INPUT_REDIRECTION 1
|
enum { REDIR_READ, REDIR_WRITE, REDIR_APPEND };
|
||||||
#define OUTPUT_REDIRECTION 2
|
typedef struct _REDIRECTION
|
||||||
#define OUTPUT_APPEND 4
|
{
|
||||||
#define ERROR_REDIRECTION 8
|
struct _REDIRECTION *Next;
|
||||||
#define ERROR_APPEND 16
|
HANDLE OldHandle;
|
||||||
INT GetRedirection (LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPINT);
|
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 */
|
/* Prototypes for REN.C */
|
||||||
|
|
|
@ -138,9 +138,7 @@ INT cmd_for (LPTSTR cmd, LPTSTR param)
|
||||||
bc->bEcho = bc->prev->bEcho;
|
bc->bEcho = bc->prev->bEcho;
|
||||||
else
|
else
|
||||||
bc->bEcho = bEcho;
|
bc->bEcho = bEcho;
|
||||||
bc->In[0] = _T('\0');
|
bc->RedirList = NULL;
|
||||||
bc->Out[0] = _T('\0');
|
|
||||||
bc->Err[0] = _T('\0');
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -411,6 +411,18 @@ LPTSTR _stpcpy (LPTSTR dest, LPCTSTR src)
|
||||||
return (dest + _tcslen (src));
|
return (dest + _tcslen (src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
StripQuotes(TCHAR *in)
|
||||||
|
{
|
||||||
|
TCHAR *out = in;
|
||||||
|
for (; *in; in++)
|
||||||
|
{
|
||||||
|
if (*in != _T('"'))
|
||||||
|
*out++ = *in;
|
||||||
|
}
|
||||||
|
*out = _T('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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;
|
INT num = 1;
|
||||||
LPTSTR dp = s;
|
LPTSTR dp = s;
|
||||||
LPTSTR sp = s;
|
LPTSTR sp = s;
|
||||||
|
TCHAR Filename[MAX_PATH];
|
||||||
|
|
||||||
#ifdef INCLUDE_CMD_REM
|
#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*/
|
/*first thing first. check to see if this is "rem" and hope out*/
|
||||||
if(!_tcsncmp (line, _T("rem "), 4))
|
if(!_tcsncmp (line, _T("rem "), 4))
|
||||||
{
|
{
|
||||||
lpnFlags = 0;
|
|
||||||
*ifn=('\0');
|
|
||||||
*ofn=('\0');
|
|
||||||
*efn=_T('\0');
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,148 +91,74 @@ INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags
|
||||||
while (*sp && *sp != qc);
|
while (*sp && *sp != qc);
|
||||||
|
|
||||||
*dp++ = *sp++;
|
*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 */
|
BYTE HandleNumber;
|
||||||
/* redirection, so we'll emulate that and not check */
|
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('<'))
|
if (*sp == _T('<'))
|
||||||
{
|
{
|
||||||
/* input redirection */
|
/* input redirection */
|
||||||
*lpnFlags |= INPUT_REDIRECTION;
|
Type = REDIR_READ;
|
||||||
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;
|
|
||||||
sp++;
|
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
|
else
|
||||||
{
|
{
|
||||||
/* no redirection!! copy the '1' character! */
|
/* output redirection */
|
||||||
sp--;
|
Type = REDIR_WRITE;
|
||||||
*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;
|
|
||||||
sp++;
|
sp++;
|
||||||
|
|
||||||
/* append request ? */
|
/* append request ? */
|
||||||
if (*sp == _T('>'))
|
if (*sp == _T('>'))
|
||||||
{
|
{
|
||||||
*lpnFlags |= ERROR_APPEND;
|
Type = REDIR_APPEND;
|
||||||
sp++;
|
sp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no redirection!! copy the '2' character! */
|
|
||||||
sp--;
|
|
||||||
*dp++ = *sp++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (_istspace (*sp))
|
while (_istspace(*sp))
|
||||||
sp++;
|
sp++;
|
||||||
|
|
||||||
/* copy file name */
|
/* copy file name */
|
||||||
while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
|
while (*sp && (bInQuote || (!IsRedirection (*sp) && !_istspace (*sp))))
|
||||||
*efn++ = *sp++;
|
|
||||||
*efn = _T('\0');
|
|
||||||
}
|
|
||||||
else if (*sp == _T('&'))
|
|
||||||
{
|
{
|
||||||
/* output AND error redirection */
|
bInQuote ^= (*sp == _T('"'));
|
||||||
sp++;
|
*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);
|
if (Redir->Number == HandleNumber)
|
||||||
sp++;
|
|
||||||
|
|
||||||
/* append request ? */
|
|
||||||
if (*sp == _T('>'))
|
|
||||||
{
|
{
|
||||||
*lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
|
*ListPtr = Redir->Next;
|
||||||
sp++;
|
cmd_free(Redir);
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no redirection!! copy the '&' character! */
|
|
||||||
sp--;
|
|
||||||
*dp++ = *sp++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ListPtr = &Redir->Next;
|
||||||
while (_istspace (*sp))
|
|
||||||
sp++;
|
|
||||||
|
|
||||||
/* copy file name */
|
|
||||||
while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
|
|
||||||
*ofn++ = *efn++ = *sp++;
|
|
||||||
*ofn = *efn = _T('\0');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
else
|
||||||
*dp++ = *sp++;
|
*dp++ = *sp++;
|
||||||
|
@ -276,4 +199,124 @@ INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags
|
||||||
return num;
|
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 */
|
#endif /* FEATURE_REDIRECTION */
|
||||||
|
|
|
@ -34,17 +34,6 @@ static TCHAR *GetParameter(TCHAR **pPointer)
|
||||||
return start - 1;
|
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)
|
INT cmd_start (LPTSTR First, LPTSTR Rest)
|
||||||
{
|
{
|
||||||
TCHAR szFullName[CMDLINE_LENGTH];
|
TCHAR szFullName[CMDLINE_LENGTH];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue