1 /* 2 * WHERE.C - file search functions. 3 * 4 * 5 * History: 6 * 7 * 07/15/95 (Tim Norman) 8 * started. 9 * 10 * 08/08/95 (Matt Rains) 11 * i have cleaned up the source code. changes now bring this source 12 * into guidelines for recommended programming practice. 13 * 14 * 12/12/95 (Steffan Kaiser & Tim Norman) 15 * added some patches to fix some things and make more efficient 16 * 17 * 1/6/96 (Tim Norman) 18 * fixed a stupid pointer mistake... 19 * Thanks to everyone who noticed it! 20 * 21 * 8/1/96 (Tim Norman) 22 * fixed a bug when getenv returns NULL 23 * 24 * 8/7/96 (Steffan Kaiser and Tim Norman) 25 * speed improvements and bug fixes 26 * 27 * 8/27/96 (Tim Norman) 28 * changed code to use pointers directly into PATH environment 29 * variable rather than making our own copy. This saves some memory, 30 * but requires we write our own function to copy pathnames out of 31 * the variable. 32 * 33 * 12/23/96 (Aaron Kaufman) 34 * Fixed a bug in get_paths() that did not point to the first PATH 35 * in the environment variable. 36 * 37 * 7/12/97 (Tim Norman) 38 * Apparently, Aaron's bugfix got lost, so I fixed it again. 39 * 40 * 16 July 1998 (John P. Price) 41 * Added stand alone code. 42 * 43 * 17 July 1998 (John P. Price) 44 * Rewrote find_which to use searchpath function 45 * 46 * 24-Jul-1998 (John P Price <linux-guru@gcfl.net>) 47 * fixed bug where didn't check all extensions when path was specified 48 * 49 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 50 * added config.h include 51 * 52 * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>) 53 * fixed so that it find_which returns NULL if filename is not 54 * executable (does not have .bat, .com, or .exe extension). 55 * Before command would to execute any file with any extension (opps!) 56 * 57 * 03-Dec-1998 (Eric Kohl) 58 * Changed find_which(). 59 * 60 * 07-Dec-1998 (Eric Kohl) 61 * Added ".CMD" extension. 62 * Replaced numeric constant by _NR_OF_EXTENSIONS. 63 * 64 * 26-Feb-1999 (Eric Kohl) 65 * Replaced find_which() by SearchForExecutable(). 66 * Now files are searched using the right extension order. 67 * 68 * 20-Apr-1999 (Eric Kohl) 69 * Some minor changes and improvements. 70 * 71 * 10-Jul-2004 (Jens Collin <jens.collin@lakhei.com>) 72 * Fixed searching for files with specific extensions in PATHEXT order. 73 * 74 */ 75 76 #include "precomp.h" 77 78 79 /* initial size of environment variable buffer */ 80 #define ENV_BUFFER_SIZE 1024 81 82 83 /* searches for file using path info. */ 84 85 BOOL 86 SearchForExecutableSingle (LPCTSTR pFileName, LPTSTR pFullName, LPTSTR pPathExt, LPTSTR pDirectory) 87 { 88 TCHAR szPathBuffer[CMDLINE_LENGTH], *pszPathEnd; 89 LPTSTR s,f; 90 /* initialize full name buffer */ 91 *pFullName = _T('\0'); 92 93 TRACE ("SearchForExecutableSingle: \'%s\' in dir: \'%s\'\n", 94 debugstr_aw(pFileName), debugstr_aw(pDirectory)); 95 96 pszPathEnd = szPathBuffer; 97 if (pDirectory != NULL) 98 { 99 _tcscpy(szPathBuffer, pDirectory); 100 pszPathEnd += _tcslen(pszPathEnd); 101 *pszPathEnd++ = _T('\\'); 102 } 103 _tcscpy(pszPathEnd, pFileName); 104 pszPathEnd += _tcslen(pszPathEnd); 105 106 if (IsExistingFile (szPathBuffer)) 107 { 108 TRACE ("Found: \'%s\'\n", debugstr_aw(szPathBuffer)); 109 GetFullPathName(szPathBuffer, MAX_PATH, pFullName, NULL); 110 return TRUE; 111 } 112 113 s = pPathExt; 114 while (s && *s) 115 { 116 f = _tcschr (s, _T(';')); 117 118 if (f) 119 { 120 _tcsncpy (pszPathEnd, s, (size_t)(f-s)); 121 pszPathEnd[f-s] = _T('\0'); 122 s = f + 1; 123 } 124 else 125 { 126 _tcscpy (pszPathEnd, s); 127 s = NULL; 128 } 129 130 if (IsExistingFile (szPathBuffer)) 131 { 132 TRACE ("Found: \'%s\'\n", debugstr_aw(szPathBuffer)); 133 GetFullPathName(szPathBuffer, MAX_PATH, pFullName, NULL); 134 return TRUE; 135 } 136 } 137 return FALSE; 138 } 139 140 141 BOOL 142 SearchForExecutable (LPCTSTR pFileName, LPTSTR pFullName) 143 { 144 static TCHAR pszDefaultPathExt[] = _T(".com;.exe;.bat;.cmd"); 145 LPTSTR pszPathExt, pszPath; 146 LPTSTR pCh; 147 DWORD dwBuffer; 148 TRACE ("SearchForExecutable: \'%s\'\n", debugstr_aw(pFileName)); 149 150 /* load environment variable PATHEXT */ 151 pszPathExt = (LPTSTR)cmd_alloc (ENV_BUFFER_SIZE * sizeof(TCHAR)); 152 if (!pszPathExt) 153 { 154 WARN("Cannot allocate memory for pszPathExt!\n"); 155 return FALSE; 156 } 157 158 dwBuffer = GetEnvironmentVariable (_T("PATHEXT"), pszPathExt, ENV_BUFFER_SIZE); 159 if (dwBuffer > ENV_BUFFER_SIZE) 160 { 161 LPTSTR pszOldPathExt = pszPathExt; 162 pszPathExt = (LPTSTR)cmd_realloc (pszPathExt, dwBuffer * sizeof (TCHAR)); 163 if (!pszPathExt) 164 { 165 WARN("Cannot reallocate memory for pszPathExt!\n"); 166 cmd_free(pszOldPathExt); 167 return FALSE; 168 } 169 GetEnvironmentVariable (_T("PATHEXT"), pszPathExt, dwBuffer); 170 _tcslwr(pszPathExt); 171 } 172 else if (0 == dwBuffer) 173 { 174 _tcscpy(pszPathExt, pszDefaultPathExt); 175 } 176 else 177 { 178 _tcslwr(pszPathExt); 179 } 180 181 /* Check if valid directly on specified path */ 182 if (SearchForExecutableSingle(pFileName, pFullName, pszPathExt, NULL)) 183 { 184 cmd_free(pszPathExt); 185 return TRUE; 186 } 187 188 /* If an explicit directory was given, stop here - no need to search PATH. */ 189 if (pFileName[1] == _T(':') || _tcschr(pFileName, _T('\\'))) 190 { 191 cmd_free(pszPathExt); 192 return FALSE; 193 } 194 195 /* load environment variable PATH into buffer */ 196 pszPath = (LPTSTR)cmd_alloc (ENV_BUFFER_SIZE * sizeof(TCHAR)); 197 if (!pszPath) 198 { 199 WARN("Cannot allocate memory for pszPath!\n"); 200 return FALSE; 201 } 202 203 dwBuffer = GetEnvironmentVariable (_T("PATH"), pszPath, ENV_BUFFER_SIZE); 204 if (dwBuffer > ENV_BUFFER_SIZE) 205 { 206 LPTSTR pszOldPath = pszPath; 207 pszPath = (LPTSTR)cmd_realloc (pszPath, dwBuffer * sizeof (TCHAR)); 208 if (!pszPath) 209 { 210 WARN("Cannot reallocate memory for pszPath!\n"); 211 cmd_free(pszOldPath); 212 cmd_free(pszPathExt); 213 return FALSE; 214 } 215 GetEnvironmentVariable (_T("PATH"), pszPath, dwBuffer); 216 } 217 218 TRACE ("SearchForExecutable(): Loaded PATH: %s\n", debugstr_aw(pszPath)); 219 220 /* search in PATH */ 221 pCh = _tcstok(pszPath, _T(";")); 222 while (pCh) 223 { 224 if (SearchForExecutableSingle(pFileName, pFullName, pszPathExt, pCh)) 225 { 226 cmd_free(pszPath); 227 cmd_free(pszPathExt); 228 return TRUE; 229 } 230 pCh = _tcstok(NULL, _T(";")); 231 } 232 233 cmd_free(pszPath); 234 cmd_free(pszPathExt); 235 return FALSE; 236 } 237 238 /* EOF */ 239