]> git.ipfire.org Git - thirdparty/bash.git/blame - findcmd.c
Bash-4.3 patch 32
[thirdparty/bash.git] / findcmd.c
CommitLineData
cce855bc
JA
1/* findcmd.c -- Functions to search for commands by name. */
2
ac50fbac 3/* Copyright (C) 1997-2012 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
495aee44
CR
47#if !defined (errno)
48extern int errno;
49#endif
50
cce855bc 51extern int posixly_correct;
ac50fbac 52extern int last_command_exit_value;
cce855bc
JA
53
54/* Static functions defined and used in this file. */
f73dda09
JA
55static char *_find_user_command_internal __P((const char *, int));
56static char *find_user_command_internal __P((const char *, int));
57static char *find_user_command_in_path __P((const char *, char *, int));
58static char *find_in_path_element __P((const char *, char *, int, int, struct stat *));
59static char *find_absolute_program __P((const char *, int));
60
61static char *get_next_path_element __P((char *, int *));
cce855bc
JA
62
63/* The file name which we would try to execute, except that it isn't
64 possible to execute it. This is the first file that matches the
65 name that we are looking for while we are searching $PATH for a
66 suitable one to execute. If we cannot find a suitable executable
67 file, then we use this one. */
68static char *file_to_lose_on;
69
70/* Non-zero if we should stat every command found in the hash table to
71 make sure it still exists. */
72int check_hashed_filenames;
73
74/* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
75 encounters a `.' as the directory pathname while scanning the
76 list of possible pathnames; i.e., if `.' comes before the directory
77 containing the file of interest. */
78int dot_found_in_search = 0;
79
cce855bc
JA
80/* Return some flags based on information about this file.
81 The EXISTS bit is non-zero if the file is found.
82 The EXECABLE bit is non-zero the file is executble.
83 Zero is returned if the file is not found. */
84int
85file_status (name)
f73dda09 86 const char *name;
cce855bc
JA
87{
88 struct stat finfo;
95732b49 89 int r;
cce855bc
JA
90
91 /* Determine whether this file exists or not. */
92 if (stat (name, &finfo) < 0)
93 return (0);
94
95 /* If the file is a directory, then it is not "executable" in the
96 sense of the shell. */
97 if (S_ISDIR (finfo.st_mode))
98 return (FS_EXISTS|FS_DIRECTORY);
99
95732b49
JA
100 r = FS_EXISTS;
101
0001803f
CR
102#if defined (HAVE_EACCESS)
103 /* Use eaccess(2) if we have it to take things like ACLs and other
104 file access mechanisms into account. eaccess uses the effective
105 user and group IDs, not the real ones. We could use sh_eaccess,
106 but we don't want any special treatment for /dev/fd. */
107 if (eaccess (name, X_OK) == 0)
108 r |= FS_EXECABLE;
109 if (eaccess (name, R_OK) == 0)
110 r |= FS_READABLE;
111
112 return r;
113#elif defined (AFS)
cce855bc
JA
114 /* We have to use access(2) to determine access because AFS does not
115 support Unix file system semantics. This may produce wrong
116 answers for non-AFS files when ruid != euid. I hate AFS. */
95732b49
JA
117 if (access (name, X_OK) == 0)
118 r |= FS_EXECABLE;
119 if (access (name, R_OK) == 0)
120 r |= FS_READABLE;
121
122 return r;
0001803f 123#else /* !HAVE_EACCESS && !AFS */
cce855bc
JA
124
125 /* Find out if the file is actually executable. By definition, the
126 only other criteria is that the file has an execute bit set that
95732b49 127 we can use. The same with whether or not a file is readable. */
cce855bc
JA
128
129 /* Root only requires execute permission for any of owner, group or
95732b49 130 others to be able to exec a file, and can read any file. */
cce855bc
JA
131 if (current_user.euid == (uid_t)0)
132 {
95732b49
JA
133 r |= FS_READABLE;
134 if (finfo.st_mode & S_IXUGO)
135 r |= FS_EXECABLE;
136 return r;
cce855bc
JA
137 }
138
95732b49 139 /* If we are the owner of the file, the owner bits apply. */
b80f6443 140 if (current_user.euid == finfo.st_uid)
95732b49
JA
141 {
142 if (finfo.st_mode & S_IXUSR)
143 r |= FS_EXECABLE;
144 if (finfo.st_mode & S_IRUSR)
145 r |= FS_READABLE;
146 }
cce855bc
JA
147
148 /* If we are in the owning group, the group permissions apply. */
b80f6443 149 else if (group_member (finfo.st_gid))
95732b49
JA
150 {
151 if (finfo.st_mode & S_IXGRP)
152 r |= FS_EXECABLE;
153 if (finfo.st_mode & S_IRGRP)
154 r |= FS_READABLE;
155 }
cce855bc 156
b80f6443
JA
157 /* Else we check whether `others' have permission to execute the file */
158 else
95732b49
JA
159 {
160 if (finfo.st_mode & S_IXOTH)
161 r |= FS_EXECABLE;
162 if (finfo.st_mode & S_IROTH)
163 r |= FS_READABLE;
164 }
165
166 return r;
cce855bc
JA
167#endif /* !AFS */
168}
169
170/* Return non-zero if FILE exists and is executable.
171 Note that this function is the definition of what an
172 executable file is; do not change this unless YOU know
173 what an executable file is. */
174int
175executable_file (file)
f73dda09 176 const char *file;
cce855bc
JA
177{
178 int s;
179
180 s = file_status (file);
495aee44
CR
181#if defined EISDIR
182 if (s & FS_DIRECTORY)
183 errno = EISDIR; /* let's see if we can improve error messages */
184#endif
cce855bc
JA
185 return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
186}
187
188int
189is_directory (file)
f73dda09 190 const char *file;
cce855bc
JA
191{
192 return (file_status (file) & FS_DIRECTORY);
193}
194
28ef6c31
JA
195int
196executable_or_directory (file)
f73dda09 197 const char *file;
28ef6c31
JA
198{
199 int s;
200
201 s = file_status (file);
202 return ((s & FS_EXECABLE) || (s & FS_DIRECTORY));
203}
204
cce855bc
JA
205/* Locate the executable file referenced by NAME, searching along
206 the contents of the shell PATH variable. Return a new string
207 which is the full pathname to the file, or NULL if the file
208 couldn't be found. If a file is found that isn't executable,
209 and that is the only match, then return that. */
210char *
211find_user_command (name)
f73dda09 212 const char *name;
cce855bc
JA
213{
214 return (find_user_command_internal (name, FS_EXEC_PREFERRED|FS_NODIRS));
215}
216
217/* Locate the file referenced by NAME, searching along the contents
218 of the shell PATH variable. Return a new string which is the full
219 pathname to the file, or NULL if the file couldn't be found. This
95732b49
JA
220 returns the first readable file found; designed to be used to look
221 for shell scripts or files to source. */
cce855bc
JA
222char *
223find_path_file (name)
f73dda09 224 const char *name;
cce855bc 225{
95732b49 226 return (find_user_command_internal (name, FS_READABLE));
cce855bc
JA
227}
228
229static char *
230_find_user_command_internal (name, flags)
f73dda09 231 const char *name;
cce855bc
JA
232 int flags;
233{
234 char *path_list, *cmd;
235 SHELL_VAR *var;
236
7117c2d2 237 /* Search for the value of PATH in both the temporary environments and
cce855bc 238 in the regular list of variables. */
ac50fbac 239 if (var = find_variable_tempenv ("PATH")) /* XXX could be array? */
cce855bc
JA
240 path_list = value_cell (var);
241 else
242 path_list = (char *)NULL;
243
244 if (path_list == 0 || *path_list == '\0')
245 return (savestring (name));
246
247 cmd = find_user_command_in_path (name, path_list, flags);
248
cce855bc
JA
249 return (cmd);
250}
251
252static char *
253find_user_command_internal (name, flags)
f73dda09 254 const char *name;
cce855bc
JA
255 int flags;
256{
257#ifdef __WIN32__
258 char *res, *dotexe;
259
f73dda09 260 dotexe = (char *)xmalloc (strlen (name) + 5);
cce855bc
JA
261 strcpy (dotexe, name);
262 strcat (dotexe, ".exe");
263 res = _find_user_command_internal (dotexe, flags);
264 free (dotexe);
265 if (res == 0)
266 res = _find_user_command_internal (name, flags);
267 return res;
268#else
269 return (_find_user_command_internal (name, flags));
270#endif
271}
272
273/* Return the next element from PATH_LIST, a colon separated list of
274 paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST;
275 the index is modified by this function.
276 Return the next element of PATH_LIST or NULL if there are no more. */
277static char *
278get_next_path_element (path_list, path_index_pointer)
279 char *path_list;
280 int *path_index_pointer;
281{
282 char *path;
283
284 path = extract_colon_unit (path_list, path_index_pointer);
285
bb70624e 286 if (path == 0)
cce855bc
JA
287 return (path);
288
bb70624e 289 if (*path == '\0')
cce855bc
JA
290 {
291 free (path);
292 path = savestring (".");
293 }
294
295 return (path);
296}
297
298/* Look for PATHNAME in $PATH. Returns either the hashed command
299 corresponding to PATHNAME or the first instance of PATHNAME found
ac50fbac
CR
300 in $PATH. If (FLAGS&1) is non-zero, insert the instance of PATHNAME
301 found in $PATH into the command hash table. Returns a newly-allocated
302 string. */
cce855bc 303char *
ac50fbac 304search_for_command (pathname, flags)
f73dda09 305 const char *pathname;
ac50fbac 306 int flags;
cce855bc
JA
307{
308 char *hashed_file, *command;
309 int temp_path, st;
310 SHELL_VAR *path;
311
312 hashed_file = command = (char *)NULL;
313
314 /* If PATH is in the temporary environment for this command, don't use the
315 hash table to search for the full pathname. */
ac50fbac 316 path = find_variable_tempenv ("PATH");
7117c2d2
JA
317 temp_path = path && tempvar_p (path);
318 if (temp_path == 0 && path)
319 path = (SHELL_VAR *)NULL;
cce855bc
JA
320
321 /* Don't waste time trying to find hashed data for a pathname
322 that is already completely specified or if we're using a command-
323 specific value for PATH. */
324 if (path == 0 && absolute_program (pathname) == 0)
7117c2d2 325 hashed_file = phash_search (pathname);
cce855bc
JA
326
327 /* If a command found in the hash table no longer exists, we need to
328 look for it in $PATH. Thank you Posix.2. This forces us to stat
329 every command found in the hash table. */
330
331 if (hashed_file && (posixly_correct || check_hashed_filenames))
332 {
333 st = file_status (hashed_file);
f1be666c 334 if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
cce855bc 335 {
7117c2d2 336 phash_remove (pathname);
cce855bc
JA
337 free (hashed_file);
338 hashed_file = (char *)NULL;
339 }
340 }
341
342 if (hashed_file)
343 command = hashed_file;
344 else if (absolute_program (pathname))
345 /* A command containing a slash is not looked up in PATH or saved in
346 the hash table. */
347 command = savestring (pathname);
348 else
349 {
350 /* If $PATH is in the temporary environment, we've already retrieved
351 it, so don't bother trying again. */
352 if (temp_path)
28ef6c31 353 {
cce855bc
JA
354 command = find_user_command_in_path (pathname, value_cell (path),
355 FS_EXEC_PREFERRED|FS_NODIRS);
28ef6c31 356 }
cce855bc
JA
357 else
358 command = find_user_command (pathname);
ac50fbac 359 if (command && hashing_enabled && temp_path == 0 && (flags & 1))
7117c2d2 360 phash_insert ((char *)pathname, command, dot_found_in_search, 1); /* XXX fix const later */
cce855bc
JA
361 }
362 return (command);
363}
364
365char *
366user_command_matches (name, flags, state)
f73dda09 367 const char *name;
cce855bc
JA
368 int flags, state;
369{
370 register int i;
371 int path_index, name_len;
372 char *path_list, *path_element, *match;
373 struct stat dotinfo;
374 static char **match_list = NULL;
375 static int match_list_size = 0;
376 static int match_index = 0;
377
378 if (state == 0)
379 {
380 /* Create the list of matches. */
381 if (match_list == 0)
382 {
383 match_list_size = 5;
7117c2d2 384 match_list = strvec_create (match_list_size);
cce855bc
JA
385 }
386
387 /* Clear out the old match list. */
388 for (i = 0; i < match_list_size; i++)
389 match_list[i] = 0;
390
391 /* We haven't found any files yet. */
392 match_index = 0;
393
394 if (absolute_program (name))
395 {
396 match_list[0] = find_absolute_program (name, flags);
397 match_list[1] = (char *)NULL;
398 path_list = (char *)NULL;
399 }
400 else
401 {
402 name_len = strlen (name);
403 file_to_lose_on = (char *)NULL;
404 dot_found_in_search = 0;
ac50fbac
CR
405 if (stat (".", &dotinfo) < 0)
406 dotinfo.st_dev = dotinfo.st_ino = 0; /* so same_file won't match */
cce855bc
JA
407 path_list = get_string_value ("PATH");
408 path_index = 0;
409 }
410
411 while (path_list && path_list[path_index])
412 {
413 path_element = get_next_path_element (path_list, &path_index);
414
415 if (path_element == 0)
416 break;
417
418 match = find_in_path_element (name, path_element, flags, name_len, &dotinfo);
419
420 free (path_element);
421
422 if (match == 0)
423 continue;
424
425 if (match_index + 1 == match_list_size)
426 {
427 match_list_size += 10;
7117c2d2 428 match_list = strvec_resize (match_list, (match_list_size + 1));
cce855bc
JA
429 }
430
431 match_list[match_index++] = match;
432 match_list[match_index] = (char *)NULL;
433 FREE (file_to_lose_on);
434 file_to_lose_on = (char *)NULL;
435 }
436
437 /* We haven't returned any strings yet. */
438 match_index = 0;
439 }
440
441 match = match_list[match_index];
442
443 if (match)
444 match_index++;
445
446 return (match);
447}
448
cce855bc
JA
449static char *
450find_absolute_program (name, flags)
f73dda09 451 const char *name;
cce855bc
JA
452 int flags;
453{
454 int st;
455
456 st = file_status (name);
457
458 /* If the file doesn't exist, quit now. */
459 if ((st & FS_EXISTS) == 0)
460 return ((char *)NULL);
461
462 /* If we only care about whether the file exists or not, return
463 this filename. Otherwise, maybe we care about whether this
464 file is executable. If it is, and that is what we want, return it. */
465 if ((flags & FS_EXISTS) || ((flags & FS_EXEC_ONLY) && (st & FS_EXECABLE)))
466 return (savestring (name));
467
f73dda09 468 return (NULL);
cce855bc
JA
469}
470
471static char *
472find_in_path_element (name, path, flags, name_len, dotinfop)
f73dda09
JA
473 const char *name;
474 char *path;
cce855bc
JA
475 int flags, name_len;
476 struct stat *dotinfop;
477{
478 int status;
479 char *full_path, *xpath;
480
7117c2d2 481 xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path;
cce855bc
JA
482
483 /* Remember the location of "." in the path, in all its forms
484 (as long as they begin with a `.', e.g. `./.') */
485 if (dot_found_in_search == 0 && *xpath == '.')
486 dot_found_in_search = same_file (".", xpath, dotinfop, (struct stat *)NULL);
487
bb70624e 488 full_path = sh_makepath (xpath, name, 0);
cce855bc
JA
489
490 status = file_status (full_path);
491
492 if (xpath != path)
493 free (xpath);
494
495 if ((status & FS_EXISTS) == 0)
496 {
497 free (full_path);
498 return ((char *)NULL);
499 }
500
501 /* The file exists. If the caller simply wants the first file, here it is. */
502 if (flags & FS_EXISTS)
503 return (full_path);
504
95732b49
JA
505 /* If we have a readable file, and the caller wants a readable file, this
506 is it. */
507 if ((flags & FS_READABLE) && (status & FS_READABLE))
508 return (full_path);
509
cce855bc
JA
510 /* If the file is executable, then it satisfies the cases of
511 EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
95732b49 512 if ((status & FS_EXECABLE) && (flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) &&
cce855bc
JA
513 (((flags & FS_NODIRS) == 0) || ((status & FS_DIRECTORY) == 0)))
514 {
515 FREE (file_to_lose_on);
516 file_to_lose_on = (char *)NULL;
517 return (full_path);
518 }
519
520 /* The file is not executable, but it does exist. If we prefer
521 an executable, then remember this one if it is the first one
522 we have found. */
523 if ((flags & FS_EXEC_PREFERRED) && file_to_lose_on == 0)
524 file_to_lose_on = savestring (full_path);
525
526 /* If we want only executable files, or we don't want directories and
95732b49
JA
527 this file is a directory, or we want a readable file and this file
528 isn't readable, fail. */
529 if ((flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) ||
530 ((flags & FS_NODIRS) && (status & FS_DIRECTORY)) ||
531 ((flags & FS_READABLE) && (status & FS_READABLE) == 0))
cce855bc
JA
532 {
533 free (full_path);
534 return ((char *)NULL);
535 }
536 else
537 return (full_path);
538}
539
540/* This does the dirty work for find_user_command_internal () and
541 user_command_matches ().
542 NAME is the name of the file to search for.
543 PATH_LIST is a colon separated list of directories to search.
544 FLAGS contains bit fields which control the files which are eligible.
545 Some values are:
546 FS_EXEC_ONLY: The file must be an executable to be found.
547 FS_EXEC_PREFERRED: If we can't find an executable, then the
548 the first file matching NAME will do.
549 FS_EXISTS: The first file found will do.
550 FS_NODIRS: Don't find any directories.
551*/
552static char *
553find_user_command_in_path (name, path_list, flags)
f73dda09 554 const char *name;
cce855bc
JA
555 char *path_list;
556 int flags;
557{
558 char *full_path, *path;
559 int path_index, name_len;
560 struct stat dotinfo;
561
562 /* We haven't started looking, so we certainly haven't seen
563 a `.' as the directory path yet. */
564 dot_found_in_search = 0;
565
566 if (absolute_program (name))
567 {
568 full_path = find_absolute_program (name, flags);
569 return (full_path);
570 }
571
572 if (path_list == 0 || *path_list == '\0')
573 return (savestring (name)); /* XXX */
574
575 file_to_lose_on = (char *)NULL;
576 name_len = strlen (name);
ac50fbac
CR
577 if (stat (".", &dotinfo) < 0)
578 dotinfo.st_dev = dotinfo.st_ino = 0;
cce855bc
JA
579 path_index = 0;
580
581 while (path_list[path_index])
582 {
583 /* Allow the user to interrupt out of a lengthy path search. */
584 QUIT;
585
586 path = get_next_path_element (path_list, &path_index);
587 if (path == 0)
588 break;
589
590 /* Side effects: sets dot_found_in_search, possibly sets
591 file_to_lose_on. */
592 full_path = find_in_path_element (name, path, flags, name_len, &dotinfo);
593 free (path);
594
595 /* This should really be in find_in_path_element, but there isn't the
596 right combination of flags. */
597 if (full_path && is_directory (full_path))
598 {
599 free (full_path);
600 continue;
601 }
602
603 if (full_path)
604 {
605 FREE (file_to_lose_on);
606 return (full_path);
607 }
608 }
609
610 /* We didn't find exactly what the user was looking for. Return
611 the contents of FILE_TO_LOSE_ON which is NULL when the search
612 required an executable, or non-NULL if a file was found and the
28ef6c31
JA
613 search would accept a non-executable as a last resort. If the
614 caller specified FS_NODIRS, and file_to_lose_on is a directory,
615 return NULL. */
616 if (file_to_lose_on && (flags & FS_NODIRS) && is_directory (file_to_lose_on))
617 {
618 free (file_to_lose_on);
619 file_to_lose_on = (char *)NULL;
620 }
621
cce855bc
JA
622 return (file_to_lose_on);
623}