No specific user configuration
[platform/upstream/bash.git] / findcmd.c
1 /* findcmd.c -- Functions to search for commands by name. */
2
3 /* Copyright (C) 1997-2012 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 #if !defined (errno)
48 extern int errno;
49 #endif
50
51 extern int posixly_correct;
52 extern int last_command_exit_value;
53
54 /* Static functions defined and used in this file. */
55 static char *_find_user_command_internal __P((const char *, int));
56 static char *find_user_command_internal __P((const char *, int));
57 static char *find_user_command_in_path __P((const char *, char *, int));
58 static char *find_in_path_element __P((const char *, char *, int, int, struct stat *));
59 static char *find_absolute_program __P((const char *, int));
60
61 static char *get_next_path_element __P((char *, int *));
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. */
68 static 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. */
72 int 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. */
78 int dot_found_in_search = 0;
79
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. */
84 int
85 file_status (name)
86      const char *name;
87 {
88   struct stat finfo;
89   int r;
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
100   r = FS_EXISTS;
101
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)
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. */
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;
123 #else /* !HAVE_EACCESS && !AFS */
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
127      we can use.  The same with whether or not a file is readable. */
128
129   /* Root only requires execute permission for any of owner, group or
130      others to be able to exec a file, and can read any file. */
131   if (current_user.euid == (uid_t)0)
132     {
133       r |= FS_READABLE;
134       if (finfo.st_mode & S_IXUGO)
135         r |= FS_EXECABLE;
136       return r;
137     }
138
139   /* If we are the owner of the file, the owner bits apply. */
140   if (current_user.euid == finfo.st_uid)
141     {
142       if (finfo.st_mode & S_IXUSR)
143         r |= FS_EXECABLE;
144       if (finfo.st_mode & S_IRUSR)
145         r |= FS_READABLE;
146     }
147
148   /* If we are in the owning group, the group permissions apply. */
149   else if (group_member (finfo.st_gid))
150     {
151       if (finfo.st_mode & S_IXGRP)
152         r |= FS_EXECABLE;
153       if (finfo.st_mode & S_IRGRP)
154         r |= FS_READABLE;
155     }
156
157   /* Else we check whether `others' have permission to execute the file */
158   else
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;
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. */
174 int
175 executable_file (file)
176      const char *file;
177 {
178   int s;
179
180   s = file_status (file);
181 #if defined EISDIR
182   if (s & FS_DIRECTORY)
183     errno = EISDIR;     /* let's see if we can improve error messages */
184 #endif
185   return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
186 }
187
188 int
189 is_directory (file)
190      const char *file;
191 {
192   return (file_status (file) & FS_DIRECTORY);
193 }
194
195 int
196 executable_or_directory (file)
197      const char *file;
198 {
199   int s;
200
201   s = file_status (file);
202   return ((s & FS_EXECABLE) || (s & FS_DIRECTORY));
203 }
204
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. */
210 char *
211 find_user_command (name)
212      const char *name;
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
220    returns the first readable file found; designed to be used to look
221    for shell scripts or files to source. */
222 char *
223 find_path_file (name)
224      const char *name;
225 {
226   return (find_user_command_internal (name, FS_READABLE));
227 }
228
229 static char *
230 _find_user_command_internal (name, flags)
231      const char *name;
232      int flags;
233 {
234   char *path_list, *cmd;
235   SHELL_VAR *var;
236
237   /* Search for the value of PATH in both the temporary environments and
238      in the regular list of variables. */
239   if (var = find_variable_tempenv ("PATH"))     /* XXX could be array? */
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
249   return (cmd);
250 }
251
252 static char *
253 find_user_command_internal (name, flags)
254      const char *name;
255      int flags;
256 {
257 #ifdef __WIN32__
258   char *res, *dotexe;
259
260   dotexe = (char *)xmalloc (strlen (name) + 5);
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. */
277 static char *
278 get_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
286   if (path == 0)
287     return (path);
288
289   if (*path == '\0')
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
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. */
303 char *
304 search_for_command (pathname, flags)
305      const char *pathname;
306      int flags;
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. */
316   path = find_variable_tempenv ("PATH");
317   temp_path = path && tempvar_p (path);
318   if (temp_path == 0 && path)
319     path = (SHELL_VAR *)NULL;
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)
325     hashed_file = phash_search (pathname);
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);
334       if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
335         {
336           phash_remove (pathname);
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)
353         {
354           command = find_user_command_in_path (pathname, value_cell (path),
355                                                FS_EXEC_PREFERRED|FS_NODIRS);
356         }
357       else
358         command = find_user_command (pathname);
359       if (command && hashing_enabled && temp_path == 0 && (flags & 1))
360         phash_insert ((char *)pathname, command, dot_found_in_search, 1);       /* XXX fix const later */
361     }
362   return (command);
363 }
364
365 char *
366 user_command_matches (name, flags, state)
367      const char *name;
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;
384           match_list = strvec_create (match_list_size);
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;
405           if (stat (".", &dotinfo) < 0)
406             dotinfo.st_dev = dotinfo.st_ino = 0;        /* so same_file won't match */
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;
428               match_list = strvec_resize (match_list, (match_list_size + 1));
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
449 static char *
450 find_absolute_program (name, flags)
451      const char *name;
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
468   return (NULL);
469 }
470
471 static char *
472 find_in_path_element (name, path, flags, name_len, dotinfop)
473      const char *name;
474      char *path;
475      int flags, name_len;
476      struct stat *dotinfop;
477 {
478   int status;
479   char *full_path, *xpath;
480
481   xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path;
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
488   full_path = sh_makepath (xpath, name, 0);
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
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
510   /* If the file is executable, then it satisfies the cases of
511       EXEC_ONLY and EXEC_PREFERRED.  Return this file unconditionally. */
512   if ((status & FS_EXECABLE) && (flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) &&
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
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))
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 */
552 static char *
553 find_user_command_in_path (name, path_list, flags)
554      const char *name;
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);
577   if (stat (".", &dotinfo) < 0)
578     dotinfo.st_dev = dotinfo.st_ino = 0;
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
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
622   return (file_to_lose_on);
623 }