reactos/base/shell/cmd/redir.c

158 lines
3.6 KiB
C
Raw Normal View History

/*
* 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
*
* 22-Jan-1999 (Eric Kohl)
* Unicode safe!
* Added new error redirection "2>" and "2>>".
*
* 26-Jan-1999 (Eric Kohl)
* 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
/* 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;
LPTSTR Filename;
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 = DoDelayedExpansion(Redir->Filename);
if (!Filename)
goto redir_error;
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);
cmd_free(Filename);
redir_error:
/* 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));
cmd_free(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 */