Updated years in version info.
[reactos.git] / rosapps / 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[] = {".bat", ".cmd", ".com", ".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
116
117
118 if (GetFullPathName (pFileName,
119 MAX_PATH,
120 szPathBuffer,
121 &pFilePart) ==0)
122 return FALSE;
123
124
125 if(pFilePart == 0)
126 return FALSE;
127
128
129
130 if (_tcschr (pFilePart, _T('.')) != NULL)
131 {
132 #ifdef _DEBUG
133 DebugPrintf (_T("Filename extension!\n"));
134 #endif
135 _tcscpy (pFullName, szPathBuffer);
136 return TRUE;
137
138 }
139 else
140 {
141 #ifdef _DEBUG
142 DebugPrintf (_T("No filename extension!\n"));
143 #endif
144
145 p = szPathBuffer + _tcslen (szPathBuffer);
146
147 for (n = 0; n < nExtCount; n++)
148 {
149 _tcscpy (p, ext[n]);
150
151 #ifdef _DEBUG
152 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
153 #endif
154
155 if (IsValidFileName (szPathBuffer))
156 {
157 #ifdef _DEBUG
158 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
159 #endif
160 _tcscpy (pFullName, szPathBuffer);
161 return TRUE;
162 }
163 }
164 return FALSE;
165 }
166 }
167
168 /* load environment varable PATH into buffer */
169 pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
170 dwBuffer = GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
171 if (dwBuffer > ENV_BUFFER_SIZE)
172 {
173 pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
174 GetEnvironmentVariable (_T("PATH"), pszBuffer, dwBuffer * sizeof (TCHAR));
175 }
176
177 if (!(p = _tcsrchr (pFileName, _T('.'))) ||
178 _tcschr (p + 1, _T('\\')))
179 {
180 /* There is no extension ==> test all the extensions. */
181 #ifdef _DEBUG
182 DebugPrintf (_T("No filename extension!\n"));
183 #endif
184
185 /* search in current directory */
186 len = GetCurrentDirectory (MAX_PATH, szPathBuffer);
187 if (szPathBuffer[len - 1] != _T('\\'))
188 {
189 szPathBuffer[len] = _T('\\');
190 szPathBuffer[len + 1] = _T('\0');
191 }
192 _tcscat (szPathBuffer, pFileName);
193
194 p = szPathBuffer + _tcslen (szPathBuffer);
195
196 for (n = 0; n < nExtCount; n++)
197 {
198 _tcscpy (p, ext[n]);
199
200 #ifdef _DEBUG
201 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
202 #endif
203
204 if (IsValidFileName (szPathBuffer))
205 {
206 #ifdef _DEBUG
207 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
208 #endif
209 free (pszBuffer);
210 _tcscpy (pFullName, szPathBuffer);
211 return TRUE;
212 }
213 }
214
215 /* search in PATH */
216 s = pszBuffer;
217 while (s && *s)
218 {
219 f = _tcschr (s, _T(';'));
220
221 if (f)
222 {
223 _tcsncpy (szPathBuffer, s, (size_t)(f-s));
224 szPathBuffer[f-s] = _T('\0');
225 s = f + 1;
226 }
227 else
228 {
229 _tcscpy (szPathBuffer, s);
230 s = NULL;
231 }
232
233 len = _tcslen(szPathBuffer);
234 if (szPathBuffer[len - 1] != _T('\\'))
235 {
236 szPathBuffer[len] = _T('\\');
237 szPathBuffer[len + 1] = _T('\0');
238 }
239 _tcscat (szPathBuffer, pFileName);
240
241 p = szPathBuffer + _tcslen (szPathBuffer);
242
243 for (n = 0; n < nExtCount; n++)
244 {
245 _tcscpy (p, ext[n]);
246
247 #ifdef _DEBUG
248 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
249 #endif
250
251 if (IsValidFileName (szPathBuffer))
252 {
253 #ifdef _DEBUG
254 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
255 #endif
256 free (pszBuffer);
257 _tcscpy (pFullName, szPathBuffer);
258 return TRUE;
259 }
260 }
261 }
262 }
263 else
264 {
265 /* There is an extension and it is in the last path component, */
266 /* so don't test all the extensions. */
267 #ifdef _DEBUG
268 DebugPrintf (_T("Filename extension!\n"));
269 #endif
270
271 /* search in current directory */
272 len = GetCurrentDirectory (MAX_PATH, szPathBuffer);
273 if (szPathBuffer[len - 1] != _T('\\'))
274 {
275 szPathBuffer[len] = _T('\\');
276 szPathBuffer[len + 1] = _T('\0');
277 }
278 _tcscat (szPathBuffer, pFileName);
279
280 #ifdef _DEBUG
281 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
282 #endif
283 if (IsValidFileName (szPathBuffer))
284 {
285 #ifdef _DEBUG
286 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
287 #endif
288 free (pszBuffer);
289 _tcscpy (pFullName, szPathBuffer);
290 return TRUE;
291 }
292
293
294 /* search in PATH */
295 s = pszBuffer;
296 while (s && *s)
297 {
298 f = _tcschr (s, _T(';'));
299
300 if (f)
301 {
302 _tcsncpy (szPathBuffer, s, (size_t)(f-s));
303 szPathBuffer[f-s] = _T('\0');
304 s = f + 1;
305 }
306 else
307 {
308 _tcscpy (szPathBuffer, s);
309 s = NULL;
310 }
311
312 len = _tcslen(szPathBuffer);
313 if (szPathBuffer[len - 1] != _T('\\'))
314 {
315 szPathBuffer[len] = _T('\\');
316 szPathBuffer[len + 1] = _T('\0');
317 }
318 _tcscat (szPathBuffer, pFileName);
319
320 #ifdef _DEBUG
321 DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
322 #endif
323 if (IsValidFileName (szPathBuffer))
324 {
325 #ifdef _DEBUG
326 DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
327 #endif
328 free (pszBuffer);
329 _tcscpy (pFullName, szPathBuffer);
330 return TRUE;
331 }
332 }
333 }
334
335 free (pszBuffer);
336
337 return FALSE;
338 }