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 * Separated 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) 17 * Added help text ("if /?") and cleaned up. 18 * 19 * 21-Jan-1999 (Eric Kohl) 20 * Unicode and redirection ready! 21 * 22 * 01-Sep-1999 (Eric Kohl) 23 * Fixed help text. 24 * 25 * 17-Feb-2001 (ea) 26 * IF DEFINED variable command 27 * 28 * 28-Apr-2005 (Magnus Olsen) <magnus@greatlord.com> 29 * Remove all hardcoded strings in En.rc 30 * 31 */ 32 33 #include "precomp.h" 34 35 static INT GenericCmp(INT (WINAPI *StringCmp)(LPCTSTR, LPCTSTR), 36 LPCTSTR Left, LPCTSTR Right) 37 { 38 TCHAR *end; 39 INT nLeft = _tcstol(Left, &end, 0); 40 if (*end == _T('\0')) 41 { 42 INT nRight = _tcstol(Right, &end, 0); 43 if (*end == _T('\0')) 44 { 45 /* both arguments are numeric */ 46 return (nLeft < nRight) ? -1 : (nLeft > nRight); 47 } 48 } 49 return StringCmp(Left, Right); 50 } 51 52 INT cmd_if(LPTSTR param) 53 { 54 TRACE("cmd_if(\'%s\')\n", debugstr_aw(param)); 55 56 if (!_tcsncmp (param, _T("/?"), 2)) 57 { 58 ConOutResPaging(TRUE, STRING_IF_HELP1); 59 return 0; 60 } 61 62 ParseErrorEx(param); 63 return 1; 64 } 65 66 INT ExecuteIf(PARSED_COMMAND *Cmd) 67 { 68 INT result = FALSE; /* when set cause 'then' clause to be executed */ 69 LPTSTR param; 70 LPTSTR Left = NULL, Right; 71 72 if (Cmd->If.LeftArg) 73 { 74 Left = DoDelayedExpansion(Cmd->If.LeftArg); 75 if (!Left) 76 return 1; 77 } 78 Right = DoDelayedExpansion(Cmd->If.RightArg); 79 if (!Right) 80 { 81 if (Left) cmd_free(Left); 82 return 1; 83 } 84 85 if (bEnableExtensions && (Cmd->If.Operator == IF_CMDEXTVERSION)) 86 { 87 /* IF CMDEXTVERSION n: check if Command Extensions 88 * version is greater or equal to n. */ 89 DWORD n = _tcstoul(Right, ¶m, 10); 90 if (*param != _T('\0')) 91 { 92 error_syntax(Right); 93 goto fail; 94 } 95 result = (CMDEXTVERSION >= n); 96 } 97 else if (bEnableExtensions && (Cmd->If.Operator == IF_DEFINED)) 98 { 99 /* IF DEFINED var: check if environment variable exists */ 100 result = (GetEnvVarOrSpecial(Right) != NULL); 101 } 102 else if (Cmd->If.Operator == IF_ERRORLEVEL) 103 { 104 /* IF ERRORLEVEL n: check if last exit code is greater or equal to n */ 105 INT n = _tcstol(Right, ¶m, 10); 106 if (*param != _T('\0')) 107 { 108 error_syntax(Right); 109 goto fail; 110 } 111 result = (nErrorLevel >= n); 112 } 113 else if (Cmd->If.Operator == IF_EXIST) 114 { 115 BOOL IsDir; 116 SIZE_T Size; 117 WIN32_FIND_DATA f; 118 HANDLE hFind; 119 DWORD attrs; 120 121 /* IF EXIST filename: check if file exists (wildcards allowed) */ 122 StripQuotes(Right); 123 124 Size = _tcslen(Right); 125 IsDir = (Right[Size - 1] == '\\'); 126 if (IsDir) 127 Right[Size - 1] = 0; 128 129 hFind = FindFirstFile(Right, &f); 130 if (hFind != INVALID_HANDLE_VALUE) 131 { 132 attrs = f.dwFileAttributes; 133 FindClose(hFind); 134 } 135 else 136 { 137 /* FindFirstFile fails at the root directory. */ 138 attrs = GetFileAttributes(Right); 139 } 140 141 if (attrs == INVALID_FILE_ATTRIBUTES) 142 result = FALSE; 143 else if (IsDir) 144 result = ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY); 145 else 146 result = TRUE; 147 148 if (IsDir) 149 Right[Size - 1] = '\\'; 150 } 151 else 152 { 153 /* 154 * Do case-insensitive string comparisons if /I specified. 155 * 156 * Since both strings are user-specific, use kernel32!lstrcmp(i) 157 * instead of CRT!_tcs(i)cmp, so as to use the correct 158 * current thread locale information. 159 */ 160 INT (WINAPI *StringCmp)(LPCTSTR, LPCTSTR) = 161 (Cmd->If.Flags & IFFLAG_IGNORECASE) ? lstrcmpi : lstrcmp; 162 163 if (Cmd->If.Operator == IF_STRINGEQ) 164 { 165 /* IF str1 == str2 */ 166 result = (StringCmp(Left, Right) == 0); 167 } 168 else if (bEnableExtensions) 169 { 170 result = GenericCmp(StringCmp, Left, Right); 171 switch (Cmd->If.Operator) 172 { 173 case IF_EQU: result = (result == 0); break; 174 case IF_NEQ: result = (result != 0); break; 175 case IF_LSS: result = (result < 0); break; 176 case IF_LEQ: result = (result <= 0); break; 177 case IF_GTR: result = (result > 0); break; 178 case IF_GEQ: result = (result >= 0); break; 179 default: goto unknownOp; 180 } 181 } 182 else 183 { 184 unknownOp: 185 ERR("Unknown IF operator 0x%x\n", Cmd->If.Operator); 186 ASSERT(FALSE); 187 goto fail; 188 } 189 } 190 191 if (Left) cmd_free(Left); 192 cmd_free(Right); 193 194 if (result ^ ((Cmd->If.Flags & IFFLAG_NEGATE) != 0)) 195 { 196 /* Full condition was true, do the command */ 197 return ExecuteCommand(Cmd->Subcommands); 198 } 199 else 200 { 201 /* Full condition was false, do the "else" command if there is one */ 202 return ExecuteCommand(Cmd->Subcommands->Next); 203 } 204 205 fail: 206 if (Left) cmd_free(Left); 207 cmd_free(Right); 208 return 1; 209 } 210 211 /* EOF */ 212