1 /* findcmd.c -- Functions to search for commands by name. */
3 /* Copyright (C) 1997-2012 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
24 #include "chartypes.h"
25 #include "bashtypes.h"
26 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
27 # include <sys/file.h>
30 #include "posixstat.h"
32 #if defined (HAVE_UNISTD_H)
45 #include "findcmd.h" /* matching prototypes and declarations */
51 extern int posixly_correct
;
52 extern int last_command_exit_value
;
54 /* Static functions defined and used in this file. */
55 static char *_find_user_command_internal
__P((const char *, int));
56 static char *find_user_command_internal
__P((const char *, int));
57 static char *find_user_command_in_path
__P((const char *, char *, int));
58 static char *find_in_path_element
__P((const char *, char *, int, int, struct stat
*));
59 static char *find_absolute_program
__P((const char *, int));
61 static char *get_next_path_element
__P((char *, int *));
63 /* The file name which we would try to execute, except that it isn't
64 possible to execute it. This is the first file that matches the
65 name that we are looking for while we are searching $PATH for a
66 suitable one to execute. If we cannot find a suitable executable
67 file, then we use this one. */
68 static char *file_to_lose_on
;
70 /* Non-zero if we should stat every command found in the hash table to
71 make sure it still exists. */
72 int check_hashed_filenames
;
74 /* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
75 encounters a `.' as the directory pathname while scanning the
76 list of possible pathnames; i.e., if `.' comes before the directory
77 containing the file of interest. */
78 int dot_found_in_search
= 0;
80 /* Return some flags based on information about this file.
81 The EXISTS bit is non-zero if the file is found.
82 The EXECABLE bit is non-zero the file is executble.
83 Zero is returned if the file is not found. */
91 /* Determine whether this file exists or not. */
92 if (stat (name
, &finfo
) < 0)
95 /* If the file is a directory, then it is not "executable" in the
96 sense of the shell. */
97 if (S_ISDIR (finfo
.st_mode
))
98 return (FS_EXISTS
|FS_DIRECTORY
);
102 #if defined (HAVE_EACCESS)
103 /* Use eaccess(2) if we have it to take things like ACLs and other
104 file access mechanisms into account. eaccess uses the effective
105 user and group IDs, not the real ones. We could use sh_eaccess,
106 but we don't want any special treatment for /dev/fd. */
107 if (eaccess (name
, X_OK
) == 0)
109 if (eaccess (name
, R_OK
) == 0)
114 /* We have to use access(2) to determine access because AFS does not
115 support Unix file system semantics. This may produce wrong
116 answers for non-AFS files when ruid != euid. I hate AFS. */
117 if (access (name
, X_OK
) == 0)
119 if (access (name
, R_OK
) == 0)
123 #else /* !HAVE_EACCESS && !AFS */
125 /* Find out if the file is actually executable. By definition, the
126 only other criteria is that the file has an execute bit set that
127 we can use. The same with whether or not a file is readable. */
129 /* Root only requires execute permission for any of owner, group or
130 others to be able to exec a file, and can read any file. */
131 if (current_user
.euid
== (uid_t
)0)
134 if (finfo
.st_mode
& S_IXUGO
)
139 /* If we are the owner of the file, the owner bits apply. */
140 if (current_user
.euid
== finfo
.st_uid
)
142 if (finfo
.st_mode
& S_IXUSR
)
144 if (finfo
.st_mode
& S_IRUSR
)
148 /* If we are in the owning group, the group permissions apply. */
149 else if (group_member (finfo
.st_gid
))
151 if (finfo
.st_mode
& S_IXGRP
)
153 if (finfo
.st_mode
& S_IRGRP
)
157 /* Else we check whether `others' have permission to execute the file */
160 if (finfo
.st_mode
& S_IXOTH
)
162 if (finfo
.st_mode
& S_IROTH
)
170 /* Return non-zero if FILE exists and is executable.
171 Note that this function is the definition of what an
172 executable file is; do not change this unless YOU know
173 what an executable file is. */
175 executable_file (file
)
180 s
= file_status (file
);
182 if (s
& FS_DIRECTORY
)
183 errno
= EISDIR
; /* let's see if we can improve error messages */
185 return ((s
& FS_EXECABLE
) && ((s
& FS_DIRECTORY
) == 0));
192 return (file_status (file
) & FS_DIRECTORY
);
196 executable_or_directory (file
)
201 s
= file_status (file
);
202 return ((s
& FS_EXECABLE
) || (s
& FS_DIRECTORY
));
205 /* Locate the executable file referenced by NAME, searching along
206 the contents of the shell PATH variable. Return a new string
207 which is the full pathname to the file, or NULL if the file
208 couldn't be found. If a file is found that isn't executable,
209 and that is the only match, then return that. */
211 find_user_command (name
)
214 return (find_user_command_internal (name
, FS_EXEC_PREFERRED
|FS_NODIRS
));
217 /* Locate the file referenced by NAME, searching along the contents
218 of the shell PATH variable. Return a new string which is the full
219 pathname to the file, or NULL if the file couldn't be found. This
220 returns the first readable file found; designed to be used to look
221 for shell scripts or files to source. */
223 find_path_file (name
)
226 return (find_user_command_internal (name
, FS_READABLE
));
230 _find_user_command_internal (name
, flags
)
234 char *path_list
, *cmd
;
237 /* Search for the value of PATH in both the temporary environments and
238 in the regular list of variables. */
239 if (var
= find_variable_tempenv ("PATH")) /* XXX could be array? */
240 path_list
= value_cell (var
);
242 path_list
= (char *)NULL
;
244 if (path_list
== 0 || *path_list
== '\0')
245 return (savestring (name
));
247 cmd
= find_user_command_in_path (name
, path_list
, flags
);
253 find_user_command_internal (name
, flags
)
260 dotexe
= (char *)xmalloc (strlen (name
) + 5);
261 strcpy (dotexe
, name
);
262 strcat (dotexe
, ".exe");
263 res
= _find_user_command_internal (dotexe
, flags
);
266 res
= _find_user_command_internal (name
, flags
);
269 return (_find_user_command_internal (name
, flags
));
273 /* Return the next element from PATH_LIST, a colon separated list of
274 paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST;
275 the index is modified by this function.
276 Return the next element of PATH_LIST or NULL if there are no more. */
278 get_next_path_element (path_list
, path_index_pointer
)
280 int *path_index_pointer
;
284 path
= extract_colon_unit (path_list
, path_index_pointer
);
292 path
= savestring (".");
298 /* Look for PATHNAME in $PATH. Returns either the hashed command
299 corresponding to PATHNAME or the first instance of PATHNAME found
300 in $PATH. If (FLAGS&1) is non-zero, insert the instance of PATHNAME
301 found in $PATH into the command hash table. Returns a newly-allocated
304 search_for_command (pathname
, flags
)
305 const char *pathname
;
308 char *hashed_file
, *command
;
312 hashed_file
= command
= (char *)NULL
;
314 /* If PATH is in the temporary environment for this command, don't use the
315 hash table to search for the full pathname. */
316 path
= find_variable_tempenv ("PATH");
317 temp_path
= path
&& tempvar_p (path
);
318 if (temp_path
== 0 && path
)
319 path
= (SHELL_VAR
*)NULL
;
321 /* Don't waste time trying to find hashed data for a pathname
322 that is already completely specified or if we're using a command-
323 specific value for PATH. */
324 if (path
== 0 && absolute_program (pathname
) == 0)
325 hashed_file
= phash_search (pathname
);
327 /* If a command found in the hash table no longer exists, we need to
328 look for it in $PATH. Thank you Posix.2. This forces us to stat
329 every command found in the hash table. */
331 if (hashed_file
&& (posixly_correct
|| check_hashed_filenames
))
333 st
= file_status (hashed_file
);
334 if ((st
& (FS_EXISTS
|FS_EXECABLE
)) != (FS_EXISTS
|FS_EXECABLE
))
336 phash_remove (pathname
);
338 hashed_file
= (char *)NULL
;
343 command
= hashed_file
;
344 else if (absolute_program (pathname
))
345 /* A command containing a slash is not looked up in PATH or saved in
347 command
= savestring (pathname
);
350 /* If $PATH is in the temporary environment, we've already retrieved
351 it, so don't bother trying again. */
354 command
= find_user_command_in_path (pathname
, value_cell (path
),
355 FS_EXEC_PREFERRED
|FS_NODIRS
);
358 command
= find_user_command (pathname
);
359 if (command
&& hashing_enabled
&& temp_path
== 0 && (flags
& 1))
360 phash_insert ((char *)pathname
, command
, dot_found_in_search
, 1); /* XXX fix const later */
366 user_command_matches (name
, flags
, state
)
371 int path_index
, name_len
;
372 char *path_list
, *path_element
, *match
;
374 static char **match_list
= NULL
;
375 static int match_list_size
= 0;
376 static int match_index
= 0;
380 /* Create the list of matches. */
384 match_list
= strvec_create (match_list_size
);
387 /* Clear out the old match list. */
388 for (i
= 0; i
< match_list_size
; i
++)
391 /* We haven't found any files yet. */
394 if (absolute_program (name
))
396 match_list
[0] = find_absolute_program (name
, flags
);
397 match_list
[1] = (char *)NULL
;
398 path_list
= (char *)NULL
;
402 name_len
= strlen (name
);
403 file_to_lose_on
= (char *)NULL
;
404 dot_found_in_search
= 0;
405 if (stat (".", &dotinfo
) < 0)
406 dotinfo
.st_dev
= dotinfo
.st_ino
= 0; /* so same_file won't match */
407 path_list
= get_string_value ("PATH");
411 while (path_list
&& path_list
[path_index
])
413 path_element
= get_next_path_element (path_list
, &path_index
);
415 if (path_element
== 0)
418 match
= find_in_path_element (name
, path_element
, flags
, name_len
, &dotinfo
);
425 if (match_index
+ 1 == match_list_size
)
427 match_list_size
+= 10;
428 match_list
= strvec_resize (match_list
, (match_list_size
+ 1));
431 match_list
[match_index
++] = match
;
432 match_list
[match_index
] = (char *)NULL
;
433 FREE (file_to_lose_on
);
434 file_to_lose_on
= (char *)NULL
;
437 /* We haven't returned any strings yet. */
441 match
= match_list
[match_index
];
450 find_absolute_program (name
, flags
)
456 st
= file_status (name
);
458 /* If the file doesn't exist, quit now. */
459 if ((st
& FS_EXISTS
) == 0)
460 return ((char *)NULL
);
462 /* If we only care about whether the file exists or not, return
463 this filename. Otherwise, maybe we care about whether this
464 file is executable. If it is, and that is what we want, return it. */
465 if ((flags
& FS_EXISTS
) || ((flags
& FS_EXEC_ONLY
) && (st
& FS_EXECABLE
)))
466 return (savestring (name
));
472 find_in_path_element (name
, path
, flags
, name_len
, dotinfop
)
476 struct stat
*dotinfop
;
479 char *full_path
, *xpath
;
481 xpath
= (*path
== '~') ? bash_tilde_expand (path
, 0) : path
;
483 /* Remember the location of "." in the path, in all its forms
484 (as long as they begin with a `.', e.g. `./.') */
485 if (dot_found_in_search
== 0 && *xpath
== '.')
486 dot_found_in_search
= same_file (".", xpath
, dotinfop
, (struct stat
*)NULL
);
488 full_path
= sh_makepath (xpath
, name
, 0);
490 status
= file_status (full_path
);
495 if ((status
& FS_EXISTS
) == 0)
498 return ((char *)NULL
);
501 /* The file exists. If the caller simply wants the first file, here it is. */
502 if (flags
& FS_EXISTS
)
505 /* If we have a readable file, and the caller wants a readable file, this
507 if ((flags
& FS_READABLE
) && (status
& FS_READABLE
))
510 /* If the file is executable, then it satisfies the cases of
511 EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
512 if ((status
& FS_EXECABLE
) && (flags
& (FS_EXEC_ONLY
|FS_EXEC_PREFERRED
)) &&
513 (((flags
& FS_NODIRS
) == 0) || ((status
& FS_DIRECTORY
) == 0)))
515 FREE (file_to_lose_on
);
516 file_to_lose_on
= (char *)NULL
;
520 /* The file is not executable, but it does exist. If we prefer
521 an executable, then remember this one if it is the first one
523 if ((flags
& FS_EXEC_PREFERRED
) && file_to_lose_on
== 0)
524 file_to_lose_on
= savestring (full_path
);
526 /* If we want only executable files, or we don't want directories and
527 this file is a directory, or we want a readable file and this file
528 isn't readable, fail. */
529 if ((flags
& (FS_EXEC_ONLY
|FS_EXEC_PREFERRED
)) ||
530 ((flags
& FS_NODIRS
) && (status
& FS_DIRECTORY
)) ||
531 ((flags
& FS_READABLE
) && (status
& FS_READABLE
) == 0))
534 return ((char *)NULL
);
540 /* This does the dirty work for find_user_command_internal () and
541 user_command_matches ().
542 NAME is the name of the file to search for.
543 PATH_LIST is a colon separated list of directories to search.
544 FLAGS contains bit fields which control the files which are eligible.
546 FS_EXEC_ONLY: The file must be an executable to be found.
547 FS_EXEC_PREFERRED: If we can't find an executable, then the
548 the first file matching NAME will do.
549 FS_EXISTS: The first file found will do.
550 FS_NODIRS: Don't find any directories.
553 find_user_command_in_path (name
, path_list
, flags
)
558 char *full_path
, *path
;
559 int path_index
, name_len
;
562 /* We haven't started looking, so we certainly haven't seen
563 a `.' as the directory path yet. */
564 dot_found_in_search
= 0;
566 if (absolute_program (name
))
568 full_path
= find_absolute_program (name
, flags
);
572 if (path_list
== 0 || *path_list
== '\0')
573 return (savestring (name
)); /* XXX */
575 file_to_lose_on
= (char *)NULL
;
576 name_len
= strlen (name
);
577 if (stat (".", &dotinfo
) < 0)
578 dotinfo
.st_dev
= dotinfo
.st_ino
= 0;
581 while (path_list
[path_index
])
583 /* Allow the user to interrupt out of a lengthy path search. */
586 path
= get_next_path_element (path_list
, &path_index
);
590 /* Side effects: sets dot_found_in_search, possibly sets
592 full_path
= find_in_path_element (name
, path
, flags
, name_len
, &dotinfo
);
595 /* This should really be in find_in_path_element, but there isn't the
596 right combination of flags. */
597 if (full_path
&& is_directory (full_path
))
605 FREE (file_to_lose_on
);
610 /* We didn't find exactly what the user was looking for. Return
611 the contents of FILE_TO_LOSE_ON which is NULL when the search
612 required an executable, or non-NULL if a file was found and the
613 search would accept a non-executable as a last resort. If the
614 caller specified FS_NODIRS, and file_to_lose_on is a directory,
616 if (file_to_lose_on
&& (flags
& FS_NODIRS
) && is_directory (file_to_lose_on
))
618 free (file_to_lose_on
);
619 file_to_lose_on
= (char *)NULL
;
622 return (file_to_lose_on
);