This source file includes following definitions.
- find_in_given_path
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "findprog.h"
23
24 #include <errno.h>
25 #include <stdbool.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30
31 #include "filename.h"
32 #include "concat-filename.h"
33
34 #if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
35
36 # define NATIVE_SLASH '\\'
37 #else
38
39 # define NATIVE_SLASH '/'
40 #endif
41
42
43 #if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
44
45 # define PATH_SEPARATOR ';'
46 #else
47
48 # define PATH_SEPARATOR ':'
49 #endif
50
51
52
53 static const char * const suffixes[] =
54 {
55 #if defined _WIN32 && !defined __CYGWIN__
56 "", ".com", ".exe", ".bat", ".cmd"
57
58
59
60
61
62
63 #elif defined __CYGWIN__
64 "", ".exe", ".com"
65 #elif defined __EMX__
66 "", ".exe"
67 #elif defined __DJGPP__
68 "", ".com", ".exe", ".bat"
69 #else
70 ""
71 #endif
72 };
73
74 const char *
75 find_in_given_path (const char *progname, const char *path,
76 const char *directory, bool optimize_for_exec)
77 {
78 {
79 bool has_slash = false;
80 {
81 const char *p;
82
83 for (p = progname; *p != '\0'; p++)
84 if (ISSLASH (*p))
85 {
86 has_slash = true;
87 break;
88 }
89 }
90 if (has_slash)
91 {
92
93
94 if (optimize_for_exec)
95
96
97 return progname;
98 else
99 {
100
101
102 int failure_errno;
103 size_t i;
104
105 const char *directory_as_prefix =
106 (directory != NULL && IS_RELATIVE_FILE_NAME (progname)
107 ? directory
108 : "");
109
110 #if defined _WIN32 && !defined __CYGWIN__
111 const char *progbasename;
112
113 {
114 const char *p;
115
116 progbasename = progname;
117 for (p = progname; *p != '\0'; p++)
118 if (ISSLASH (*p))
119 progbasename = p + 1;
120 }
121
122 bool progbasename_has_dot = (strchr (progbasename, '.') != NULL);
123 #endif
124
125
126 failure_errno = ENOENT;
127 for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++)
128 {
129 const char *suffix = suffixes[i];
130
131 #if defined _WIN32 && !defined __CYGWIN__
132
133
134 if ((*suffix != '\0') != progbasename_has_dot)
135 #endif
136 {
137
138 char *progpathname =
139 concatenated_filename (directory_as_prefix, progname,
140 suffix);
141
142 if (progpathname == NULL)
143 return NULL;
144
145
146
147
148
149 if (eaccess (progpathname, X_OK) == 0)
150 {
151
152
153 struct stat statbuf;
154
155 if (stat (progpathname, &statbuf) >= 0)
156 {
157 if (! S_ISDIR (statbuf.st_mode))
158 {
159
160 if (strcmp (progpathname, progname) == 0)
161 {
162 free (progpathname);
163 return progname;
164 }
165 else
166 return progpathname;
167 }
168
169 errno = EACCES;
170 }
171 }
172
173 if (errno != ENOENT)
174 failure_errno = errno;
175
176 free (progpathname);
177 }
178 }
179 #if defined _WIN32 && !defined __CYGWIN__
180 if (failure_errno == ENOENT && !progbasename_has_dot)
181 {
182
183
184
185 char *progpathname =
186 concatenated_filename (directory_as_prefix, progname, "");
187
188 if (progpathname == NULL)
189 return NULL;
190
191 if (eaccess (progpathname, X_OK) == 0)
192 {
193 struct stat statbuf;
194
195 if (stat (progpathname, &statbuf) >= 0)
196 {
197 if (! S_ISDIR (statbuf.st_mode))
198 errno = ENOEXEC;
199 else
200 errno = EACCES;
201 }
202 }
203
204 failure_errno = errno;
205
206 free (progpathname);
207 }
208 #endif
209
210 errno = failure_errno;
211 return NULL;
212 }
213 }
214 }
215
216 if (path == NULL)
217
218
219 path = "";
220
221 {
222
223 char *path_copy = strdup (path);
224 if (path_copy == NULL)
225 return NULL;
226
227 int failure_errno;
228 char *path_rest;
229 char *cp;
230
231 #if defined _WIN32 && !defined __CYGWIN__
232 bool progname_has_dot = (strchr (progname, '.') != NULL);
233 #endif
234
235 failure_errno = ENOENT;
236 for (path_rest = path_copy; ; path_rest = cp + 1)
237 {
238 const char *dir;
239 bool last;
240 char *dir_as_prefix_to_free;
241 const char *dir_as_prefix;
242 size_t i;
243
244
245 dir = path_rest;
246 for (cp = path_rest; *cp != '\0' && *cp != PATH_SEPARATOR; cp++)
247 ;
248 last = (*cp == '\0');
249 *cp = '\0';
250
251
252 if (dir == cp)
253 dir = ".";
254
255
256 if (directory != NULL && IS_RELATIVE_FILE_NAME (dir))
257 {
258 dir_as_prefix_to_free =
259 concatenated_filename (directory, dir, NULL);
260 if (dir_as_prefix_to_free == NULL)
261 {
262
263 failure_errno = errno;
264 goto failed;
265 }
266 dir_as_prefix = dir_as_prefix_to_free;
267 }
268 else
269 {
270 dir_as_prefix_to_free = NULL;
271 dir_as_prefix = dir;
272 }
273
274
275 for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++)
276 {
277 const char *suffix = suffixes[i];
278
279 #if defined _WIN32 && !defined __CYGWIN__
280
281
282 if ((*suffix != '\0') != progname_has_dot)
283 #endif
284 {
285
286 char *progpathname =
287 concatenated_filename (dir_as_prefix, progname, suffix);
288
289 if (progpathname == NULL)
290 {
291
292 failure_errno = errno;
293 free (dir_as_prefix_to_free);
294 goto failed;
295 }
296
297
298
299
300
301 if (eaccess (progpathname, X_OK) == 0)
302 {
303
304
305 struct stat statbuf;
306
307 if (stat (progpathname, &statbuf) >= 0)
308 {
309 if (! S_ISDIR (statbuf.st_mode))
310 {
311
312 if (strcmp (progpathname, progname) == 0)
313 {
314 free (progpathname);
315
316
317
318
319
320 progpathname =
321 (char *) malloc (2 + strlen (progname) + 1);
322 if (progpathname == NULL)
323 {
324
325 failure_errno = errno;
326 free (dir_as_prefix_to_free);
327 goto failed;
328 }
329 progpathname[0] = '.';
330 progpathname[1] = NATIVE_SLASH;
331 memcpy (progpathname + 2, progname,
332 strlen (progname) + 1);
333 }
334
335 free (dir_as_prefix_to_free);
336 free (path_copy);
337 return progpathname;
338 }
339
340 errno = EACCES;
341 }
342 }
343
344 if (errno != ENOENT)
345 failure_errno = errno;
346
347 free (progpathname);
348 }
349 }
350 #if defined _WIN32 && !defined __CYGWIN__
351 if (failure_errno == ENOENT && !progname_has_dot)
352 {
353
354
355
356 char *progpathname =
357 concatenated_filename (dir_as_prefix, progname, "");
358
359 if (progpathname == NULL)
360 {
361
362 failure_errno = errno;
363 free (dir_as_prefix_to_free);
364 goto failed;
365 }
366
367 if (eaccess (progpathname, X_OK) == 0)
368 {
369 struct stat statbuf;
370
371 if (stat (progpathname, &statbuf) >= 0)
372 {
373 if (! S_ISDIR (statbuf.st_mode))
374 errno = ENOEXEC;
375 else
376 errno = EACCES;
377 }
378 }
379
380 failure_errno = errno;
381
382 free (progpathname);
383 }
384 #endif
385
386 free (dir_as_prefix_to_free);
387
388 if (last)
389 break;
390 }
391
392 failed:
393
394 free (path_copy);
395
396 errno = failure_errno;
397 return NULL;
398 }
399 }