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 _tcscpy (pFullName, szPathBuffer); 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 _tcscpy (pFullName, szPathBuffer); 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 dwBuffer = GetEnvironmentVariable (_T("PATHEXT"), pszPathExt, ENV_BUFFER_SIZE); 153 if (dwBuffer > ENV_BUFFER_SIZE) 154 { 155 LPTSTR pszOldPathExt = pszPathExt; 156 pszPathExt = (LPTSTR)cmd_realloc (pszPathExt, dwBuffer * sizeof (TCHAR)); 157 if (pszPathExt == NULL) 158 { 159 cmd_free(pszOldPathExt); 160 return FALSE; 161 } 162 GetEnvironmentVariable (_T("PATHEXT"), pszPathExt, dwBuffer); 163 _tcslwr(pszPathExt); 164 } 165 else if (0 == dwBuffer) 166 { 167 _tcscpy(pszPathExt, pszDefaultPathExt); 168 } 169 else 170 { 171 _tcslwr(pszPathExt); 172 } 173 174 /* Check if valid directly on specified path */ 175 if (SearchForExecutableSingle(pFileName, pFullName, pszPathExt, NULL)) 176 { 177 cmd_free(pszPathExt); 178 return TRUE; 179 } 180 181 /* If an explicit directory was given, stop here - no need to search PATH. */ 182 if (pFileName[1] == _T(':') || _tcschr(pFileName, _T('\\'))) 183 { 184 cmd_free(pszPathExt); 185 return FALSE; 186 } 187 188 /* load environment variable PATH into buffer */ 189 pszPath = (LPTSTR)cmd_alloc (ENV_BUFFER_SIZE * sizeof(TCHAR)); 190 dwBuffer = GetEnvironmentVariable (_T("PATH"), pszPath, ENV_BUFFER_SIZE); 191 if (dwBuffer > ENV_BUFFER_SIZE) 192 { 193 LPTSTR pszOldPath = pszPath; 194 pszPath = (LPTSTR)cmd_realloc (pszPath, dwBuffer * sizeof (TCHAR)); 195 if (pszPath == NULL) 196 { 197 cmd_free(pszOldPath); 198 cmd_free(pszPathExt); 199 return FALSE; 200 } 201 GetEnvironmentVariable (_T("PATH"), pszPath, dwBuffer); 202 } 203 204 TRACE ("SearchForExecutable(): Loaded PATH: %s\n", debugstr_aw(pszPath)); 205 206 /* search in PATH */ 207 pCh = _tcstok(pszPath, _T(";")); 208 while (pCh) 209 { 210 if (SearchForExecutableSingle(pFileName, pFullName, pszPathExt, pCh)) 211 { 212 cmd_free(pszPath); 213 cmd_free(pszPathExt); 214 return TRUE; 215 } 216 pCh = _tcstok(NULL, _T(";")); 217 } 218 219 cmd_free(pszPath); 220 cmd_free(pszPathExt); 221 return FALSE; 222 } 223 224 /* EOF */ 225