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 these don't 34 * correspond to any STD_ constant. */ 35 static HANDLE ExtraHandles[10 - 3]; 36 37 static HANDLE GetHandle(UINT Number) 38 { 39 if (Number < 3) 40 return GetStdHandle(STD_INPUT_HANDLE - Number); 41 else 42 return ExtraHandles[Number - 3]; 43 } 44 45 static VOID SetHandle(UINT Number, HANDLE Handle) 46 { 47 if (Number < 3) 48 SetStdHandle(STD_INPUT_HANDLE - Number, Handle); 49 else 50 ExtraHandles[Number - 3] = Handle; 51 } 52 53 BOOL 54 PerformRedirection(REDIRECTION *RedirList) 55 { 56 REDIRECTION *Redir; 57 LPTSTR Filename; 58 HANDLE hNew; 59 UINT DupNumber; 60 static SECURITY_ATTRIBUTES SecAttr = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; 61 62 /* Some parameters used for read, write, and append, respectively */ 63 static const DWORD dwAccess[] = { 64 GENERIC_READ, 65 GENERIC_WRITE, 66 GENERIC_WRITE 67 }; 68 static const DWORD dwShareMode[] = { 69 FILE_SHARE_READ | FILE_SHARE_WRITE, 70 FILE_SHARE_READ, 71 FILE_SHARE_READ 72 }; 73 static const DWORD dwCreationDisposition[] = { 74 OPEN_EXISTING, 75 CREATE_ALWAYS, 76 OPEN_ALWAYS 77 }; 78 79 for (Redir = RedirList; Redir; Redir = Redir->Next) 80 { 81 Filename = DoDelayedExpansion(Redir->Filename); 82 if (!Filename) 83 goto redir_error; 84 StripQuotes(Filename); 85 86 if (*Filename == _T('&')) 87 { 88 DupNumber = Filename[1] - _T('0'); 89 if (DupNumber >= 10 || 90 !DuplicateHandle(GetCurrentProcess(), 91 GetHandle(DupNumber), 92 GetCurrentProcess(), 93 &hNew, 94 0, 95 TRUE, 96 DUPLICATE_SAME_ACCESS)) 97 { 98 hNew = INVALID_HANDLE_VALUE; 99 } 100 } 101 else 102 { 103 hNew = CreateFile(Filename, 104 dwAccess[Redir->Type], 105 dwShareMode[Redir->Type], 106 &SecAttr, 107 dwCreationDisposition[Redir->Type], 108 0, 109 NULL); 110 } 111 112 if (hNew == INVALID_HANDLE_VALUE) 113 { 114 ConErrResPrintf(Redir->Type == REDIR_READ ? STRING_CMD_ERROR1 : STRING_CMD_ERROR3, 115 Filename); 116 cmd_free(Filename); 117 redir_error: 118 /* Undo all the redirections before this one */ 119 UndoRedirection(RedirList, Redir); 120 return FALSE; 121 } 122 123 if (Redir->Type == REDIR_APPEND) 124 SetFilePointer(hNew, 0, NULL, FILE_END); 125 Redir->OldHandle = GetHandle(Redir->Number); 126 SetHandle(Redir->Number, hNew); 127 128 TRACE("%d redirected to: %s\n", Redir->Number, debugstr_aw(Filename)); 129 cmd_free(Filename); 130 } 131 return TRUE; 132 } 133 134 VOID 135 UndoRedirection(REDIRECTION *Redir, REDIRECTION *End) 136 { 137 for (; Redir != End; Redir = Redir->Next) 138 { 139 CloseHandle(GetHandle(Redir->Number)); 140 SetHandle(Redir->Number, Redir->OldHandle); 141 Redir->OldHandle = INVALID_HANDLE_VALUE; 142 } 143 } 144 145 VOID 146 FreeRedirection(REDIRECTION *Redir) 147 { 148 REDIRECTION *Next; 149 for (; Redir; Redir = Next) 150 { 151 Next = Redir->Next; 152 ASSERT(Redir->OldHandle == INVALID_HANDLE_VALUE); 153 cmd_free(Redir); 154 } 155 } 156 157 #endif /* FEATURE_REDIRECTION */ 158