update for HEAD-2003050101
[reactos.git] / subsys / system / cmd / if.c
1 /*
2  *  IF.C - if internal batch command.
3  *
4  *
5  *  History:
6  *
7  *    16 Jul 1998 (Hans B Pufal)
8  *        started.
9  *
10  *    16 Jul 1998 (John P Price)
11  *        Seperated commands into individual files.
12  *
13  *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14  *        added config.h include
15  *
16  *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
17  *        Added help text ("if /?") and cleaned up.
18  *
19  *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
20  *        Unicode and redirection ready!
21  *
22  *    01-Sep-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
23  *        Fixed help text.
24  *
25  *    17-Feb-2001 (ea)
26  *        IF DEFINED variable command
27  */
28
29 #include "config.h"
30
31 #include <windows.h>
32 #include <tchar.h>
33 #include <string.h>
34 #include <ctype.h>
35
36 #include "cmd.h"
37 #include "batch.h"
38
39
40 #define X_EXEC 1
41 #define X_EMPTY 0x80
42
43 INT cmd_if (LPTSTR cmd, LPTSTR param)
44 {
45         INT x_flag = 0; /* when set cause 'then' clause to be executed */
46         LPTSTR pp;
47
48 #ifdef _DEBUG
49         DebugPrintf ("cmd_if: (\'%s\', \'%s\'\n", cmd, param);
50 #endif
51
52         if (!_tcsncmp (param, _T("/?"), 2))
53         {
54                 ConOutPuts (_T("Performs conditional processing in batch programs.\n"
55                                "\n"
56                                "  IF [NOT] ERRORLEVEL number command\n"
57                                "  IF [NOT] string1==string2 command\n"
58                                "  IF [NOT] EXIST filename command\n"
59                                "  IF [NOT] DEFINED variable command\n"
60                                "\n"
61                                "NOT               Specifies that CMD should carry out the command only if\n"
62                                "                  the condition is false\n"
63                                "ERRORLEVEL number Specifies a true condition if the last program run returned\n"
64                                "                  an exit code equal or greater than the number specified.\n"
65                                "command           Specifies the command to carry out if the condition is met.\n"
66                                "string1==string2  Specifies a true condition if the specified text strings\n"
67                                "                  match.\n"
68                                "EXIST filename    Specifies a true condition if the specified filename exists.\n"
69                                "DEFINED variable  Specifies a true condition if the specified variable is\n"
70                                "                  defined."));
71                 return 0;
72         }
73
74         /* First check if param string begins with word 'not' */
75         if (!_tcsnicmp (param, _T("not"), 3) && _istspace (*(param + 3)))
76         {
77                 x_flag = X_EXEC;            /* Remember 'NOT' */
78                 param += 3;                 /* Step over 'NOT' */
79                 while (_istspace (*param))  /* And subsequent spaces */
80                         param++;
81         }
82
83         /* Check for 'exist' form */
84         if (!_tcsnicmp (param, _T("exist"), 5) && _istspace (*(param + 5)))
85         {
86                 param += 5;
87                 while (_istspace (*param))
88                         param++;
89
90                 pp = param;
91                 while (*pp && !_istspace (*pp))
92                         pp++;
93
94                 if (*pp)
95                 {
96                         WIN32_FIND_DATA f;
97                         HANDLE hFind;
98
99                         *pp++ = _T('\0');
100                         hFind = FindFirstFile (param, &f);
101                         x_flag ^= (hFind == INVALID_HANDLE_VALUE) ? 0 : X_EXEC;
102                         if (hFind != INVALID_HANDLE_VALUE)
103                         {
104                                 FindClose (hFind);
105                         }
106                 }
107                 else
108                         return 0;
109         }
110
111         /* Check for 'defined' form */
112         else if (!_tcsnicmp (param, _T("defined"), 7) && _istspace (*(param + 7)))
113         {
114                 TCHAR Value [1];
115                 INT   ValueSize = 0;
116
117                 param += 7;
118                 /* IF [NOT] DEFINED var COMMAND */
119                 /*                 ^            */
120                 while (_istspace (*param))
121                         param++;
122                 /* IF [NOT] DEFINED var COMMAND */
123                 /*                  ^           */
124                 pp = param;
125                 while (*pp && !_istspace (*pp))
126                         pp++;
127                 /* IF [NOT] DEFINED var COMMAND */
128                 /*                     ^        */
129                 if (*pp)
130                 {
131                         *pp++ = _T('\0');
132                         ValueSize = GetEnvironmentVariable(param, Value, sizeof Value);
133                         x_flag ^= (0 == ValueSize)
134                                         ? 0 
135                                         : X_EXEC;
136                         x_flag |= X_EMPTY;
137                 }
138                 else
139                         return 0;
140         }
141
142         /* Check for 'errorlevel' form */
143         else if (!_tcsnicmp (param, _T("errorlevel"), 10) && _istspace (*(param + 10)))
144         {
145                 INT n = 0;
146
147                 pp = param + 10;
148                 while (_istspace (*pp))
149                         pp++;
150
151                 while (_istdigit (*pp))
152                         n = n * 10 + (*pp++ - _T('0'));
153
154                 x_flag ^= (nErrorLevel < n) ? 0 : X_EXEC;
155
156                 x_flag |= X_EMPTY;          /* Syntax error if comd empty */
157         }
158
159         /* Check that '==' is present, syntax error if not */
160         else if (NULL == (pp = _tcsstr (param, _T("=="))))
161         {
162                 error_syntax (NULL);
163                 return 1;
164         }
165
166         else
167         {
168                 /* Change first '='to space to terminate comparison loop */
169
170                 *pp = _T(' ');   /* Need a space to terminate comparison loop */
171                 pp += 2;                /* over '==' */
172                 while (_istspace (*pp)) /* Skip subsequent spaces */
173                         pp++;
174
175                 _tcscat (pp, _T(" "));  /* Add one space to ensure comparison ends */
176
177                 while (*param == *pp)       /* Comparison loop */
178                 {
179                         if (_istspace (*param))      /* Terminates on space */
180                                 break;
181
182                         param++, pp++;
183                 }
184
185                 if (x_flag ^= (*param != *pp) ? 0 : X_EXEC)
186                 {
187                         while (*pp && !_istspace (*pp))  /* Find first space, */
188                                 pp++;
189
190                         x_flag |= X_EMPTY;
191                 }
192         }
193
194         if (x_flag & X_EMPTY)
195         {
196                 while (_istspace (*pp)) /* Then skip spaces */
197                         pp++;
198
199                 if (*pp == _T('\0'))    /* If nothing left then syntax err */
200                 {
201                         error_syntax (NULL);
202                         return 1;
203                 }
204         }
205
206         if (x_flag & X_EXEC)
207         {
208                 ParseCommandLine (pp);
209         }
210
211         return 0;
212 }