[MMEBUDDY]
[reactos.git] / reactos / base / shell / cmd / redir.c
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 */