/* * WHERE.C - file search functions. * * * History: * * 07/15/95 (Tim Norman) * started. * * 08/08/95 (Matt Rains) * i have cleaned up the source code. changes now bring this source * into guidelines for recommended programming practice. * * 12/12/95 (Steffan Kaiser & Tim Norman) * added some patches to fix some things and make more efficient * * 1/6/96 (Tim Norman) * fixed a stupid pointer mistake... * Thanks to everyone who noticed it! * * 8/1/96 (Tim Norman) * fixed a bug when getenv returns NULL * * 8/7/96 (Steffan Kaiser and Tim Norman) * speed improvements and bug fixes * * 8/27/96 (Tim Norman) * changed code to use pointers directly into PATH environment * variable rather than making our own copy. This saves some memory, * but requires we write our own function to copy pathnames out of * the variable. * * 12/23/96 (Aaron Kaufman) * Fixed a bug in get_paths() that did not point to the first PATH * in the environment variable. * * 7/12/97 (Tim Norman) * Apparently, Aaron's bugfix got lost, so I fixed it again. * * 16 July 1998 (John P. Price) * Added stand alone code. * * 17 July 1998 (John P. Price) * Rewrote find_which to use searchpath function * * 24-Jul-1998 (John P Price ) * fixed bug where didn't check all extensions when path was specified * * 27-Jul-1998 (John P Price ) * added config.h include * * 30-Jul-1998 (John P Price ) * fixed so that it find_which returns NULL if filename is not * executable (does not have .bat, .com, or .exe extension). * Before command would to execute any file with any extension (opps!) * * 03-Dec-1998 (Eric Kohl) * Changed find_which(). * * 07-Dec-1998 (Eric Kohl) * Added ".CMD" extension. * Replaced numeric constant by _NR_OF_EXTENSIONS. * * 26-Feb-1999 (Eric Kohl) * Replaced find_which() by SearchForExecutable(). * Now files are searched using the right extension order. * * 20-Apr-1999 (Eric Kohl) * Some minor changes and improvements. * * 10-Jul-2004 (Jens Collin ) * Fixed searching for files with specific extensions in PATHEXT order. * */ #include "precomp.h" /* initial size of environment variable buffer */ #define ENV_BUFFER_SIZE 1024 /* searches for file using path info. */ BOOL SearchForExecutableSingle (LPCTSTR pFileName, LPTSTR pFullName, LPTSTR pPathExt, LPTSTR pDirectory) { TCHAR szPathBuffer[CMDLINE_LENGTH], *pszPathEnd; LPTSTR s,f; /* initialize full name buffer */ *pFullName = _T('\0'); TRACE ("SearchForExecutableSingle: \'%s\' in dir: \'%s\'\n", debugstr_aw(pFileName), debugstr_aw(pDirectory)); pszPathEnd = szPathBuffer; if (pDirectory != NULL) { _tcscpy(szPathBuffer, pDirectory); pszPathEnd += _tcslen(pszPathEnd); *pszPathEnd++ = _T('\\'); } _tcscpy(pszPathEnd, pFileName); pszPathEnd += _tcslen(pszPathEnd); if (IsExistingFile (szPathBuffer)) { TRACE ("Found: \'%s\'\n", debugstr_aw(szPathBuffer)); GetFullPathName(szPathBuffer, MAX_PATH, pFullName, NULL); return TRUE; } s = pPathExt; while (s && *s) { f = _tcschr (s, _T(';')); if (f) { _tcsncpy (pszPathEnd, s, (size_t)(f-s)); pszPathEnd[f-s] = _T('\0'); s = f + 1; } else { _tcscpy (pszPathEnd, s); s = NULL; } if (IsExistingFile (szPathBuffer)) { TRACE ("Found: \'%s\'\n", debugstr_aw(szPathBuffer)); GetFullPathName(szPathBuffer, MAX_PATH, pFullName, NULL); return TRUE; } } return FALSE; } BOOL SearchForExecutable (LPCTSTR pFileName, LPTSTR pFullName) { static TCHAR pszDefaultPathExt[] = _T(".com;.exe;.bat;.cmd"); LPTSTR pszPathExt, pszPath; LPTSTR pCh; DWORD dwBuffer; TRACE ("SearchForExecutable: \'%s\'\n", debugstr_aw(pFileName)); /* load environment variable PATHEXT */ pszPathExt = (LPTSTR)cmd_alloc (ENV_BUFFER_SIZE * sizeof(TCHAR)); if (!pszPathExt) { WARN("Cannot allocate memory for pszPathExt!\n"); return FALSE; } dwBuffer = GetEnvironmentVariable (_T("PATHEXT"), pszPathExt, ENV_BUFFER_SIZE); if (dwBuffer > ENV_BUFFER_SIZE) { LPTSTR pszOldPathExt = pszPathExt; pszPathExt = (LPTSTR)cmd_realloc (pszPathExt, dwBuffer * sizeof (TCHAR)); if (!pszPathExt) { WARN("Cannot reallocate memory for pszPathExt!\n"); cmd_free(pszOldPathExt); return FALSE; } GetEnvironmentVariable (_T("PATHEXT"), pszPathExt, dwBuffer); _tcslwr(pszPathExt); } else if (0 == dwBuffer) { _tcscpy(pszPathExt, pszDefaultPathExt); } else { _tcslwr(pszPathExt); } /* Check if valid directly on specified path */ if (SearchForExecutableSingle(pFileName, pFullName, pszPathExt, NULL)) { cmd_free(pszPathExt); return TRUE; } /* If an explicit directory was given, stop here - no need to search PATH. */ if (pFileName[1] == _T(':') || _tcschr(pFileName, _T('\\'))) { cmd_free(pszPathExt); return FALSE; } /* load environment variable PATH into buffer */ pszPath = (LPTSTR)cmd_alloc (ENV_BUFFER_SIZE * sizeof(TCHAR)); if (!pszPath) { WARN("Cannot allocate memory for pszPath!\n"); return FALSE; } dwBuffer = GetEnvironmentVariable (_T("PATH"), pszPath, ENV_BUFFER_SIZE); if (dwBuffer > ENV_BUFFER_SIZE) { LPTSTR pszOldPath = pszPath; pszPath = (LPTSTR)cmd_realloc (pszPath, dwBuffer * sizeof (TCHAR)); if (!pszPath) { WARN("Cannot reallocate memory for pszPath!\n"); cmd_free(pszOldPath); cmd_free(pszPathExt); return FALSE; } GetEnvironmentVariable (_T("PATH"), pszPath, dwBuffer); } TRACE ("SearchForExecutable(): Loaded PATH: %s\n", debugstr_aw(pszPath)); /* search in PATH */ pCh = _tcstok(pszPath, _T(";")); while (pCh) { if (SearchForExecutableSingle(pFileName, pFullName, pszPathExt, pCh)) { cmd_free(pszPath); cmd_free(pszPathExt); return TRUE; } pCh = _tcstok(NULL, _T(";")); } cmd_free(pszPath); cmd_free(pszPathExt); return FALSE; } /* EOF */