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