/* * 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 ) * 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 ) * 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 */