update for HEAD-2003091401
[reactos.git] / subsys / system / cmd / where.c
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 extention).
55  *        Before command would to execute any file with any extension (opps!)
56  *
57  *    03-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
58  *        Changed find_which().
59  *
60  *    07-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
61  *        Added ".CMD" extension.
62  *        Replaced numeric constant by _NR_OF_EXTENSIONS.
63  *
64  *    26-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
65  *        Replaced find_which() by SearchForExecutable().
66  *        Now files are searched using the right extension order.
67  *
68  *    20-Apr-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
69  *        Some minor changes and improvements.
70  */
71
72 #include "config.h"
73
74 #include <windows.h>
75 #include <string.h>
76 #include <stdlib.h>
77
78 #include "cmd.h"
79
80
81 /* initial size of environment variable buffer */
82 #define ENV_BUFFER_SIZE  1024
83
84
85 static LPTSTR ext[]  = {_T(".bat"), _T(".cmd"), _T(".com"), _T(".exe")};
86 static INT nExtCount = sizeof(ext) / sizeof(LPTSTR);
87
88
89 /* searches for file using path info. */
90
91 BOOL
92 SearchForExecutable (LPCTSTR pFileName, LPTSTR pFullName)
93 {
94         TCHAR  szPathBuffer[MAX_PATH];
95         LPTSTR pszBuffer = NULL;
96         DWORD  dwBuffer, len;
97         INT    n;
98         LPTSTR p,s,f;
99
100
101         /* initialize full name buffer */
102         *pFullName = _T('\0');
103
104 #ifdef _DEBUG
105         DebugPrintf (_T("SearchForExecutable: \'%s\'\n"), pFileName);
106 #endif
107
108         if (_tcschr (pFileName, _T('\\')) != NULL)
109         {
110                 LPTSTR pFilePart;
111 #ifdef _DEBUG
112                 DebugPrintf (_T("Absolute or relative path is given.\n"));
113 #endif
114
115                 if (GetFullPathName (pFileName,
116                                      MAX_PATH,
117                                      szPathBuffer,
118                                      &pFilePart)  ==0)
119                         return FALSE;
120
121                 if(pFilePart == 0)
122                         return FALSE;
123
124
125                 if (_tcschr (pFilePart, _T('.')) != NULL)
126                 {
127 #ifdef _DEBUG
128                         DebugPrintf (_T("Filename extension!\n"));
129 #endif
130                         _tcscpy (pFullName, szPathBuffer);
131                         return TRUE;
132
133                 }
134                 else
135                 {
136 #ifdef _DEBUG
137                         DebugPrintf (_T("No filename extension!\n"));
138 #endif
139
140                         p = szPathBuffer + _tcslen (szPathBuffer);
141
142                         for (n = 0; n < nExtCount; n++)
143                         {
144                                 _tcscpy (p, ext[n]);
145
146 #ifdef _DEBUG
147                                 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
148 #endif
149
150                                 if (IsValidFileName (szPathBuffer))
151                                 {
152 #ifdef _DEBUG
153                                         DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
154 #endif
155                                         _tcscpy (pFullName, szPathBuffer);
156                                         return TRUE;
157                                 }
158                         }
159                         return FALSE;
160                 }
161         }
162
163         /* load environment varable PATH into buffer */
164         pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
165         dwBuffer = GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
166         if (dwBuffer > ENV_BUFFER_SIZE)
167         {
168                 pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
169                 GetEnvironmentVariable (_T("PATH"), pszBuffer, dwBuffer * sizeof (TCHAR));
170         }
171
172         if (!(p = _tcsrchr (pFileName, _T('.'))) ||
173                 _tcschr (p + 1, _T('\\')))
174         {
175                 /* There is no extension ==> test all the extensions. */
176 #ifdef _DEBUG
177                 DebugPrintf (_T("No filename extension!\n"));
178 #endif
179
180                 /* search in current directory */
181                 len = GetCurrentDirectory (MAX_PATH, szPathBuffer);
182                 if (szPathBuffer[len - 1] != _T('\\'))
183                 {
184                         szPathBuffer[len] = _T('\\');
185                         szPathBuffer[len + 1] = _T('\0');
186                 }
187                 _tcscat (szPathBuffer, pFileName);
188
189                 p = szPathBuffer + _tcslen (szPathBuffer);
190
191                 for (n = 0; n < nExtCount; n++)
192                 {
193                         _tcscpy (p, ext[n]);
194
195 #ifdef _DEBUG
196                         DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
197 #endif
198
199                         if (IsValidFileName (szPathBuffer))
200                         {
201 #ifdef _DEBUG
202                                 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
203 #endif
204                                 free (pszBuffer);
205                                 _tcscpy (pFullName, szPathBuffer);
206                                 return TRUE;
207                         }
208                 }
209
210                 /* search in PATH */
211                 s = pszBuffer;
212                 while (s && *s)
213                 {
214                         f = _tcschr (s, _T(';'));
215
216                         if (f)
217                         {
218                                 _tcsncpy (szPathBuffer, s, (size_t)(f-s));
219                                 szPathBuffer[f-s] = _T('\0');
220                                 s = f + 1;
221                         }
222                         else
223                         {
224                                 _tcscpy (szPathBuffer, s);
225                                 s = NULL;
226                         }
227
228                         len = _tcslen(szPathBuffer);
229                         if (szPathBuffer[len - 1] != _T('\\'))
230                         {
231                                 szPathBuffer[len] = _T('\\');
232                                 szPathBuffer[len + 1] = _T('\0');
233                         }
234                         _tcscat (szPathBuffer, pFileName);
235
236                         p = szPathBuffer + _tcslen (szPathBuffer);
237
238                         for (n = 0; n < nExtCount; n++)
239                         {
240                                 _tcscpy (p, ext[n]);
241
242 #ifdef _DEBUG
243                                 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
244 #endif
245
246                                 if (IsValidFileName (szPathBuffer))
247                                 {
248 #ifdef _DEBUG
249                                         DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
250 #endif
251                                         free (pszBuffer);
252                                         _tcscpy (pFullName, szPathBuffer);
253                                         return TRUE;
254                                 }
255                         }
256                 }
257         }
258         else
259         {
260                 /* There is an extension and it is in the last path component, */
261                 /* so don't test all the extensions. */
262 #ifdef _DEBUG
263                 DebugPrintf (_T("Filename extension!\n"));
264 #endif
265
266                 /* search in current directory */
267                 len = GetCurrentDirectory (MAX_PATH, szPathBuffer);
268                 if (szPathBuffer[len - 1] != _T('\\'))
269                 {
270                         szPathBuffer[len] = _T('\\');
271                         szPathBuffer[len + 1] = _T('\0');
272                 }
273                 _tcscat (szPathBuffer, pFileName);
274
275 #ifdef _DEBUG
276                 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
277 #endif
278                 if (IsValidFileName (szPathBuffer))
279                 {
280 #ifdef _DEBUG
281                         DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
282 #endif
283                         free (pszBuffer);
284                         _tcscpy (pFullName, szPathBuffer);
285                         return TRUE;
286                 }
287
288
289                 /* search in PATH */
290                 s = pszBuffer;
291                 while (s && *s)
292                 {
293                         f = _tcschr (s, _T(';'));
294
295                         if (f)
296                         {
297                                 _tcsncpy (szPathBuffer, s, (size_t)(f-s));
298                                 szPathBuffer[f-s] = _T('\0');
299                                 s = f + 1;
300                         }
301                         else
302                         {
303                                 _tcscpy (szPathBuffer, s);
304                                 s = NULL;
305                         }
306
307                         len = _tcslen(szPathBuffer);
308                         if (szPathBuffer[len - 1] != _T('\\'))
309                         {
310                                 szPathBuffer[len] = _T('\\');
311                                 szPathBuffer[len + 1] = _T('\0');
312                         }
313                         _tcscat (szPathBuffer, pFileName);
314
315 #ifdef _DEBUG
316                         DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
317 #endif
318                         if (IsValidFileName (szPathBuffer))
319                         {
320 #ifdef _DEBUG
321                                 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
322 #endif
323                                 free (pszBuffer);
324                                 _tcscpy (pFullName, szPathBuffer);
325                                 return TRUE;
326                         }
327                 }
328         }
329
330         free (pszBuffer);
331
332         return FALSE;
333 }