1 /* findcmd.c -- Functions to search for commands by name. */
3 /* Copyright (C) 1997-2009 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)
44 #include "findcmd.h" /* matching prototypes and declarations */
46 extern int posixly_correct
;
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));
55 static char *get_next_path_element
__P((char *, int *));
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
;
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
;
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;
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. */
85 /* Determine whether this file exists or not. */
86 if (stat (name
, &finfo
) < 0)
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
);
97 /* We have to use access(2) to determine access because AFS does not
98 support Unix file system semantics. This may produce wrong
99 answers for non-AFS files when ruid != euid. I hate AFS. */
100 if (access (name
, X_OK
) == 0)
102 if (access (name
, R_OK
) == 0)
108 /* Find out if the file is actually executable. By definition, the
109 only other criteria is that the file has an execute bit set that
110 we can use. The same with whether or not a file is readable. */
112 /* Root only requires execute permission for any of owner, group or
113 others to be able to exec a file, and can read any file. */
114 if (current_user
.euid
== (uid_t
)0)
117 if (finfo
.st_mode
& S_IXUGO
)
122 /* If we are the owner of the file, the owner bits apply. */
123 if (current_user
.euid
== finfo
.st_uid
)
125 if (finfo
.st_mode
& S_IXUSR
)
127 if (finfo
.st_mode
& S_IRUSR
)
131 /* If we are in the owning group, the group permissions apply. */
132 else if (group_member (finfo
.st_gid
))
134 if (finfo
.st_mode
& S_IXGRP
)
136 if (finfo
.st_mode
& S_IRGRP
)
140 /* Else we check whether `others' have permission to execute the file */
143 if (finfo
.st_mode
& S_IXOTH
)
145 if (finfo
.st_mode
& S_IROTH
)
153 /* Return non-zero if FILE exists and is executable.
154 Note that this function is the definition of what an
155 executable file is; do not change this unless YOU know
156 what an executable file is. */
158 executable_file (file
)
163 s
= file_status (file
);
164 return ((s
& FS_EXECABLE
) && ((s
& FS_DIRECTORY
) == 0));
171 return (file_status (file
) & FS_DIRECTORY
);
175 executable_or_directory (file
)
180 s
= file_status (file
);
181 return ((s
& FS_EXECABLE
) || (s
& FS_DIRECTORY
));
184 /* Locate the executable file referenced by NAME, searching along
185 the contents of the shell PATH variable. Return a new string
186 which is the full pathname to the file, or NULL if the file
187 couldn't be found. If a file is found that isn't executable,
188 and that is the only match, then return that. */
190 find_user_command (name
)
193 return (find_user_command_internal (name
, FS_EXEC_PREFERRED
|FS_NODIRS
));
196 /* Locate the file referenced by NAME, searching along the contents
197 of the shell PATH variable. Return a new string which is the full
198 pathname to the file, or NULL if the file couldn't be found. This
199 returns the first readable file found; designed to be used to look
200 for shell scripts or files to source. */
202 find_path_file (name
)
205 return (find_user_command_internal (name
, FS_READABLE
));
209 _find_user_command_internal (name
, flags
)
213 char *path_list
, *cmd
;
216 /* Search for the value of PATH in both the temporary environments and
217 in the regular list of variables. */
218 if (var
= find_variable_internal ("PATH", 1)) /* XXX could be array? */
219 path_list
= value_cell (var
);
221 path_list
= (char *)NULL
;
223 if (path_list
== 0 || *path_list
== '\0')
224 return (savestring (name
));
226 cmd
= find_user_command_in_path (name
, path_list
, flags
);
232 find_user_command_internal (name
, flags
)
239 dotexe
= (char *)xmalloc (strlen (name
) + 5);
240 strcpy (dotexe
, name
);
241 strcat (dotexe
, ".exe");
242 res
= _find_user_command_internal (dotexe
, flags
);
245 res
= _find_user_command_internal (name
, flags
);
248 return (_find_user_command_internal (name
, flags
));
252 /* Return the next element from PATH_LIST, a colon separated list of
253 paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST;
254 the index is modified by this function.
255 Return the next element of PATH_LIST or NULL if there are no more. */
257 get_next_path_element (path_list
, path_index_pointer
)
259 int *path_index_pointer
;
263 path
= extract_colon_unit (path_list
, path_index_pointer
);
271 path
= savestring (".");
277 /* Look for PATHNAME in $PATH. Returns either the hashed command
278 corresponding to PATHNAME or the first instance of PATHNAME found
279 in $PATH. Returns a newly-allocated string. */
281 search_for_command (pathname
)
282 const char *pathname
;
284 char *hashed_file
, *command
;
288 hashed_file
= command
= (char *)NULL
;
290 /* If PATH is in the temporary environment for this command, don't use the
291 hash table to search for the full pathname. */
292 path
= find_variable_internal ("PATH", 1);
293 temp_path
= path
&& tempvar_p (path
);
294 if (temp_path
== 0 && path
)
295 path
= (SHELL_VAR
*)NULL
;
297 /* Don't waste time trying to find hashed data for a pathname
298 that is already completely specified or if we're using a command-
299 specific value for PATH. */
300 if (path
== 0 && absolute_program (pathname
) == 0)
301 hashed_file
= phash_search (pathname
);
303 /* If a command found in the hash table no longer exists, we need to
304 look for it in $PATH. Thank you Posix.2. This forces us to stat
305 every command found in the hash table. */
307 if (hashed_file
&& (posixly_correct
|| check_hashed_filenames
))
309 st
= file_status (hashed_file
);
310 if ((st
& (FS_EXISTS
|FS_EXECABLE
)) != (FS_EXISTS
|FS_EXECABLE
))
312 phash_remove (pathname
);
314 hashed_file
= (char *)NULL
;
319 command
= hashed_file
;
320 else if (absolute_program (pathname
))
321 /* A command containing a slash is not looked up in PATH or saved in
323 command
= savestring (pathname
);
326 /* If $PATH is in the temporary environment, we've already retrieved
327 it, so don't bother trying again. */
330 command
= find_user_command_in_path (pathname
, value_cell (path
),
331 FS_EXEC_PREFERRED
|FS_NODIRS
);
334 command
= find_user_command (pathname
);
335 if (command
&& hashing_enabled
&& temp_path
== 0)
336 phash_insert ((char *)pathname
, command
, dot_found_in_search
, 1); /* XXX fix const later */
342 user_command_matches (name
, flags
, state
)
347 int path_index
, name_len
;
348 char *path_list
, *path_element
, *match
;
350 static char **match_list
= NULL
;
351 static int match_list_size
= 0;
352 static int match_index
= 0;
356 /* Create the list of matches. */
360 match_list
= strvec_create (match_list_size
);
363 /* Clear out the old match list. */
364 for (i
= 0; i
< match_list_size
; i
++)
367 /* We haven't found any files yet. */
370 if (absolute_program (name
))
372 match_list
[0] = find_absolute_program (name
, flags
);
373 match_list
[1] = (char *)NULL
;
374 path_list
= (char *)NULL
;
378 name_len
= strlen (name
);
379 file_to_lose_on
= (char *)NULL
;
380 dot_found_in_search
= 0;
381 stat (".", &dotinfo
);
382 path_list
= get_string_value ("PATH");
386 while (path_list
&& path_list
[path_index
])
388 path_element
= get_next_path_element (path_list
, &path_index
);
390 if (path_element
== 0)
393 match
= find_in_path_element (name
, path_element
, flags
, name_len
, &dotinfo
);
400 if (match_index
+ 1 == match_list_size
)
402 match_list_size
+= 10;
403 match_list
= strvec_resize (match_list
, (match_list_size
+ 1));
406 match_list
[match_index
++] = match
;
407 match_list
[match_index
] = (char *)NULL
;
408 FREE (file_to_lose_on
);
409 file_to_lose_on
= (char *)NULL
;
412 /* We haven't returned any strings yet. */
416 match
= match_list
[match_index
];
425 find_absolute_program (name
, flags
)
431 st
= file_status (name
);
433 /* If the file doesn't exist, quit now. */
434 if ((st
& FS_EXISTS
) == 0)
435 return ((char *)NULL
);
437 /* If we only care about whether the file exists or not, return
438 this filename. Otherwise, maybe we care about whether this
439 file is executable. If it is, and that is what we want, return it. */
440 if ((flags
& FS_EXISTS
) || ((flags
& FS_EXEC_ONLY
) && (st
& FS_EXECABLE
)))
441 return (savestring (name
));
447 find_in_path_element (name
, path
, flags
, name_len
, dotinfop
)
451 struct stat
*dotinfop
;
454 char *full_path
, *xpath
;
456 xpath
= (*path
== '~') ? bash_tilde_expand (path
, 0) : path
;
458 /* Remember the location of "." in the path, in all its forms
459 (as long as they begin with a `.', e.g. `./.') */
460 if (dot_found_in_search
== 0 && *xpath
== '.')
461 dot_found_in_search
= same_file (".", xpath
, dotinfop
, (struct stat
*)NULL
);
463 full_path
= sh_makepath (xpath
, name
, 0);
465 status
= file_status (full_path
);
470 if ((status
& FS_EXISTS
) == 0)
473 return ((char *)NULL
);
476 /* The file exists. If the caller simply wants the first file, here it is. */
477 if (flags
& FS_EXISTS
)
480 /* If we have a readable file, and the caller wants a readable file, this
482 if ((flags
& FS_READABLE
) && (status
& FS_READABLE
))
485 /* If the file is executable, then it satisfies the cases of
486 EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
487 if ((status
& FS_EXECABLE
) && (flags
& (FS_EXEC_ONLY
|FS_EXEC_PREFERRED
)) &&
488 (((flags
& FS_NODIRS
) == 0) || ((status
& FS_DIRECTORY
) == 0)))
490 FREE (file_to_lose_on
);
491 file_to_lose_on
= (char *)NULL
;
495 /* The file is not executable, but it does exist. If we prefer
496 an executable, then remember this one if it is the first one
498 if ((flags
& FS_EXEC_PREFERRED
) && file_to_lose_on
== 0)
499 file_to_lose_on
= savestring (full_path
);
501 /* If we want only executable files, or we don't want directories and
502 this file is a directory, or we want a readable file and this file
503 isn't readable, fail. */
504 if ((flags
& (FS_EXEC_ONLY
|FS_EXEC_PREFERRED
)) ||
505 ((flags
& FS_NODIRS
) && (status
& FS_DIRECTORY
)) ||
506 ((flags
& FS_READABLE
) && (status
& FS_READABLE
) == 0))
509 return ((char *)NULL
);
515 /* This does the dirty work for find_user_command_internal () and
516 user_command_matches ().
517 NAME is the name of the file to search for.
518 PATH_LIST is a colon separated list of directories to search.
519 FLAGS contains bit fields which control the files which are eligible.
521 FS_EXEC_ONLY: The file must be an executable to be found.
522 FS_EXEC_PREFERRED: If we can't find an executable, then the
523 the first file matching NAME will do.
524 FS_EXISTS: The first file found will do.
525 FS_NODIRS: Don't find any directories.
528 find_user_command_in_path (name
, path_list
, flags
)
533 char *full_path
, *path
;
534 int path_index
, name_len
;
537 /* We haven't started looking, so we certainly haven't seen
538 a `.' as the directory path yet. */
539 dot_found_in_search
= 0;
541 if (absolute_program (name
))
543 full_path
= find_absolute_program (name
, flags
);
547 if (path_list
== 0 || *path_list
== '\0')
548 return (savestring (name
)); /* XXX */
550 file_to_lose_on
= (char *)NULL
;
551 name_len
= strlen (name
);
552 stat (".", &dotinfo
);
555 while (path_list
[path_index
])
557 /* Allow the user to interrupt out of a lengthy path search. */
560 path
= get_next_path_element (path_list
, &path_index
);
564 /* Side effects: sets dot_found_in_search, possibly sets
566 full_path
= find_in_path_element (name
, path
, flags
, name_len
, &dotinfo
);
569 /* This should really be in find_in_path_element, but there isn't the
570 right combination of flags. */
571 if (full_path
&& is_directory (full_path
))
579 FREE (file_to_lose_on
);
584 /* We didn't find exactly what the user was looking for. Return
585 the contents of FILE_TO_LOSE_ON which is NULL when the search
586 required an executable, or non-NULL if a file was found and the
587 search would accept a non-executable as a last resort. If the
588 caller specified FS_NODIRS, and file_to_lose_on is a directory,
590 if (file_to_lose_on
&& (flags
& FS_NODIRS
) && is_directory (file_to_lose_on
))
592 free (file_to_lose_on
);
593 file_to_lose_on
= (char *)NULL
;
596 return (file_to_lose_on
);