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
GetHandle(UINT Number)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
SetHandle(UINT Number,HANDLE Handle)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
PerformRedirection(REDIRECTION * RedirList)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
UndoRedirection(REDIRECTION * Redir,REDIRECTION * End)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
FreeRedirection(REDIRECTION * Redir)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