CMD: implemented IF [NOT] DEFINED variable command
[reactos.git] / rosapps / 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 }