mirror of
https://github.com/reactos/reactos.git
synced 2024-08-24 20:28:57 +00:00
165 lines
4.7 KiB
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 */
|