Line data Source code
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 0 : setup_exec_ignore (varname)
95 : char *varname;
96 : {
97 0 : setup_ignore_patterns (&execignore);
98 0 : }
99 :
100 : static int
101 95190 : exec_name_should_ignore (name)
102 : const char *name;
103 : {
104 95190 : struct ign *p;
105 :
106 95190 : for (p = execignore.ignores; p && p->val; p++)
107 0 : 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 26948868 : file_status (name)
118 : const char *name;
119 : {
120 26948868 : struct stat finfo;
121 26948868 : int r;
122 :
123 : /* Determine whether this file exists or not. */
124 26948868 : 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 97369 : if (S_ISDIR (finfo.st_mode))
130 : return (FS_EXISTS|FS_DIRECTORY);
131 :
132 94569 : 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 94569 : if (exec_name_should_ignore (name) == 0 && eaccess (name, X_OK) == 0)
140 94190 : r |= FS_EXECABLE;
141 94569 : if (eaccess (name, R_OK) == 0)
142 94106 : 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 151257 : executable_file (file)
208 : const char *file;
209 : {
210 151257 : int s;
211 :
212 151257 : s = file_status (file);
213 : #if defined (EISDIR)
214 151257 : if (s & FS_DIRECTORY)
215 0 : errno = EISDIR; /* let's see if we can improve error messages */
216 : #endif
217 151257 : return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
218 : }
219 :
220 : int
221 0 : is_directory (file)
222 : const char *file;
223 : {
224 0 : return (file_status (file) & FS_DIRECTORY);
225 : }
226 :
227 : int
228 0 : executable_or_directory (file)
229 : const char *file;
230 : {
231 0 : int s;
232 :
233 0 : s = file_status (file);
234 0 : 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 131 : find_user_command (name)
244 : const char *name;
245 : {
246 262 : 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 12498 : find_path_file (name)
256 : const char *name;
257 : {
258 24996 : return (find_user_command_internal (name, FS_READABLE));
259 : }
260 :
261 : static char *
262 12629 : _find_user_command_internal (name, flags)
263 : const char *name;
264 : int flags;
265 : {
266 12629 : char *path_list, *cmd;
267 12629 : 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 12629 : if (var = find_variable_tempenv ("PATH")) /* XXX could be array? */
272 12629 : path_list = value_cell (var);
273 : else
274 : path_list = (char *)NULL;
275 :
276 12629 : if (path_list == 0 || *path_list == '\0')
277 0 : return (savestring (name));
278 :
279 12629 : cmd = find_user_command_in_path (name, path_list, flags);
280 :
281 12629 : 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 12629 : 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 26738014 : get_next_path_element (path_list, path_index_pointer)
311 : char *path_list;
312 : int *path_index_pointer;
313 : {
314 26738014 : char *path;
315 :
316 26738014 : path = extract_colon_unit (path_list, path_index_pointer);
317 :
318 26738014 : if (path == 0)
319 : return (path);
320 :
321 26738014 : if (*path == '\0')
322 : {
323 0 : free (path);
324 0 : 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 7040326 : search_for_command (pathname, flags)
339 : const char *pathname;
340 : int flags;
341 : {
342 7040326 : char *hashed_file, *command, *pathlist;
343 7040326 : int temp_path, st;
344 7040326 : SHELL_VAR *path;
345 :
346 7040326 : 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 7040326 : path = find_variable_tempenv ("PATH");
351 7040326 : 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 7040326 : if (temp_path == 0 && absolute_program (pathname) == 0)
357 5374899 : 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 5374899 : if (hashed_file && (posixly_correct || check_hashed_filenames))
364 : {
365 0 : st = file_status (hashed_file);
366 0 : if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
367 : {
368 0 : phash_remove (pathname);
369 0 : free (hashed_file);
370 0 : hashed_file = (char *)NULL;
371 : }
372 : }
373 :
374 7040326 : if (hashed_file)
375 : command = hashed_file;
376 7040234 : 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 1665427 : command = savestring (pathname);
380 : else
381 : {
382 5374807 : if (flags & CMDSRCH_STDPATH)
383 0 : pathlist = conf_standard_path ();
384 5374807 : else if (temp_path || path)
385 5374807 : pathlist = value_cell (path);
386 : else
387 : pathlist = 0;
388 :
389 5374807 : command = find_user_command_in_path (pathname, pathlist, FS_EXEC_PREFERRED|FS_NODIRS);
390 :
391 5374807 : 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 47129 : if (STREQ (command, pathname))
397 : {
398 0 : st = file_status (command);
399 0 : if (st & FS_EXECABLE)
400 0 : phash_insert ((char *)pathname, command, dot_found_in_search, 1);
401 : }
402 : else
403 47129 : phash_insert ((char *)pathname, command, dot_found_in_search, 1);
404 : }
405 :
406 5374807 : if (flags & CMDSRCH_STDPATH)
407 0 : free (pathlist);
408 : }
409 :
410 7040326 : return (command);
411 : }
412 :
413 : char *
414 0 : user_command_matches (name, flags, state)
415 : const char *name;
416 : int flags, state;
417 : {
418 0 : register int i;
419 0 : int path_index, name_len;
420 0 : char *path_list, *path_element, *match;
421 0 : struct stat dotinfo;
422 0 : static char **match_list = NULL;
423 0 : static int match_list_size = 0;
424 0 : static int match_index = 0;
425 :
426 0 : if (state == 0)
427 : {
428 : /* Create the list of matches. */
429 0 : if (match_list == 0)
430 : {
431 0 : match_list_size = 5;
432 0 : match_list = strvec_create (match_list_size);
433 : }
434 :
435 : /* Clear out the old match list. */
436 0 : for (i = 0; i < match_list_size; i++)
437 0 : match_list[i] = 0;
438 :
439 : /* We haven't found any files yet. */
440 0 : match_index = 0;
441 :
442 0 : if (absolute_program (name))
443 : {
444 0 : match_list[0] = find_absolute_program (name, flags);
445 0 : match_list[1] = (char *)NULL;
446 0 : path_list = (char *)NULL;
447 : }
448 : else
449 : {
450 0 : name_len = strlen (name);
451 0 : file_to_lose_on = (char *)NULL;
452 0 : dot_found_in_search = 0;
453 0 : if (stat (".", &dotinfo) < 0)
454 0 : dotinfo.st_dev = dotinfo.st_ino = 0; /* so same_file won't match */
455 0 : path_list = get_string_value ("PATH");
456 0 : path_index = 0;
457 : }
458 :
459 0 : while (path_list && path_list[path_index])
460 : {
461 0 : path_element = get_next_path_element (path_list, &path_index);
462 :
463 0 : if (path_element == 0)
464 : break;
465 :
466 0 : match = find_in_path_element (name, path_element, flags, name_len, &dotinfo);
467 :
468 0 : free (path_element);
469 :
470 0 : if (match == 0)
471 : continue;
472 :
473 0 : if (match_index + 1 == match_list_size)
474 : {
475 0 : match_list_size += 10;
476 0 : match_list = strvec_resize (match_list, (match_list_size + 1));
477 : }
478 :
479 0 : match_list[match_index++] = match;
480 0 : match_list[match_index] = (char *)NULL;
481 0 : FREE (file_to_lose_on);
482 0 : file_to_lose_on = (char *)NULL;
483 : }
484 :
485 : /* We haven't returned any strings yet. */
486 0 : match_index = 0;
487 : }
488 :
489 0 : match = match_list[match_index];
490 :
491 0 : if (match)
492 0 : match_index++;
493 :
494 0 : return (match);
495 : }
496 :
497 : static char *
498 11881 : find_absolute_program (name, flags)
499 : const char *name;
500 : int flags;
501 : {
502 11881 : int st;
503 :
504 11881 : st = file_status (name);
505 :
506 : /* If the file doesn't exist, quit now. */
507 11881 : 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 0 : if ((flags & FS_EXISTS) || ((flags & FS_EXEC_ONLY) && (st & FS_EXECABLE)))
514 0 : return (savestring (name));
515 :
516 : return (NULL);
517 : }
518 :
519 : static char *
520 0 : 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 0 : int status;
527 0 : char *full_path, *xpath;
528 :
529 0 : 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 0 : if (dot_found_in_search == 0 && *xpath == '.')
534 0 : dot_found_in_search = same_file (".", xpath, dotinfop, (struct stat *)NULL);
535 :
536 0 : full_path = sh_makepath (xpath, name, 0);
537 :
538 0 : status = file_status (full_path);
539 :
540 0 : if (xpath != path)
541 0 : free (xpath);
542 :
543 0 : if ((status & FS_EXISTS) == 0)
544 : {
545 0 : free (full_path);
546 0 : return ((char *)NULL);
547 : }
548 :
549 : /* The file exists. If the caller simply wants the first file, here it is. */
550 0 : if (flags & FS_EXISTS)
551 0 : return (full_path);
552 :
553 : /* If we have a readable file, and the caller wants a readable file, this
554 : is it. */
555 0 : if ((flags & FS_READABLE) && (status & FS_READABLE))
556 0 : 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 0 : if ((status & FS_EXECABLE) && (flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) &&
561 0 : (((flags & FS_NODIRS) == 0) || ((status & FS_DIRECTORY) == 0)))
562 : {
563 0 : FREE (file_to_lose_on);
564 0 : file_to_lose_on = (char *)NULL;
565 0 : 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 0 : if ((flags & FS_EXEC_PREFERRED) && file_to_lose_on == 0 && exec_name_should_ignore (full_path) == 0)
572 0 : 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 0 : if ((flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) ||
578 0 : ((flags & FS_NODIRS) && (status & FS_DIRECTORY)) ||
579 0 : ((flags & FS_READABLE) && (status & FS_READABLE) == 0))
580 : {
581 0 : free (full_path);
582 0 : return ((char *)NULL);
583 : }
584 : else
585 0 : 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 5387436 : find_user_command_in_path (name, path_list, flags)
602 : const char *name;
603 : char *path_list;
604 : int flags;
605 : {
606 5387436 : char *full_path, *path;
607 5387436 : int path_index, name_len;
608 5387436 : struct stat dotinfo;
609 :
610 : /* We haven't started looking, so we certainly haven't seen
611 : a `.' as the directory path yet. */
612 5387436 : dot_found_in_search = 0;
613 :
614 5387436 : if (absolute_program (name))
615 : {
616 11881 : full_path = find_absolute_program (name, flags);
617 11881 : return (full_path);
618 : }
619 :
620 5375555 : if (path_list == 0 || *path_list == '\0')
621 0 : return (savestring (name)); /* XXX */
622 :
623 5375555 : file_to_lose_on = (char *)NULL;
624 5375555 : name_len = strlen (name);
625 5375555 : if (stat (".", &dotinfo) < 0)
626 0 : dotinfo.st_dev = dotinfo.st_ino = 0;
627 5375555 : path_index = 0;
628 :
629 32066474 : while (path_list[path_index])
630 : {
631 : /* Allow the user to interrupt out of a lengthy path search. */
632 26738014 : QUIT;
633 :
634 26738014 : path = get_next_path_element (path_list, &path_index);
635 26738014 : if (path == 0)
636 : break;
637 :
638 : /* Side effects: sets dot_found_in_search, possibly sets
639 : file_to_lose_on. */
640 26738014 : full_path = find_in_path_element (name, path, flags, name_len, &dotinfo);
641 26738014 : free (path);
642 :
643 : /* This should really be in find_in_path_element, but there isn't the
644 : right combination of flags. */
645 26738014 : if (full_path && is_directory (full_path))
646 : {
647 0 : free (full_path);
648 0 : continue;
649 : }
650 :
651 26738014 : if (full_path)
652 : {
653 47095 : FREE (file_to_lose_on);
654 47095 : 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 5328460 : if (file_to_lose_on && (flags & FS_NODIRS) && is_directory (file_to_lose_on))
665 : {
666 560 : free (file_to_lose_on);
667 560 : file_to_lose_on = (char *)NULL;
668 : }
669 :
670 5328460 : 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 0 : find_in_path (name, path_list, flags)
677 : const char *name;
678 : char *path_list;
679 : int flags;
680 : {
681 0 : return (find_user_command_in_path (name, path_list, flags));
682 : }
|