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