]> git.ipfire.org Git - thirdparty/bash.git/blame - findcmd.c
Bash-4.4 patch 19
[thirdparty/bash.git] / findcmd.c
CommitLineData
cce855bc
JA
1/* findcmd.c -- Functions to search for commands by name. */
2
a0c0a00f 3/* Copyright (C) 1997-2015 Free Software Foundation, Inc.
cce855bc
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
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.
cce855bc 11
3185942a
JA
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.
cce855bc
JA
16
17 You should have received a copy of the GNU General Public License
3185942a
JA
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
cce855bc
JA
20
21#include "config.h"
22
23#include <stdio.h>
f73dda09 24#include "chartypes.h"
cce855bc 25#include "bashtypes.h"
b80f6443 26#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
cce855bc
JA
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
495aee44 35#include <errno.h>
cce855bc 36
cce855bc
JA
37#include "bashansi.h"
38
39#include "memalloc.h"
40#include "shell.h"
41#include "flags.h"
42#include "hashlib.h"
43#include "pathexp.h"
44#include "hashcmd.h"
f73dda09 45#include "findcmd.h" /* matching prototypes and declarations */
cce855bc 46
a0c0a00f
CR
47#include <glob/strmatch.h>
48
495aee44
CR
49#if !defined (errno)
50extern int errno;
51#endif
52
cce855bc 53extern int posixly_correct;
ac50fbac 54extern int last_command_exit_value;
cce855bc
JA
55
56/* Static functions defined and used in this file. */
f73dda09
JA
57static char *_find_user_command_internal __P((const char *, int));
58static char *find_user_command_internal __P((const char *, int));
59static char *find_user_command_in_path __P((const char *, char *, int));
60static char *find_in_path_element __P((const char *, char *, int, int, struct stat *));
61static char *find_absolute_program __P((const char *, int));
62
63static char *get_next_path_element __P((char *, int *));
cce855bc
JA
64
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. */
70static char *file_to_lose_on;
71
72/* Non-zero if we should stat every command found in the hash table to
73 make sure it still exists. */
a0c0a00f 74int check_hashed_filenames = CHECKHASH_DEFAULT;
cce855bc
JA
75
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. */
80int dot_found_in_search = 0;
81
a0c0a00f
CR
82/* Set up EXECIGNORE; a blacklist of patterns that executable files should not
83 match. */
84static struct ignorevar execignore =
85{
86 "EXECIGNORE",
87 NULL,
88 0,
89 NULL,
90 NULL
91};
92
93void
94setup_exec_ignore (varname)
95 char *varname;
96{
97 setup_ignore_patterns (&execignore);
98}
99
100static int
101exec_name_should_ignore (name)
102 const char *name;
103{
104 struct ign *p;
105
106 for (p = execignore.ignores; p && p->val; p++)
107 if (strmatch (p->val, (char *)name, FNMATCH_EXTFLAG|FNM_CASEFOLD) != FNM_NOMATCH)
108 return 1;
109 return 0;
110}
111
cce855bc
JA
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. */
116int
117file_status (name)
f73dda09 118 const char *name;
cce855bc
JA
119{
120 struct stat finfo;
95732b49 121 int r;
cce855bc
JA
122
123 /* Determine whether this file exists or not. */
124 if (stat (name, &finfo) < 0)
125 return (0);
126
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);
131
95732b49
JA
132 r = FS_EXISTS;
133
0001803f
CR
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. */
a0c0a00f 139 if (exec_name_should_ignore (name) == 0 && eaccess (name, X_OK) == 0)
0001803f
CR
140 r |= FS_EXECABLE;
141 if (eaccess (name, R_OK) == 0)
142 r |= FS_READABLE;
143
144 return r;
145#elif defined (AFS)
cce855bc
JA
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. */
a0c0a00f 149 if (exec_name_should_ignore (name) == 0 && access (name, X_OK) == 0)
95732b49
JA
150 r |= FS_EXECABLE;
151 if (access (name, R_OK) == 0)
152 r |= FS_READABLE;
153
154 return r;
0001803f 155#else /* !HAVE_EACCESS && !AFS */
cce855bc
JA
156
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
95732b49 159 we can use. The same with whether or not a file is readable. */
cce855bc
JA
160
161 /* Root only requires execute permission for any of owner, group or
95732b49 162 others to be able to exec a file, and can read any file. */
cce855bc
JA
163 if (current_user.euid == (uid_t)0)
164 {
95732b49 165 r |= FS_READABLE;
a0c0a00f 166 if (exec_name_should_ignore (name) == 0 && (finfo.st_mode & S_IXUGO))
95732b49
JA
167 r |= FS_EXECABLE;
168 return r;
cce855bc
JA
169 }
170
95732b49 171 /* If we are the owner of the file, the owner bits apply. */
b80f6443 172 if (current_user.euid == finfo.st_uid)
95732b49 173 {
a0c0a00f 174 if (exec_name_should_ignore (name) == 0 && (finfo.st_mode & S_IXUSR))
95732b49
JA
175 r |= FS_EXECABLE;
176 if (finfo.st_mode & S_IRUSR)
177 r |= FS_READABLE;
178 }
cce855bc
JA
179
180 /* If we are in the owning group, the group permissions apply. */
b80f6443 181 else if (group_member (finfo.st_gid))
95732b49 182 {
a0c0a00f 183 if (exec_name_should_ignore (name) == 0 && (finfo.st_mode & S_IXGRP))
95732b49
JA
184 r |= FS_EXECABLE;
185 if (finfo.st_mode & S_IRGRP)
186 r |= FS_READABLE;
187 }
cce855bc 188
b80f6443
JA
189 /* Else we check whether `others' have permission to execute the file */
190 else
95732b49 191 {
a0c0a00f 192 if (exec_name_should_ignore (name) == 0 && finfo.st_mode & S_IXOTH)
95732b49
JA
193 r |= FS_EXECABLE;
194 if (finfo.st_mode & S_IROTH)
195 r |= FS_READABLE;
196 }
197
198 return r;
cce855bc
JA
199#endif /* !AFS */
200}
201
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. */
206int
207executable_file (file)
f73dda09 208 const char *file;
cce855bc
JA
209{
210 int s;
211
212 s = file_status (file);
a0c0a00f 213#if defined (EISDIR)
495aee44
CR
214 if (s & FS_DIRECTORY)
215 errno = EISDIR; /* let's see if we can improve error messages */
216#endif
cce855bc
JA
217 return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
218}
219
220int
221is_directory (file)
f73dda09 222 const char *file;
cce855bc
JA
223{
224 return (file_status (file) & FS_DIRECTORY);
225}
226
28ef6c31
JA
227int
228executable_or_directory (file)
f73dda09 229 const char *file;
28ef6c31
JA
230{
231 int s;
232
233 s = file_status (file);
234 return ((s & FS_EXECABLE) || (s & FS_DIRECTORY));
235}
236
cce855bc
JA
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. */
242char *
243find_user_command (name)
f73dda09 244 const char *name;
cce855bc
JA
245{
246 return (find_user_command_internal (name, FS_EXEC_PREFERRED|FS_NODIRS));
247}
248
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
95732b49
JA
252 returns the first readable file found; designed to be used to look
253 for shell scripts or files to source. */
cce855bc
JA
254char *
255find_path_file (name)
f73dda09 256 const char *name;
cce855bc 257{
95732b49 258 return (find_user_command_internal (name, FS_READABLE));
cce855bc
JA
259}
260
261static char *
262_find_user_command_internal (name, flags)
f73dda09 263 const char *name;
cce855bc
JA
264 int flags;
265{
266 char *path_list, *cmd;
267 SHELL_VAR *var;
268
7117c2d2 269 /* Search for the value of PATH in both the temporary environments and
cce855bc 270 in the regular list of variables. */
ac50fbac 271 if (var = find_variable_tempenv ("PATH")) /* XXX could be array? */
cce855bc
JA
272 path_list = value_cell (var);
273 else
274 path_list = (char *)NULL;
275
276 if (path_list == 0 || *path_list == '\0')
277 return (savestring (name));
278
279 cmd = find_user_command_in_path (name, path_list, flags);
280
cce855bc
JA
281 return (cmd);
282}
283
284static char *
285find_user_command_internal (name, flags)
f73dda09 286 const char *name;
cce855bc
JA
287 int flags;
288{
289#ifdef __WIN32__
290 char *res, *dotexe;
291
f73dda09 292 dotexe = (char *)xmalloc (strlen (name) + 5);
cce855bc
JA
293 strcpy (dotexe, name);
294 strcat (dotexe, ".exe");
295 res = _find_user_command_internal (dotexe, flags);
296 free (dotexe);
297 if (res == 0)
298 res = _find_user_command_internal (name, flags);
299 return res;
300#else
301 return (_find_user_command_internal (name, flags));
302#endif
303}
304
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. */
309static char *
310get_next_path_element (path_list, path_index_pointer)
311 char *path_list;
312 int *path_index_pointer;
313{
314 char *path;
315
316 path = extract_colon_unit (path_list, path_index_pointer);
317
bb70624e 318 if (path == 0)
cce855bc
JA
319 return (path);
320
bb70624e 321 if (*path == '\0')
cce855bc
JA
322 {
323 free (path);
324 path = savestring (".");
325 }
326
327 return (path);
328}
329
330/* Look for PATHNAME in $PATH. Returns either the hashed command
331 corresponding to PATHNAME or the first instance of PATHNAME found
a0c0a00f
CR
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. */
cce855bc 337char *
ac50fbac 338search_for_command (pathname, flags)
f73dda09 339 const char *pathname;
ac50fbac 340 int flags;
cce855bc 341{
a0c0a00f 342 char *hashed_file, *command, *pathlist;
cce855bc
JA
343 int temp_path, st;
344 SHELL_VAR *path;
345
346 hashed_file = command = (char *)NULL;
347
348 /* If PATH is in the temporary environment for this command, don't use the
349 hash table to search for the full pathname. */
ac50fbac 350 path = find_variable_tempenv ("PATH");
7117c2d2 351 temp_path = path && tempvar_p (path);
cce855bc
JA
352
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. */
a0c0a00f 356 if (temp_path == 0 && absolute_program (pathname) == 0)
7117c2d2 357 hashed_file = phash_search (pathname);
cce855bc
JA
358
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. */
362
363 if (hashed_file && (posixly_correct || check_hashed_filenames))
364 {
365 st = file_status (hashed_file);
f1be666c 366 if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
cce855bc 367 {
7117c2d2 368 phash_remove (pathname);
cce855bc
JA
369 free (hashed_file);
370 hashed_file = (char *)NULL;
371 }
372 }
373
374 if (hashed_file)
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
378 the hash table. */
379 command = savestring (pathname);
380 else
381 {
a0c0a00f
CR
382 if (flags & CMDSRCH_STDPATH)
383 pathlist = conf_standard_path ();
384 else if (temp_path || path)
385 pathlist = value_cell (path);
386 else
387 pathlist = 0;
388
389 command = find_user_command_in_path (pathname, pathlist, FS_EXEC_PREFERRED|FS_NODIRS);
390
391 if (command && hashing_enabled && temp_path == 0 && (flags & CMDSRCH_HASH))
28ef6c31 392 {
a0c0a00f
CR
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
395 table. */
396 if (STREQ (command, pathname))
397 {
398 st = file_status (command);
399 if (st & FS_EXECABLE)
400 phash_insert ((char *)pathname, command, dot_found_in_search, 1);
401 }
402 else
403 phash_insert ((char *)pathname, command, dot_found_in_search, 1);
28ef6c31 404 }
a0c0a00f
CR
405
406 if (flags & CMDSRCH_STDPATH)
407 free (pathlist);
cce855bc 408 }
a0c0a00f 409
cce855bc
JA
410 return (command);
411}
412
413char *
414user_command_matches (name, flags, state)
f73dda09 415 const char *name;
cce855bc
JA
416 int flags, state;
417{
418 register int i;
419 int path_index, name_len;
420 char *path_list, *path_element, *match;
421 struct stat dotinfo;
422 static char **match_list = NULL;
423 static int match_list_size = 0;
424 static int match_index = 0;
425
426 if (state == 0)
427 {
428 /* Create the list of matches. */
429 if (match_list == 0)
430 {
431 match_list_size = 5;
7117c2d2 432 match_list = strvec_create (match_list_size);
cce855bc
JA
433 }
434
435 /* Clear out the old match list. */
436 for (i = 0; i < match_list_size; i++)
437 match_list[i] = 0;
438
439 /* We haven't found any files yet. */
440 match_index = 0;
441
442 if (absolute_program (name))
443 {
444 match_list[0] = find_absolute_program (name, flags);
445 match_list[1] = (char *)NULL;
446 path_list = (char *)NULL;
447 }
448 else
449 {
450 name_len = strlen (name);
451 file_to_lose_on = (char *)NULL;
452 dot_found_in_search = 0;
ac50fbac
CR
453 if (stat (".", &dotinfo) < 0)
454 dotinfo.st_dev = dotinfo.st_ino = 0; /* so same_file won't match */
cce855bc
JA
455 path_list = get_string_value ("PATH");
456 path_index = 0;
457 }
458
459 while (path_list && path_list[path_index])
460 {
461 path_element = get_next_path_element (path_list, &path_index);
462
463 if (path_element == 0)
464 break;
465
466 match = find_in_path_element (name, path_element, flags, name_len, &dotinfo);
467
468 free (path_element);
469
470 if (match == 0)
471 continue;
472
473 if (match_index + 1 == match_list_size)
474 {
475 match_list_size += 10;
7117c2d2 476 match_list = strvec_resize (match_list, (match_list_size + 1));
cce855bc
JA
477 }
478
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;
483 }
484
485 /* We haven't returned any strings yet. */
486 match_index = 0;
487 }
488
489 match = match_list[match_index];
490
491 if (match)
492 match_index++;
493
494 return (match);
495}
496
cce855bc
JA
497static char *
498find_absolute_program (name, flags)
f73dda09 499 const char *name;
cce855bc
JA
500 int flags;
501{
502 int st;
503
504 st = file_status (name);
505
506 /* If the file doesn't exist, quit now. */
507 if ((st & FS_EXISTS) == 0)
508 return ((char *)NULL);
509
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));
515
f73dda09 516 return (NULL);
cce855bc
JA
517}
518
519static char *
520find_in_path_element (name, path, flags, name_len, dotinfop)
f73dda09
JA
521 const char *name;
522 char *path;
cce855bc
JA
523 int flags, name_len;
524 struct stat *dotinfop;
525{
526 int status;
527 char *full_path, *xpath;
528
a0c0a00f 529 xpath = (posixly_correct == 0 && *path == '~') ? bash_tilde_expand (path, 0) : path;
cce855bc
JA
530
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);
535
bb70624e 536 full_path = sh_makepath (xpath, name, 0);
cce855bc
JA
537
538 status = file_status (full_path);
539
540 if (xpath != path)
541 free (xpath);
542
543 if ((status & FS_EXISTS) == 0)
544 {
545 free (full_path);
546 return ((char *)NULL);
547 }
548
549 /* The file exists. If the caller simply wants the first file, here it is. */
550 if (flags & FS_EXISTS)
551 return (full_path);
552
95732b49
JA
553 /* If we have a readable file, and the caller wants a readable file, this
554 is it. */
555 if ((flags & FS_READABLE) && (status & FS_READABLE))
556 return (full_path);
557
cce855bc
JA
558 /* If the file is executable, then it satisfies the cases of
559 EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
95732b49 560 if ((status & FS_EXECABLE) && (flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) &&
cce855bc
JA
561 (((flags & FS_NODIRS) == 0) || ((status & FS_DIRECTORY) == 0)))
562 {
563 FREE (file_to_lose_on);
564 file_to_lose_on = (char *)NULL;
565 return (full_path);
566 }
567
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
570 we have found. */
a0c0a00f 571 if ((flags & FS_EXEC_PREFERRED) && file_to_lose_on == 0 && exec_name_should_ignore (full_path) == 0)
cce855bc
JA
572 file_to_lose_on = savestring (full_path);
573
574 /* If we want only executable files, or we don't want directories and
95732b49
JA
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))
cce855bc
JA
580 {
581 free (full_path);
582 return ((char *)NULL);
583 }
584 else
585 return (full_path);
586}
587
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.
593 Some values are:
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.
599*/
600static char *
601find_user_command_in_path (name, path_list, flags)
f73dda09 602 const char *name;
cce855bc
JA
603 char *path_list;
604 int flags;
605{
606 char *full_path, *path;
607 int path_index, name_len;
608 struct stat dotinfo;
609
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;
613
614 if (absolute_program (name))
615 {
616 full_path = find_absolute_program (name, flags);
617 return (full_path);
618 }
619
620 if (path_list == 0 || *path_list == '\0')
621 return (savestring (name)); /* XXX */
622
623 file_to_lose_on = (char *)NULL;
624 name_len = strlen (name);
ac50fbac
CR
625 if (stat (".", &dotinfo) < 0)
626 dotinfo.st_dev = dotinfo.st_ino = 0;
cce855bc
JA
627 path_index = 0;
628
629 while (path_list[path_index])
630 {
631 /* Allow the user to interrupt out of a lengthy path search. */
632 QUIT;
633
634 path = get_next_path_element (path_list, &path_index);
635 if (path == 0)
636 break;
637
638 /* Side effects: sets dot_found_in_search, possibly sets
639 file_to_lose_on. */
640 full_path = find_in_path_element (name, path, flags, name_len, &dotinfo);
641 free (path);
642
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))
646 {
647 free (full_path);
648 continue;
649 }
650
651 if (full_path)
652 {
653 FREE (file_to_lose_on);
654 return (full_path);
655 }
656 }
657
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
28ef6c31
JA
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,
663 return NULL. */
664 if (file_to_lose_on && (flags & FS_NODIRS) && is_directory (file_to_lose_on))
665 {
666 free (file_to_lose_on);
667 file_to_lose_on = (char *)NULL;
668 }
669
cce855bc
JA
670 return (file_to_lose_on);
671}
a0c0a00f
CR
672
673/* External interface to find a command given a $PATH. Separate from
674 find_user_command_in_path to allow future customization. */
675char *
676find_in_path (name, path_list, flags)
677 const char *name;
678 char *path_list;
679 int flags;
680{
681 return (find_user_command_in_path (name, path_list, flags));
682}