2006-02-16 23:23:37 +00:00
|
|
|
/*
|
|
|
|
* REDIR.C - redirection handling.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* History:
|
|
|
|
*
|
|
|
|
* 12/15/95 (Tim Norman)
|
|
|
|
* started.
|
|
|
|
*
|
|
|
|
* 12 Jul 98 (Hans B Pufal)
|
|
|
|
* Rewrote to make more efficient and to conform to new command.c
|
|
|
|
* and batch.c processing.
|
|
|
|
*
|
|
|
|
* 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
|
|
|
|
* Added config.h include
|
|
|
|
*
|
2007-05-05 11:32:25 +00:00
|
|
|
* 22-Jan-1999 (Eric Kohl)
|
2006-02-16 23:23:37 +00:00
|
|
|
* Unicode safe!
|
|
|
|
* Added new error redirection "2>" and "2>>".
|
|
|
|
*
|
2007-05-05 11:32:25 +00:00
|
|
|
* 26-Jan-1999 (Eric Kohl)
|
2006-02-16 23:23:37 +00:00
|
|
|
* Added new error AND output redirection "&>" and "&>>".
|
|
|
|
*
|
|
|
|
* 24-Jun-2005 (Brandon Turner <turnerb7@msu.edu>)
|
|
|
|
* simple check to fix > and | bug with 'rem'
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <precomp.h>
|
|
|
|
|
|
|
|
#ifdef FEATURE_REDIRECTION
|
|
|
|
|
|
|
|
|
2008-08-21 15:33:59 +00:00
|
|
|
/* 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;
|
2009-02-14 01:13:17 +00:00
|
|
|
LPTSTR Filename;
|
2008-08-21 15:33:59 +00:00
|
|
|
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)
|
|
|
|
{
|
2009-02-14 01:13:17 +00:00
|
|
|
Filename = DoDelayedExpansion(Redir->Filename);
|
|
|
|
if (!Filename)
|
|
|
|
goto redir_error;
|
2008-08-21 15:33:59 +00:00
|
|
|
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);
|
2009-02-14 01:13:17 +00:00
|
|
|
cmd_free(Filename);
|
|
|
|
redir_error:
|
2008-08-21 15:33:59 +00:00
|
|
|
/* 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));
|
2009-02-14 01:13:17 +00:00
|
|
|
cmd_free(Filename);
|
2008-08-21 15:33:59 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-16 23:23:37 +00:00
|
|
|
#endif /* FEATURE_REDIRECTION */
|