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