]> git.ipfire.org Git - thirdparty/bash.git/blob - findcmd.c
fix for SIGINT in sourced script
[thirdparty/bash.git] / findcmd.c
1 /* findcmd.c -- Functions to search for commands by name. */
2
3 /* Copyright (C) 1997-2015 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 #include <errno.h>
36
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"
45 #include "findcmd.h" /* matching prototypes and declarations */
46
47 #include <glob/strmatch.h>
48
49 #if !defined (errno)
50 extern int errno;
51 #endif
52
53 extern int posixly_correct;
54 extern int last_command_exit_value;
55
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));
62
63 static char *get_next_path_element __P((char *, int *));
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. */
70 static 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. */
74 int check_hashed_filenames = CHECKHASH_DEFAULT;
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. */
80 int dot_found_in_search = 0;
81
82 /* Set up EXECIGNORE; a blacklist of patterns that executable files should not
83 match. */
84 static struct ignorevar execignore =
85 {
86 "EXECIGNORE",
87 NULL,
88 0,
89 NULL,
90 NULL
91 };
92
93 void
94 setup_exec_ignore (varname)
95 char *varname;
96 {
97 setup_ignore_patterns (&execignore);
98 }
99
100 static int
101 exec_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
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. */
116 int
117 file_status (name)
118 const char *name;
119 {
120 struct stat finfo;
121 int r;
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
132 r = FS_EXISTS;
133
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)
140 r |= FS_EXECABLE;
141 if (eaccess (name, R_OK) == 0)
142 r |= FS_READABLE;
143
144 return r;
145 #elif defined (AFS)
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)
150 r |= FS_EXECABLE;
151 if (access (name, R_OK) == 0)
152 r |= FS_READABLE;
153
154 return r;
155 #else /* !HAVE_EACCESS && !AFS */
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
159 we can use. The same with whether or not a file is readable. */
160
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)
164 {
165 r |= FS_READABLE;
166 if (exec_name_should_ignore (name) == 0 && (finfo.st_mode & S_IXUGO))
167 r |= FS_EXECABLE;
168 return r;
169 }
170
171 /* If we are the owner of the file, the owner bits apply. */
172 if (current_user.euid == finfo.st_uid)
173 {
174 if (exec_name_should_ignore (name) == 0 && (finfo.st_mode & S_IXUSR))
175 r |= FS_EXECABLE;
176 if (finfo.st_mode & S_IRUSR)
177 r |= FS_READABLE;
178 }
179
180 /* If we are in the owning group, the group permissions apply. */
181 else if (group_member (finfo.st_gid))
182 {
183 if (exec_name_should_ignore (name) == 0 && (finfo.st_mode & S_IXGRP))
184 r |= FS_EXECABLE;
185 if (finfo.st_mode & S_IRGRP)
186 r |= FS_READABLE;
187 }
188
189 /* Else we check whether `others' have permission to execute the file */
190 else
191 {
192 if (exec_name_should_ignore (name) == 0 && finfo.st_mode & S_IXOTH)
193 r |= FS_EXECABLE;
194 if (finfo.st_mode & S_IROTH)
195 r |= FS_READABLE;
196 }
197
198 return r;
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. */
206 int
207 executable_file (file)
208 const char *file;
209 {
210 int s;
211
212 s = file_status (file);
213 #if defined (EISDIR)
214 if (s & FS_DIRECTORY)
215 errno = EISDIR; /* let's see if we can improve error messages */
216 #endif
217 return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
218 }
219
220 int
221 is_directory (file)
222 const char *file;
223 {
224 return (file_status (file) & FS_DIRECTORY);
225 }
226
227 int
228 executable_or_directory (file)
229 const char *file;
230 {
231 int s;
232
233 s = file_status (file);
234 return ((s & FS_EXECABLE) || (s & FS_DIRECTORY));
235 }
236
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. */
242 char *
243 find_user_command (name)
244 const char *name;
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
252 returns the first readable file found; designed to be used to look
253 for shell scripts or files to source. */
254 char *
255 find_path_file (name)
256 const char *name;
257 {
258 return (find_user_command_internal (name, FS_READABLE));
259 }
260
261 static char *
262 _find_user_command_internal (name, flags)
263 const char *name;
264 int flags;
265 {
266 char *path_list, *cmd;
267 SHELL_VAR *var;
268
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);
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
281 return (cmd);
282 }
283
284 static char *
285 find_user_command_internal (name, flags)
286 const char *name;
287 int flags;
288 {
289 #ifdef __WIN32__
290 char *res, *dotexe;
291
292 dotexe = (char *)xmalloc (strlen (name) + 5);
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. */
309 static char *
310 get_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
318 if (path == 0)
319 return (path);
320
321 if (*path == '\0')
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
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. */
337 char *
338 search_for_command (pathname, flags)
339 const char *pathname;
340 int flags;
341 {
342 char *hashed_file, *command, *pathlist;
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. */
350 path = find_variable_tempenv ("PATH");
351 temp_path = path && tempvar_p (path);
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. */
356 if (temp_path == 0 && absolute_program (pathname) == 0)
357 hashed_file = phash_search (pathname);
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);
366 if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
367 {
368 phash_remove (pathname);
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 {
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))
392 {
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);
404 }
405
406 if (flags & CMDSRCH_STDPATH)
407 free (pathlist);
408 }
409
410 return (command);
411 }
412
413 char *
414 user_command_matches (name, flags, state)
415 const char *name;
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;
432 match_list = strvec_create (match_list_size);
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;
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");
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;
476 match_list = strvec_resize (match_list, (match_list_size + 1));
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
497 static char *
498 find_absolute_program (name, flags)
499 const char *name;
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
516 return (NULL);
517 }
518
519 static char *
520 find_in_path_element (name, path, flags, name_len, dotinfop)
521 const char *name;
522 char *path;
523 int flags, name_len;
524 struct stat *dotinfop;
525 {
526 int status;
527 char *full_path, *xpath;
528
529 xpath = (posixly_correct == 0 && *path == '~') ? bash_tilde_expand (path, 0) : path;
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
536 full_path = sh_makepath (xpath, name, 0);
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
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
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)))
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. */
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);
573
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))
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 */
600 static char *
601 find_user_command_in_path (name, path_list, flags)
602 const char *name;
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);
625 if (stat (".", &dotinfo) < 0)
626 dotinfo.st_dev = dotinfo.st_ino = 0;
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
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
670 return (file_to_lose_on);
671 }
672
673 /* External interface to find a command given a $PATH. Separate from
674 find_user_command_in_path to allow future customization. */
675 char *
676 find_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 }