Implement escape char in console. "^"
[reactos.git] / reactos / subsys / system / 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 <ekohl@abo.rhein-zeitung.de>)
18 * Unicode safe!
19 * Added new error redirection "2>" and "2>>".
20 *
21 * 26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
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 static BOOL
34 IsRedirection (TCHAR c)
35 {
36 return (c == _T('<')) || (c == _T('>')) || (c == _T('|'));
37 }
38
39
40 /*
41 * Gets the redirection info from the command line and copies the
42 * file names into ifn, ofn and efn removing them from the command
43 * line.
44 *
45 * Converts remaining command line into a series of null terminated
46 * strings defined by the pipe char '|'. Each string corresponds
47 * to a single executable command. A double null terminates the
48 * command strings.
49 *
50 * Return number of command strings found.
51 *
52 */
53
54 INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags)
55 {
56 INT num = 1;
57 LPTSTR dp = s;
58 LPTSTR sp = s;
59
60 #ifdef INCLUDE_CMD_REM
61
62 TCHAR * line = s;
63
64
65 while (_istspace (*line))
66 line++;
67
68 /*first thing first. check to see if this is "rem" and hope out*/
69 if(!_tcsncmp (line, _T("rem "), 4))
70 {
71 lpnFlags = 0;
72 *ifn=('\0');
73 *ofn=('\0');
74 *efn=_T('\0');
75 return 1;
76 }
77 #endif
78 /* find and remove all the redirections first */
79 while (*sp)
80 {
81 if (*sp == _T('^'))
82 {
83 *dp++ = *sp++;
84 *dp++ = *sp++;
85 continue;
86 }
87 if ((*sp == _T('"')) || (*sp == _T('\'')))
88 {
89 /* No redirects inside quotes */
90 TCHAR qc = *sp;
91
92 do
93 *dp++ = *sp++;
94 while (*sp && *sp != qc);
95
96 *dp++ = *sp++;
97 }
98 else if ((*sp == _T('<')) || (*sp == _T('>')) ||
99 (*sp == _T('1')) || (*sp == _T('2')) || (*sp == _T('&')))
100 {
101 /* MS-DOS ignores multiple redirection symbols and uses the last */
102 /* redirection, so we'll emulate that and not check */
103
104 if (*sp == _T('<'))
105 {
106 /* input redirection */
107 *lpnFlags |= INPUT_REDIRECTION;
108 do sp++;
109 while( _istspace (*sp) );
110
111 /* copy file name */
112 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
113 *ifn++ = *sp++;
114 *ifn = _T('\0');
115 }
116 else if (*sp == _T('>'))
117 {
118 /* output redirection */
119 *lpnFlags |= OUTPUT_REDIRECTION;
120 sp++;
121
122 /* append request ? */
123 if (*sp == _T('>'))
124 {
125 *lpnFlags |= OUTPUT_APPEND;
126 sp++;
127 }
128
129 while (_istspace (*sp))
130 sp++;
131
132 /* copy file name */
133 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
134 *ofn++ = *sp++;
135 *ofn = _T('\0');
136 }
137
138 else if (*sp == _T('1'))
139 {
140 /* output redirection */
141 sp++;
142
143 if (*sp == _T('>'))
144 {
145 /* output redirection */
146 *lpnFlags |= OUTPUT_REDIRECTION;
147 sp++;
148
149 /* append request ? */
150 if (*sp == _T('>'))
151 {
152 *lpnFlags |= OUTPUT_APPEND;
153 sp++;
154 }
155 }
156 else
157 {
158 /* no redirection!! copy the '1' character! */
159 sp--;
160 *dp++ = *sp++;
161 continue;
162 }
163
164 while (_istspace (*sp))
165 sp++;
166
167 /* copy file name */
168 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
169 *ofn++ = *sp++;
170 *ofn = _T('\0');
171 }
172
173 else if (*sp == _T('2'))
174 {
175 /* error redirection */
176 sp++;
177
178 if (*sp == _T('>'))
179 {
180 *lpnFlags |= ERROR_REDIRECTION;
181 sp++;
182
183 /* append request ? */
184 if (*sp == _T('>'))
185 {
186 *lpnFlags |= ERROR_APPEND;
187 sp++;
188 }
189 }
190 else
191 {
192 /* no redirection!! copy the '2' character! */
193 sp--;
194 *dp++ = *sp++;
195 continue;
196 }
197
198 while (_istspace (*sp))
199 sp++;
200
201 /* copy file name */
202 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
203 *efn++ = *sp++;
204 *efn = _T('\0');
205 }
206 else if (*sp == _T('&'))
207 {
208 /* output AND error redirection */
209 sp++;
210
211 if (*sp == _T('>'))
212 {
213 *lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION);
214 sp++;
215
216 /* append request ? */
217 if (*sp == _T('>'))
218 {
219 *lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
220 sp++;
221 }
222 }
223 else
224 {
225 /* no redirection!! copy the '&' character! */
226 sp--;
227 *dp++ = *sp++;
228 continue;
229 }
230
231 while (_istspace (*sp))
232 sp++;
233
234 /* copy file name */
235 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
236 *ofn++ = *efn++ = *sp++;
237 *ofn = *efn = _T('\0');
238 }
239 }
240 else
241 *dp++ = *sp++;
242 }
243
244 *dp++ = _T('\0');
245 *dp = _T('\0');
246
247 /* now go for the pipes */
248 sp = s;
249 while (*sp)
250 {
251 if (*sp == _T('^'))
252 {
253 *sp++;
254 *sp++;
255 continue;
256 }
257 else if ((*sp == _T('"')) || (*sp == _T('\'')))
258 {
259 TCHAR qc = *sp;
260
261 do
262 sp++;
263 while (*sp && *sp != qc);
264
265 sp++;
266 }
267 else if (*sp == _T('|'))
268 {
269 *sp++ = _T('\0');
270 num++;
271 }
272 else
273 sp++;
274 }
275
276 return num;
277 }
278
279 #endif /* FEATURE_REDIRECTION */