Added Eric Kohl's port of freedos command
[reactos.git] / reactos / apps / utils / 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
25 #define WIN32_LEAN_AND_MEAN
26
27 #include "config.h"
28
29 #ifdef FEATURE_REDIRECTION
30
31 #include <windows.h>
32 #include <tchar.h>
33 #include <string.h>
34 #include <ctype.h>
35
36 #include "cmd.h"
37
38
39 static BOOL
40 IsRedirection (TCHAR c)
41 {
42 return (c == _T('<')) || (c == _T('>')) || (c == _T('|'));
43 }
44
45
46 /*
47 * Gets the redirection info from the command line and copies the
48 * file names into ifn, ofn and efn removing them from the command
49 * line.
50 *
51 * Converts remaining command line into a series of null terminated
52 * strings defined by the pipe char '|'. Each string corresponds
53 * to a single executable command. A double null terminates the
54 * command strings.
55 *
56 * Return number of command strings found.
57 *
58 */
59
60 INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags)
61 {
62 INT num = 1;
63 LPTSTR dp = s;
64 LPTSTR sp = s;
65
66 /* find and remove all the redirections first */
67 while (*sp)
68 {
69 if ((*sp == _T('"')) || (*sp == _T('\'')))
70 {
71 /* No redirects inside quotes */
72 TCHAR qc = *sp;
73
74 do
75 *dp++ = *sp++;
76 while (*sp != qc);
77
78 *dp++ = *sp++;
79 }
80 else if ((*sp == _T('<')) || (*sp == _T('>')) ||
81 (*sp == _T('2')) || (*sp == _T('&')))
82 {
83 /* MS-DOS ignores multiple redirection symbols and uses the last */
84 /* redirection, so we'll emulate that and not check */
85
86 if (*sp == _T('<'))
87 {
88 /* input redirection */
89 *lpnFlags |= INPUT_REDIRECTION;
90 while (_istspace (*sp))
91 sp++;
92
93 /* copy file name */
94 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
95 *ifn++ = *sp++;
96 *ifn = _T('\0');
97 }
98 else if (*sp == _T('>'))
99 {
100 /* output redirection */
101 *lpnFlags |= OUTPUT_REDIRECTION;
102 sp++;
103
104 /* append request ? */
105 if (*sp == _T('>'))
106 {
107 *lpnFlags |= OUTPUT_APPEND;
108 sp++;
109 }
110
111 while (_istspace (*sp))
112 sp++;
113
114 /* copy file name */
115 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
116 *ofn++ = *sp++;
117 *ofn = _T('\0');
118 }
119 else if (*sp == _T('2'))
120 {
121 /* error redirection */
122 sp++;
123
124 if (*sp == _T('>'))
125 {
126 *lpnFlags |= ERROR_REDIRECTION;
127 sp++;
128
129 /* append request ? */
130 if (*sp == _T('>'))
131 {
132 *lpnFlags |= ERROR_APPEND;
133 sp++;
134 }
135 }
136 else
137 {
138 /* no redirection!! copy the '2' character! */
139 sp--;
140 *dp++ = *sp++;
141 continue;
142 }
143
144 while (_istspace (*sp))
145 sp++;
146
147 /* copy file name */
148 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
149 *efn++ = *sp++;
150 *efn = _T('\0');
151 }
152 else if (*sp == _T('&'))
153 {
154 /* output AND error redirection */
155 sp++;
156
157 if (*sp == _T('>'))
158 {
159 *lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION);
160 sp++;
161
162 /* append request ? */
163 if (*sp == _T('>'))
164 {
165 *lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
166 sp++;
167 }
168 }
169 else
170 {
171 /* no redirection!! copy the '&' character! */
172 sp--;
173 *dp++ = *sp++;
174 continue;
175 }
176
177 while (_istspace (*sp))
178 sp++;
179
180 /* copy file name */
181 while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
182 *ofn++ = *efn++ = *sp++;
183 *ofn = *efn = _T('\0');
184 }
185 }
186 else
187 *dp++ = *sp++;
188 }
189 *dp++ = _T('\0');
190 *dp = _T('\0');
191
192 /* now go for the pipes */
193 sp = s;
194 while (*sp)
195 {
196 if ((*sp == _T('"')) || (*sp == _T('\'')))
197 {
198 TCHAR qc = *sp;
199
200 do
201 sp++;
202 while (*sp != qc);
203
204 sp++;
205 }
206 else if (*sp == _T('|'))
207 {
208 *sp++ = '\0';
209 num++;
210 }
211 else
212 sp++;
213 }
214
215 return num;
216 }
217
218 #endif /* FEATURE_REDIRECTION */