1 /* findcmd.c -- Functions to search for commands by name. */
3 /* Copyright (C) 1997-2015 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 */
47 #include <glob/strmatch.h>
53 extern int posixly_correct
;
54 extern int last_command_exit_value
;
56 /* Static functions defined and used in this file. */
57 static char *_find_user_command_internal
__P((const char *, int));
58 static char *find_user_command_internal
__P((const char *, int));
59 static char *find_user_command_in_path
__P((const char *, char *, int));
60 static char *find_in_path_element
__P((const char *, char *, int, int, struct stat
*));
61 static char *find_absolute_program
__P((const char *, int));
63 static char *get_next_path_element
__P((char *, int *));
65 /* The file name which we would try to execute, except that it isn't
66 possible to execute it. This is the first file that matches the
67 name that we are looking for while we are searching $PATH for a
68 suitable one to execute. If we cannot find a suitable executable
69 file, then we use this one. */
70 static char *file_to_lose_on
;
72 /* Non-zero if we should stat every command found in the hash table to
73 make sure it still exists. */
74 int check_hashed_filenames
= CHECKHASH_DEFAULT
;
76 /* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
77 encounters a `.' as the directory pathname while scanning the
78 list of possible pathnames; i.e., if `.' comes before the directory
79 containing the file of interest. */
80 int dot_found_in_search
= 0;
82 /* Set up EXECIGNORE; a blacklist of patterns that executable files should not
84 static struct ignorevar execignore
=
94 setup_exec_ignore (varname
)
97 setup_ignore_patterns (&execignore
);
101 exec_name_should_ignore (name
)
106 for (p
= execignore
.ignores
; p
&& p
->val
; p
++)
107 if (strmatch (p
->val
, (char *)name
, FNMATCH_EXTFLAG
|FNM_CASEFOLD
) != FNM_NOMATCH
)
112 /* Return some flags based on information about this file.
113 The EXISTS bit is non-zero if the file is found.
114 The EXECABLE bit is non-zero the file is executble.
115 Zero is returned if the file is not found. */
123 /* Determine whether this file exists or not. */
124 if (stat (name
, &finfo
) < 0)
127 /* If the file is a directory, then it is not "executable" in the
128 sense of the shell. */
129 if (S_ISDIR (finfo
.st_mode
))
130 return (FS_EXISTS
|FS_DIRECTORY
);
134 #if defined (HAVE_EACCESS)
135 /* Use eaccess(2) if we have it to take things like ACLs and other
136 file access mechanisms into account. eaccess uses the effective
137 user and group IDs, not the real ones. We could use sh_eaccess,
138 but we don't want any special treatment for /dev/fd. */
139 if (exec_name_should_ignore (name
) == 0 && eaccess (name
, X_OK
) == 0)
141 if (eaccess (name
, R_OK
) == 0)
146 /* We have to use access(2) to determine access because AFS does not
147 support Unix file system semantics. This may produce wrong
148 answers for non-AFS files when ruid != euid. I hate AFS. */
149 if (exec_name_should_ignore (name
) == 0 && access (name
, X_OK
) == 0)
151 if (access (name
, R_OK
) == 0)
155 #else /* !HAVE_EACCESS && !AFS */
157 /* Find out if the file is actually executable. By definition, the
158 only other criteria is that the file has an execute bit set that
159 we can use. The same with whether or not a file is readable. */
161 /* Root only requires execute permission for any of owner, group or
162 others to be able to exec a file, and can read any file. */
163 if (current_user
.euid
== (uid_t
)0)
166 if (exec_name_should_ignore (name
) == 0 && (finfo
.st_mode
& S_IXUGO
))
171 /* If we are the owner of the file, the owner bits apply. */
172 if (current_user
.euid
== finfo
.st_uid
)
174 if (exec_name_should_ignore (name
) == 0 && (finfo
.st_mode
& S_IXUSR
))
176 if (finfo
.st_mode
& S_IRUSR
)
180 /* If we are in the owning group, the group permissions apply. */
181 else if (group_member (finfo
.st_gid
))
183 if (exec_name_should_ignore (name
) == 0 && (finfo
.st_mode
& S_IXGRP
))
185 if (finfo
.st_mode
& S_IRGRP
)
189 /* Else we check whether `others' have permission to execute the file */
192 if (exec_name_should_ignore (name
) == 0 && finfo
.st_mode
& S_IXOTH
)
194 if (finfo
.st_mode
& S_IROTH
)
202 /* Return non-zero if FILE exists and is executable.
203 Note that this function is the definition of what an
204 executable file is; do not change this unless YOU know
205 what an executable file is. */
207 executable_file (file
)
212 s
= file_status (file
);
214 if (s
& FS_DIRECTORY
)
215 errno
= EISDIR
; /* let's see if we can improve error messages */
217 return ((s
& FS_EXECABLE
) && ((s
& FS_DIRECTORY
) == 0));
224 return (file_status (file
) & FS_DIRECTORY
);
228 executable_or_directory (file
)
233 s
= file_status (file
);
234 return ((s
& FS_EXECABLE
) || (s
& FS_DIRECTORY
));
237 /* Locate the executable file referenced by NAME, searching along
238 the contents of the shell PATH variable. Return a new string
239 which is the full pathname to the file, or NULL if the file
240 couldn't be found. If a file is found that isn't executable,
241 and that is the only match, then return that. */
243 find_user_command (name
)
246 return (find_user_command_internal (name
, FS_EXEC_PREFERRED
|FS_NODIRS
));
249 /* Locate the file referenced by NAME, searching along the contents
250 of the shell PATH variable. Return a new string which is the full
251 pathname to the file, or NULL if the file couldn't be found. This
252 returns the first readable file found; designed to be used to look
253 for shell scripts or files to source. */
255 find_path_file (name
)
258 return (find_user_command_internal (name
, FS_READABLE
));
262 _find_user_command_internal (name
, flags
)
266 char *path_list
, *cmd
;
269 /* Search for the value of PATH in both the temporary environments and
270 in the regular list of variables. */
271 if (var
= find_variable_tempenv ("PATH")) /* XXX could be array? */
272 path_list
= value_cell (var
);
274 path_list
= (char *)NULL
;
276 if (path_list
== 0 || *path_list
== '\0')
277 return (savestring (name
));
279 cmd
= find_user_command_in_path (name
, path_list
, flags
);
285 find_user_command_internal (name
, flags
)
292 dotexe
= (char *)xmalloc (strlen (name
) + 5);
293 strcpy (dotexe
, name
);
294 strcat (dotexe
, ".exe");
295 res
= _find_user_command_internal (dotexe
, flags
);
298 res
= _find_user_command_internal (name
, flags
);
301 return (_find_user_command_internal (name
, flags
));
305 /* Return the next element from PATH_LIST, a colon separated list of
306 paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST;
307 the index is modified by this function.
308 Return the next element of PATH_LIST or NULL if there are no more. */
310 get_next_path_element (path_list
, path_index_pointer
)
312 int *path_index_pointer
;
316 path
= extract_colon_unit (path_list
, path_index_pointer
);
324 path
= savestring (".");
330 /* Look for PATHNAME in $PATH. Returns either the hashed command
331 corresponding to PATHNAME or the first instance of PATHNAME found
332 in $PATH. If (FLAGS&CMDSRCH_HASH) is non-zero, insert the instance of
333 PATHNAME found in $PATH into the command hash table. If (FLAGS&CMDSRCH_STDPATH)
334 is non-zero, we are running in a `command -p' environment and should use
335 the Posix standard path.
336 Returns a newly-allocated string. */
338 search_for_command (pathname
, flags
)
339 const char *pathname
;
342 char *hashed_file
, *command
, *pathlist
;
346 hashed_file
= command
= (char *)NULL
;
348 /* If PATH is in the temporary environment for this command, don't use the
349 hash table to search for the full pathname. */
350 path
= find_variable_tempenv ("PATH");
351 temp_path
= path
&& tempvar_p (path
);
353 /* Don't waste time trying to find hashed data for a pathname
354 that is already completely specified or if we're using a command-
355 specific value for PATH. */
356 if (temp_path
== 0 && absolute_program (pathname
) == 0)
357 hashed_file
= phash_search (pathname
);
359 /* If a command found in the hash table no longer exists, we need to
360 look for it in $PATH. Thank you Posix.2. This forces us to stat
361 every command found in the hash table. */
363 if (hashed_file
&& (posixly_correct
|| check_hashed_filenames
))
365 st
= file_status (hashed_file
);
366 if ((st
& (FS_EXISTS
|FS_EXECABLE
)) != (FS_EXISTS
|FS_EXECABLE
))
368 phash_remove (pathname
);
370 hashed_file
= (char *)NULL
;
375 command
= hashed_file
;
376 else if (absolute_program (pathname
))
377 /* A command containing a slash is not looked up in PATH or saved in
379 command
= savestring (pathname
);
382 if (flags
& CMDSRCH_STDPATH
)
383 pathlist
= conf_standard_path ();
384 else if (temp_path
|| path
)
385 pathlist
= value_cell (path
);
389 command
= find_user_command_in_path (pathname
, pathlist
, FS_EXEC_PREFERRED
|FS_NODIRS
);
391 if (command
&& hashing_enabled
&& temp_path
== 0 && (flags
& CMDSRCH_HASH
))
393 /* If we found the full pathname the same as the command name, the
394 command probably doesn't exist. Don't put it into the hash
396 if (STREQ (command
, pathname
))
398 st
= file_status (command
);
399 if (st
& FS_EXECABLE
)
400 phash_insert ((char *)pathname
, command
, dot_found_in_search
, 1);
403 phash_insert ((char *)pathname
, command
, dot_found_in_search
, 1);
406 if (flags
& CMDSRCH_STDPATH
)
414 user_command_matches (name
, flags
, state
)
419 int path_index
, name_len
;
420 char *path_list
, *path_element
, *match
;
422 static char **match_list
= NULL
;
423 static int match_list_size
= 0;
424 static int match_index
= 0;
428 /* Create the list of matches. */
432 match_list
= strvec_create (match_list_size
);
435 /* Clear out the old match list. */
436 for (i
= 0; i
< match_list_size
; i
++)
439 /* We haven't found any files yet. */
442 if (absolute_program (name
))
444 match_list
[0] = find_absolute_program (name
, flags
);
445 match_list
[1] = (char *)NULL
;
446 path_list
= (char *)NULL
;
450 name_len
= strlen (name
);
451 file_to_lose_on
= (char *)NULL
;
452 dot_found_in_search
= 0;
453 if (stat (".", &dotinfo
) < 0)
454 dotinfo
.st_dev
= dotinfo
.st_ino
= 0; /* so same_file won't match */
455 path_list
= get_string_value ("PATH");
459 while (path_list
&& path_list
[path_index
])
461 path_element
= get_next_path_element (path_list
, &path_index
);
463 if (path_element
== 0)
466 match
= find_in_path_element (name
, path_element
, flags
, name_len
, &dotinfo
);
473 if (match_index
+ 1 == match_list_size
)
475 match_list_size
+= 10;
476 match_list
= strvec_resize (match_list
, (match_list_size
+ 1));
479 match_list
[match_index
++] = match
;
480 match_list
[match_index
] = (char *)NULL
;
481 FREE (file_to_lose_on
);
482 file_to_lose_on
= (char *)NULL
;
485 /* We haven't returned any strings yet. */
489 match
= match_list
[match_index
];
498 find_absolute_program (name
, flags
)
504 st
= file_status (name
);
506 /* If the file doesn't exist, quit now. */
507 if ((st
& FS_EXISTS
) == 0)
508 return ((char *)NULL
);
510 /* If we only care about whether the file exists or not, return
511 this filename. Otherwise, maybe we care about whether this
512 file is executable. If it is, and that is what we want, return it. */
513 if ((flags
& FS_EXISTS
) || ((flags
& FS_EXEC_ONLY
) && (st
& FS_EXECABLE
)))
514 return (savestring (name
));
520 find_in_path_element (name
, path
, flags
, name_len
, dotinfop
)
524 struct stat
*dotinfop
;
527 char *full_path
, *xpath
;
529 xpath
= (posixly_correct
== 0 && *path
== '~') ? bash_tilde_expand (path
, 0) : path
;
531 /* Remember the location of "." in the path, in all its forms
532 (as long as they begin with a `.', e.g. `./.') */
533 if (dot_found_in_search
== 0 && *xpath
== '.')
534 dot_found_in_search
= same_file (".", xpath
, dotinfop
, (struct stat
*)NULL
);
536 full_path
= sh_makepath (xpath
, name
, 0);
538 status
= file_status (full_path
);
543 if ((status
& FS_EXISTS
) == 0)
546 return ((char *)NULL
);
549 /* The file exists. If the caller simply wants the first file, here it is. */
550 if (flags
& FS_EXISTS
)
553 /* If we have a readable file, and the caller wants a readable file, this
555 if ((flags
& FS_READABLE
) && (status
& FS_READABLE
))
558 /* If the file is executable, then it satisfies the cases of
559 EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
560 if ((status
& FS_EXECABLE
) && (flags
& (FS_EXEC_ONLY
|FS_EXEC_PREFERRED
)) &&
561 (((flags
& FS_NODIRS
) == 0) || ((status
& FS_DIRECTORY
) == 0)))
563 FREE (file_to_lose_on
);
564 file_to_lose_on
= (char *)NULL
;
568 /* The file is not executable, but it does exist. If we prefer
569 an executable, then remember this one if it is the first one
571 if ((flags
& FS_EXEC_PREFERRED
) && file_to_lose_on
== 0 && exec_name_should_ignore (full_path
) == 0)
572 file_to_lose_on
= savestring (full_path
);
574 /* If we want only executable files, or we don't want directories and
575 this file is a directory, or we want a readable file and this file
576 isn't readable, fail. */
577 if ((flags
& (FS_EXEC_ONLY
|FS_EXEC_PREFERRED
)) ||
578 ((flags
& FS_NODIRS
) && (status
& FS_DIRECTORY
)) ||
579 ((flags
& FS_READABLE
) && (status
& FS_READABLE
) == 0))
582 return ((char *)NULL
);
588 /* This does the dirty work for find_user_command_internal () and
589 user_command_matches ().
590 NAME is the name of the file to search for.
591 PATH_LIST is a colon separated list of directories to search.
592 FLAGS contains bit fields which control the files which are eligible.
594 FS_EXEC_ONLY: The file must be an executable to be found.
595 FS_EXEC_PREFERRED: If we can't find an executable, then the
596 the first file matching NAME will do.
597 FS_EXISTS: The first file found will do.
598 FS_NODIRS: Don't find any directories.
601 find_user_command_in_path (name
, path_list
, flags
)
606 char *full_path
, *path
;
607 int path_index
, name_len
;
610 /* We haven't started looking, so we certainly haven't seen
611 a `.' as the directory path yet. */
612 dot_found_in_search
= 0;
614 if (absolute_program (name
))
616 full_path
= find_absolute_program (name
, flags
);
620 if (path_list
== 0 || *path_list
== '\0')
621 return (savestring (name
)); /* XXX */
623 file_to_lose_on
= (char *)NULL
;
624 name_len
= strlen (name
);
625 if (stat (".", &dotinfo
) < 0)
626 dotinfo
.st_dev
= dotinfo
.st_ino
= 0;
629 while (path_list
[path_index
])
631 /* Allow the user to interrupt out of a lengthy path search. */
634 path
= get_next_path_element (path_list
, &path_index
);
638 /* Side effects: sets dot_found_in_search, possibly sets
640 full_path
= find_in_path_element (name
, path
, flags
, name_len
, &dotinfo
);
643 /* This should really be in find_in_path_element, but there isn't the
644 right combination of flags. */
645 if (full_path
&& is_directory (full_path
))
653 FREE (file_to_lose_on
);
658 /* We didn't find exactly what the user was looking for. Return
659 the contents of FILE_TO_LOSE_ON which is NULL when the search
660 required an executable, or non-NULL if a file was found and the
661 search would accept a non-executable as a last resort. If the
662 caller specified FS_NODIRS, and file_to_lose_on is a directory,
664 if (file_to_lose_on
&& (flags
& FS_NODIRS
) && is_directory (file_to_lose_on
))
666 free (file_to_lose_on
);
667 file_to_lose_on
= (char *)NULL
;
670 return (file_to_lose_on
);
673 /* External interface to find a command given a $PATH. Separate from
674 find_user_command_in_path to allow future customization. */
676 find_in_path (name
, path_list
, flags
)
681 return (find_user_command_in_path (name
, path_list
, flags
));