1 /* 2 * REDIR.C - redirection handling. 3 * 4 * 5 * History: 6 * 7 * 12/15/95 (Tim Norman) 8 * started. 9 * 10 * 12 Jul 98 (Hans B Pufal) 11 * Rewrote to make more efficient and to conform to new command.c 12 * and batch.c processing. 13 * 14 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 15 * Added config.h include 16 * 17 * 22-Jan-1999 (Eric Kohl) 18 * Unicode safe! 19 * Added new error redirection "2>" and "2>>". 20 * 21 * 26-Jan-1999 (Eric Kohl) 22 * Added new error AND output redirection "&>" and "&>>". 23 * 24 * 24-Jun-2005 (Brandon Turner <turnerb7@msu.edu>) 25 * simple check to fix > and | bug with 'rem' 26 */ 27 28 #include "precomp.h" 29 30 #ifdef FEATURE_REDIRECTION 31 32 /* 33 * CMD allows redirection of handles numbered 3-9 even though 34 * these don't correspond to any STD_ constant. 35 */ 36 static const PCON_STREAM StdStreams[] = { StdIn, StdOut, StdErr }; 37 static HANDLE ExtraHandles[10 - 3]; // 3 == ARRAYSIZE(StdStreams) 38 39 HANDLE GetHandle(UINT Number) 40 { 41 if (Number < 3) 42 return ConStreamGetOSHandle(StdStreams[Number]); 43 // return GetStdHandle(STD_INPUT_HANDLE - Number); 44 else if (Number < ARRAYSIZE(ExtraHandles) + 3) 45 return ExtraHandles[Number - 3]; 46 else 47 return INVALID_HANDLE_VALUE; 48 } 49 50 VOID SetHandle(UINT Number, HANDLE Handle) 51 { 52 if (Number < 3) 53 { 54 ConStreamSetOSHandle(StdStreams[Number], Handle); 55 /* Synchronize the associated Win32 handle */ 56 SetStdHandle(STD_INPUT_HANDLE - Number, Handle); 57 } 58 else if (Number < ARRAYSIZE(ExtraHandles) + 3) 59 ExtraHandles[Number - 3] = Handle; 60 } 61 62 BOOL 63 PerformRedirection(REDIRECTION *RedirList) 64 { 65 REDIRECTION *Redir; 66 LPTSTR Filename; 67 HANDLE hNew; 68 UINT DupNumber; 69 70 static SECURITY_ATTRIBUTES SecAttr = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; 71 72 /* Some parameters used for read, write, and append, respectively */ 73 static struct REDIR_PARAMS 74 { 75 DWORD dwDesiredAccess; 76 DWORD dwShareMode; 77 DWORD dwCreationDisposition; 78 } RedirParams[] = 79 { 80 {GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING}, // REDIR_READ 81 {GENERIC_WRITE, FILE_SHARE_READ , CREATE_ALWAYS}, // REDIR_WRITE 82 {GENERIC_WRITE, FILE_SHARE_READ , OPEN_ALWAYS } // REDIR_APPEND 83 }; 84 85 for (Redir = RedirList; Redir; Redir = Redir->Next) 86 { 87 Filename = DoDelayedExpansion(Redir->Filename); 88 if (!Filename) 89 goto redir_error; 90 StripQuotes(Filename); 91 92 if (*Filename == _T('&')) 93 { 94 DupNumber = Filename[1] - _T('0'); 95 if (DupNumber >= 10 || 96 !DuplicateHandle(GetCurrentProcess(), 97 GetHandle(DupNumber), 98 GetCurrentProcess(), 99 &hNew, 100 0, 101 TRUE, 102 DUPLICATE_SAME_ACCESS)) 103 { 104 hNew = INVALID_HANDLE_VALUE; 105 } 106 } 107 else 108 { 109 hNew = CreateFile(Filename, 110 RedirParams[Redir->Mode].dwDesiredAccess, 111 RedirParams[Redir->Mode].dwShareMode, 112 &SecAttr, 113 RedirParams[Redir->Mode].dwCreationDisposition, 114 0, 115 NULL); 116 } 117 118 if (hNew == INVALID_HANDLE_VALUE) 119 { 120 /* TODO: Print a more detailed message */ 121 ConErrResPrintf(Redir->Mode == REDIR_READ ? STRING_CMD_ERROR1 : STRING_CMD_ERROR3, 122 Filename); 123 cmd_free(Filename); 124 redir_error: 125 /* Undo all the redirections before this one */ 126 UndoRedirection(RedirList, Redir); 127 return FALSE; 128 } 129 130 if (Redir->Mode == REDIR_APPEND) 131 SetFilePointer(hNew, 0, NULL, FILE_END); 132 Redir->OldHandle = GetHandle(Redir->Number); 133 SetHandle(Redir->Number, hNew); 134 135 TRACE("%d redirected to: %s\n", Redir->Number, debugstr_aw(Filename)); 136 cmd_free(Filename); 137 } 138 return TRUE; 139 } 140 141 VOID 142 UndoRedirection(REDIRECTION *Redir, REDIRECTION *End) 143 { 144 for (; Redir != End; Redir = Redir->Next) 145 { 146 CloseHandle(GetHandle(Redir->Number)); 147 SetHandle(Redir->Number, Redir->OldHandle); 148 Redir->OldHandle = INVALID_HANDLE_VALUE; 149 } 150 } 151 152 VOID 153 FreeRedirection(REDIRECTION *Redir) 154 { 155 REDIRECTION *Next; 156 for (; Redir; Redir = Next) 157 { 158 Next = Redir->Next; 159 ASSERT(Redir->OldHandle == INVALID_HANDLE_VALUE); 160 cmd_free(Redir); 161 } 162 } 163 164 #endif /* FEATURE_REDIRECTION */ 165