]> git.ipfire.org Git - thirdparty/bash.git/blob - findcmd.c
Bash-4.1 distribution source
[thirdparty/bash.git] / findcmd.c
1 /* findcmd.c -- Functions to search for commands by name. */
2
3 /* Copyright (C) 1997-2009 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include "chartypes.h"
25 #include "bashtypes.h"
26 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
27 # include <sys/file.h>
28 #endif
29 #include "filecntl.h"
30 #include "posixstat.h"
31
32 #if defined (HAVE_UNISTD_H)
33 # include <unistd.h>
34 #endif
35
36 #include "bashansi.h"
37
38 #include "memalloc.h"
39 #include "shell.h"
40 #include "flags.h"
41 #include "hashlib.h"
42 #include "pathexp.h"
43 #include "hashcmd.h"
44 #include "findcmd.h" /* matching prototypes and declarations */
45
46 extern int posixly_correct;
47
48 /* Static functions defined and used in this file. */
49 static char *_find_user_command_internal __P((const char *, int));
50 static char *find_user_command_internal __P((const char *, int));
51 static char *find_user_command_in_path __P((const char *, char *, int));
52 static char *find_in_path_element __P((const char *, char *, int, int, struct stat *));
53 static char *find_absolute_program __P((const char *, int));
54
55 static char *get_next_path_element __P((char *, int *));
56
57 /* The file name which we would try to execute, except that it isn't
58 possible to execute it. This is the first file that matches the
59 name that we are looking for while we are searching $PATH for a
60 suitable one to execute. If we cannot find a suitable executable
61 file, then we use this one. */
62 static char *file_to_lose_on;
63
64 /* Non-zero if we should stat every command found in the hash table to
65 make sure it still exists. */
66 int check_hashed_filenames;
67
68 /* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
69 encounters a `.' as the directory pathname while scanning the
70 list of possible pathnames; i.e., if `.' comes before the directory
71 containing the file of interest. */
72 int dot_found_in_search = 0;
73
74 /* Return some flags based on information about this file.
75 The EXISTS bit is non-zero if the file is found.
76 The EXECABLE bit is non-zero the file is executble.
77 Zero is returned if the file is not found. */
78 int
79 file_status (name)
80 const char *name;
81 {
82 struct stat finfo;
83 int r;
84
85 /* Determine whether this file exists or not. */
86 if (stat (name, &finfo) < 0)
87 return (0);
88
89 /* If the file is a directory, then it is not "executable" in the
90 sense of the shell. */
91 if (S_ISDIR (finfo.st_mode))
92 return (FS_EXISTS|FS_DIRECTORY);
93
94 r = FS_EXISTS;
95
96 #if defined (HAVE_EACCESS)
97 /* Use eaccess(2) if we have it to take things like ACLs and other
98 file access mechanisms into account. eaccess uses the effective
99 user and group IDs, not the real ones. We could use sh_eaccess,
100 but we don't want any special treatment for /dev/fd. */
101 if (eaccess (name, X_OK) == 0)
102 r |= FS_EXECABLE;
103 if (eaccess (name, R_OK) == 0)
104 r |= FS_READABLE;
105
106 return r;
107 #elif defined (AFS)
108 /* We have to use access(2) to determine access because AFS does not
109 support Unix file system semantics. This may produce wrong
110 answers for non-AFS files when ruid != euid. I hate AFS. */
111 if (access (name, X_OK) == 0)
112 r |= FS_EXECABLE;
113 if (access (name, R_OK) == 0)
114 r |= FS_READABLE;
115
116 return r;
117 #else /* !HAVE_EACCESS && !AFS */
118
119 /* Find out if the file is actually executable. By definition, the
120 only other criteria is that the file has an execute bit set that
121 we can use. The same with whether or not a file is readable. */
122
123 /* Root only requires execute permission for any of owner, group or
124 others to be able to exec a file, and can read any file. */
125 if (current_user.euid == (uid_t)0)
126 {
127 r |= FS_READABLE;
128 if (finfo.st_mode & S_IXUGO)
129 r |= FS_EXECABLE;
130 return r;
131 }
132
133 /* If we are the owner of the file, the owner bits apply. */
134 if (current_user.euid == finfo.st_uid)
135 {
136 if (finfo.st_mode & S_IXUSR)
137 r |= FS_EXECABLE;
138 if (finfo.st_mode & S_IRUSR)
139 r |= FS_READABLE;
140 }
141
142 /* If we are in the owning group, the group permissions apply. */
143 else if (group_member (finfo.st_gid))
144 {
145 if (finfo.st_mode & S_IXGRP)
146 r |= FS_EXECABLE;
147 if (finfo.st_mode & S_IRGRP)
148 r |= FS_READABLE;
149 }
150
151 /* Else we check whether `others' have permission to execute the file */
152 else
153 {
154 if (finfo.st_mode & S_IXOTH)
155 r |= FS_EXECABLE;
156 if (finfo.st_mode & S_IROTH)
157 r |= FS_READABLE;
158 }
159
160 return r;
161 #endif /* !AFS */
162 }
163
164 /* Return non-zero if FILE exists and is executable.
165 Note that this function is the definition of what an
166 executable file is; do not change this unless YOU know
167 what an executable file is. */
168 int
169 executable_file (file)
170 const char *file;
171 {
172 int s;
173
174 s = file_status (file);
175 return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
176 }
177
178 int
179 is_directory (file)
180 const char *file;
181 {
182 return (file_status (file) & FS_DIRECTORY);
183 }
184
185 int
186 executable_or_directory (file)
187 const char *file;
188 {
189 int s;
190
191 s = file_status (file);
192 return ((s & FS_EXECABLE) || (s & FS_DIRECTORY));
193 }
194
195 /* Locate the executable file referenced by NAME, searching along
196 the contents of the shell PATH variable. Return a new string
197 which is the full pathname to the file, or NULL if the file
198 couldn't be found. If a file is found that isn't executable,
199 and that is the only match, then return that. */
200 char *
201 find_user_command (name)
202 const char *name;
203 {
204 return (find_user_command_internal (name, FS_EXEC_PREFERRED|FS_NODIRS));
205 }
206
207 /* Locate the file referenced by NAME, searching along the contents
208 of the shell PATH variable. Return a new string which is the full
209 pathname to the file, or NULL if the file couldn't be found. This
210 returns the first readable file found; designed to be used to look
211 for shell scripts or files to source. */
212 char *
213 find_path_file (name)
214 const char *name;
215 {
216 return (find_user_command_internal (name, FS_READABLE));
217 }
218
219 static char *
220 _find_user_command_internal (name, flags)
221 const char *name;
222 int flags;
223 {
224 char *path_list, *cmd;
225 SHELL_VAR *var;
226
227 /* Search for the value of PATH in both the temporary environments and
228 in the regular list of variables. */
229 if (var = find_variable_internal ("PATH", 1)) /* XXX could be array? */
230 path_list = value_cell (var);
231 else
232 path_list = (char *)NULL;
233
234 if (path_list == 0 || *path_list == '\0')
235 return (savestring (name));
236
237 cmd = find_user_command_in_path (name, path_list, flags);
238
239 return (cmd);
240 }
241
242 static char *
243 find_user_command_internal (name, flags)
244 const char *name;
245 int flags;
246 {
247 #ifdef __WIN32__
248 char *res, *dotexe;
249
250 dotexe = (char *)xmalloc (strlen (name) + 5);
251 strcpy (dotexe, name);
252 strcat (dotexe, ".exe");
253 res = _find_user_command_internal (dotexe, flags);
254 free (dotexe);
255 if (res == 0)
256 res = _find_user_command_internal (name, flags);
257 return res;
258 #else
259 return (_find_user_command_internal (name, flags));
260 #endif
261 }
262
263 /* Return the next element from PATH_LIST, a colon separated list of
264 paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST;
265 the index is modified by this function.
266 Return the next element of PATH_LIST or NULL if there are no more. */
267 static char *
268 get_next_path_element (path_list, path_index_pointer)
269 char *path_list;
270 int *path_index_pointer;
271 {
272 char *path;
273
274 path = extract_colon_unit (path_list, path_index_pointer);
275
276 if (path == 0)
277 return (path);
278
279 if (*path == '\0')
280 {
281 free (path);
282 path = savestring (".");
283 }
284
285 return (path);
286 }
287
288 /* Look for PATHNAME in $PATH. Returns either the hashed command
289 corresponding to PATHNAME or the first instance of PATHNAME found
290 in $PATH. Returns a newly-allocated string. */
291 char *
292 search_for_command (pathname)
293 const char *pathname;
294 {
295 char *hashed_file, *command;
296 int temp_path, st;
297 SHELL_VAR *path;
298
299 hashed_file = command = (char *)NULL;
300
301 /* If PATH is in the temporary environment for this command, don't use the
302 hash table to search for the full pathname. */
303 path = find_variable_internal ("PATH", 1);
304 temp_path = path && tempvar_p (path);
305 if (temp_path == 0 && path)
306 path = (SHELL_VAR *)NULL;
307
308 /* Don't waste time trying to find hashed data for a pathname
309 that is already completely specified or if we're using a command-
310 specific value for PATH. */
311 if (path == 0 && absolute_program (pathname) == 0)
312 hashed_file = phash_search (pathname);
313
314 /* If a command found in the hash table no longer exists, we need to
315 look for it in $PATH. Thank you Posix.2. This forces us to stat
316 every command found in the hash table. */
317
318 if (hashed_file && (posixly_correct || check_hashed_filenames))
319 {
320 st = file_status (hashed_file);
321 if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
322 {
323 phash_remove (pathname);
324 free (hashed_file);
325 hashed_file = (char *)NULL;
326 }
327 }
328
329 if (hashed_file)
330 command = hashed_file;
331 else if (absolute_program (pathname))
332 /* A command containing a slash is not looked up in PATH or saved in
333 the hash table. */
334 command = savestring (pathname);
335 else
336 {
337 /* If $PATH is in the temporary environment, we've already retrieved
338 it, so don't bother trying again. */
339 if (temp_path)
340 {
341 command = find_user_command_in_path (pathname, value_cell (path),
342 FS_EXEC_PREFERRED|FS_NODIRS);
343 }
344 else
345 command = find_user_command (pathname);
346 if (command && hashing_enabled && temp_path == 0)
347 phash_insert ((char *)pathname, command, dot_found_in_search, 1); /* XXX fix const later */
348 }
349 return (command);
350 }
351
352 char *
353 user_command_matches (name, flags, state)
354 const char *name;
355 int flags, state;
356 {
357 register int i;
358 int path_index, name_len;
359 char *path_list, *path_element, *match;
360 struct stat dotinfo;
361 static char **match_list = NULL;
362 static int match_list_size = 0;
363 static int match_index = 0;
364
365 if (state == 0)
366 {
367 /* Create the list of matches. */
368 if (match_list == 0)
369 {
370 match_list_size = 5;
371 match_list = strvec_create (match_list_size);
372 }
373
374 /* Clear out the old match list. */
375 for (i = 0; i < match_list_size; i++)
376 match_list[i] = 0;
377
378 /* We haven't found any files yet. */
379 match_index = 0;
380
381 if (absolute_program (name))
382 {
383 match_list[0] = find_absolute_program (name, flags);
384 match_list[1] = (char *)NULL;
385 path_list = (char *)NULL;
386 }
387 else
388 {
389 name_len = strlen (name);
390 file_to_lose_on = (char *)NULL;
391 dot_found_in_search = 0;
392 stat (".", &dotinfo);
393 path_list = get_string_value ("PATH");
394 path_index = 0;
395 }
396
397 while (path_list && path_list[path_index])
398 {
399 path_element = get_next_path_element (path_list, &path_index);
400
401 if (path_element == 0)
402 break;
403
404 match = find_in_path_element (name, path_element, flags, name_len, &dotinfo);
405
406 free (path_element);
407
408 if (match == 0)
409 continue;
410
411 if (match_index + 1 == match_list_size)
412 {
413 match_list_size += 10;
414 match_list = strvec_resize (match_list, (match_list_size + 1));
415 }
416
417 match_list[match_index++] = match;
418 match_list[match_index] = (char *)NULL;
419 FREE (file_to_lose_on);
420 file_to_lose_on = (char *)NULL;
421 }
422
423 /* We haven't returned any strings yet. */
424 match_index = 0;
425 }
426
427 match = match_list[match_index];
428
429 if (match)
430 match_index++;
431
432 return (match);
433 }
434
435 static char *
436 find_absolute_program (name, flags)
437 const char *name;
438 int flags;
439 {
440 int st;
441
442 st = file_status (name);
443
444 /* If the file doesn't exist, quit now. */
445 if ((st & FS_EXISTS) == 0)
446 return ((char *)NULL);
447
448 /* If we only care about whether the file exists or not, return
449 this filename. Otherwise, maybe we care about whether this
450 file is executable. If it is, and that is what we want, return it. */
451 if ((flags & FS_EXISTS) || ((flags & FS_EXEC_ONLY) && (st & FS_EXECABLE)))
452 return (savestring (name));
453
454 return (NULL);
455 }
456
457 static char *
458 find_in_path_element (name, path, flags, name_len, dotinfop)
459 const char *name;
460 char *path;
461 int flags, name_len;
462 struct stat *dotinfop;
463 {
464 int status;
465 char *full_path, *xpath;
466
467 xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path;
468
469 /* Remember the location of "." in the path, in all its forms
470 (as long as they begin with a `.', e.g. `./.') */
471 if (dot_found_in_search == 0 && *xpath == '.')
472 dot_found_in_search = same_file (".", xpath, dotinfop, (struct stat *)NULL);
473
474 full_path = sh_makepath (xpath, name, 0);
475
476 status = file_status (full_path);
477
478 if (xpath != path)
479 free (xpath);
480
481 if ((status & FS_EXISTS) == 0)
482 {
483 free (full_path);
484 return ((char *)NULL);
485 }
486
487 /* The file exists. If the caller simply wants the first file, here it is. */
488 if (flags & FS_EXISTS)
489 return (full_path);
490
491 /* If we have a readable file, and the caller wants a readable file, this
492 is it. */
493 if ((flags & FS_READABLE) && (status & FS_READABLE))
494 return (full_path);
495
496 /* If the file is executable, then it satisfies the cases of
497 EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
498 if ((status & FS_EXECABLE) && (flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) &&
499 (((flags & FS_NODIRS) == 0) || ((status & FS_DIRECTORY) == 0)))
500 {
501 FREE (file_to_lose_on);
502 file_to_lose_on = (char *)NULL;
503 return (full_path);
504 }
505
506 /* The file is not executable, but it does exist. If we prefer
507 an executable, then remember this one if it is the first one
508 we have found. */
509 if ((flags & FS_EXEC_PREFERRED) && file_to_lose_on == 0)
510 file_to_lose_on = savestring (full_path);
511
512 /* If we want only executable files, or we don't want directories and
513 this file is a directory, or we want a readable file and this file
514 isn't readable, fail. */
515 if ((flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) ||
516 ((flags & FS_NODIRS) && (status & FS_DIRECTORY)) ||
517 ((flags & FS_READABLE) && (status & FS_READABLE) == 0))
518 {
519 free (full_path);
520 return ((char *)NULL);
521 }
522 else
523 return (full_path);
524 }
525
526 /* This does the dirty work for find_user_command_internal () and
527 user_command_matches ().
528 NAME is the name of the file to search for.
529 PATH_LIST is a colon separated list of directories to search.
530 FLAGS contains bit fields which control the files which are eligible.
531 Some values are:
532 FS_EXEC_ONLY: The file must be an executable to be found.
533 FS_EXEC_PREFERRED: If we can't find an executable, then the
534 the first file matching NAME will do.
535 FS_EXISTS: The first file found will do.
536 FS_NODIRS: Don't find any directories.
537 */
538 static char *
539 find_user_command_in_path (name, path_list, flags)
540 const char *name;
541 char *path_list;
542 int flags;
543 {
544 char *full_path, *path;
545 int path_index, name_len;
546 struct stat dotinfo;
547
548 /* We haven't started looking, so we certainly haven't seen
549 a `.' as the directory path yet. */
550 dot_found_in_search = 0;
551
552 if (absolute_program (name))
553 {
554 full_path = find_absolute_program (name, flags);
555 return (full_path);
556 }
557
558 if (path_list == 0 || *path_list == '\0')
559 return (savestring (name)); /* XXX */
560
561 file_to_lose_on = (char *)NULL;
562 name_len = strlen (name);
563 stat (".", &dotinfo);
564 path_index = 0;
565
566 while (path_list[path_index])
567 {
568 /* Allow the user to interrupt out of a lengthy path search. */
569 QUIT;
570
571 path = get_next_path_element (path_list, &path_index);
572 if (path == 0)
573 break;
574
575 /* Side effects: sets dot_found_in_search, possibly sets
576 file_to_lose_on. */
577 full_path = find_in_path_element (name, path, flags, name_len, &dotinfo);
578 free (path);
579
580 /* This should really be in find_in_path_element, but there isn't the
581 right combination of flags. */
582 if (full_path && is_directory (full_path))
583 {
584 free (full_path);
585 continue;
586 }
587
588 if (full_path)
589 {
590 FREE (file_to_lose_on);
591 return (full_path);
592 }
593 }
594
595 /* We didn't find exactly what the user was looking for. Return
596 the contents of FILE_TO_LOSE_ON which is NULL when the search
597 required an executable, or non-NULL if a file was found and the
598 search would accept a non-executable as a last resort. If the
599 caller specified FS_NODIRS, and file_to_lose_on is a directory,
600 return NULL. */
601 if (file_to_lose_on && (flags & FS_NODIRS) && is_directory (file_to_lose_on))
602 {
603 free (file_to_lose_on);
604 file_to_lose_on = (char *)NULL;
605 }
606
607 return (file_to_lose_on);
608 }