reactos/base/shell/cmd/redir.c

165 lines
4.7 KiB
C

/*
* 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 const PCON_STREAM StdStreams[] = { StdIn, StdOut, StdErr };
static HANDLE ExtraHandles[10 - 3]; // 3 == ARRAYSIZE(StdStreams)
HANDLE GetHandle(UINT Number)
{
if (Number < 3)
return ConStreamGetOSHandle(StdStreams[Number]);
// return GetStdHandle(STD_INPUT_HANDLE - Number);
else if (Number < ARRAYSIZE(ExtraHandles) + 3)
return ExtraHandles[Number - 3];
else
return INVALID_HANDLE_VALUE;
}
VOID SetHandle(UINT Number, HANDLE Handle)
{
if (Number < 3)
{
ConStreamSetOSHandle(StdStreams[Number], Handle);
/* Synchronize the associated Win32 handle */
SetStdHandle(STD_INPUT_HANDLE - Number, Handle);
}
else if (Number < ARRAYSIZE(ExtraHandles) + 3)
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 struct REDIR_PARAMS
{
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD dwCreationDisposition;
} RedirParams[] =
{
{GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING}, // REDIR_READ
{GENERIC_WRITE, FILE_SHARE_READ , CREATE_ALWAYS}, // REDIR_WRITE
{GENERIC_WRITE, FILE_SHARE_READ , OPEN_ALWAYS } // REDIR_APPEND
};
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,
RedirParams[Redir->Mode].dwDesiredAccess,
RedirParams[Redir->Mode].dwShareMode,
&SecAttr,
RedirParams[Redir->Mode].dwCreationDisposition,
0,
NULL);
}
if (hNew == INVALID_HANDLE_VALUE)
{
/* TODO: Print a more detailed message */
ConErrResPrintf(Redir->Mode == 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->Mode == 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 */