1 /* pathexp.c -- The shell interface to the globbing library. */
3 /* Copyright (C) 1995 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #include "bashtypes.h"
26 #if defined (HAVE_UNISTD_H)
36 #include <glob/strmatch.h>
38 #if defined (USE_POSIX_GLOB_LIBRARY)
40 typedef int posix_glob_errfunc_t __P((const char *, int));
42 # include <glob/glob.h>
45 /* Control whether * matches .files in globbing. */
46 int glob_dot_filenames;
48 /* Control whether the extended globbing features are enabled. */
49 int extended_glob = 0;
51 /* Return nonzero if STRING has any unquoted special globbing chars in it. */
53 unquoted_glob_pattern_p (string)
54 register char *string;
80 if (*string == '(') /*)*/
86 if (*string++ == '\0')
93 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
94 that the character is to be quoted. We quote it here in the style
95 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
96 we change quoted null strings (pathname[0] == CTLNUL) into empty
97 strings (pathname[0] == 0). If this is called after quote removal
98 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
99 removal has not been done (for example, before attempting to match a
100 pattern while executing a case statement), flags should include
101 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
102 to match a filename should be performed. */
104 quote_string_for_globbing (pathname, qflags)
105 const char *pathname;
111 temp = (char *)xmalloc (strlen (pathname) + 1);
113 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
119 for (i = j = 0; pathname[i]; i++)
121 if (pathname[i] == CTLESC)
123 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
128 temp[j++] = pathname[i];
136 quote_globbing_chars (string)
141 temp = (char *)xmalloc (strlen (string) * 2 + 1);
142 for (t = temp, s = string; *s; )
156 if (s[1] == '(') /*(*/
166 /* Call the glob library to do globbing on PATHNAME. */
168 shell_glob_filename (pathname)
169 const char *pathname;
171 #if defined (USE_POSIX_GLOB_LIBRARY)
173 char *temp, **results;
177 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
179 filenames.gl_offs = 0;
181 # if defined (GLOB_PERIOD)
182 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
185 # endif /* !GLOB_PERIOD */
187 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
189 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
193 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
194 return ((char **)NULL);
195 else if (i == GLOB_NOMATCH)
196 filenames.gl_pathv = (char **)NULL;
197 else if (i != 0) /* other error codes not in POSIX.2 */
198 filenames.gl_pathv = (char **)NULL;
200 results = filenames.gl_pathv;
202 if (results && ((GLOB_FAILED (results)) == 0))
204 if (should_ignore_glob_matches ())
205 ignore_glob_matches (results);
206 if (results && results[0])
207 sort_char_array (results);
211 results = (char **)NULL;
217 #else /* !USE_POSIX_GLOB_LIBRARY */
219 char *temp, **results;
221 noglob_dot_filenames = glob_dot_filenames == 0;
223 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
225 results = glob_filename (temp);
228 if (results && ((GLOB_FAILED (results)) == 0))
230 if (should_ignore_glob_matches ())
231 ignore_glob_matches (results);
232 if (results && results[0])
233 sort_char_array (results);
237 results = (char **)&glob_error_return;
242 #endif /* !USE_POSIX_GLOB_LIBRARY */
245 /* Stuff for GLOBIGNORE. */
247 static struct ignorevar globignore =
253 (sh_iv_item_func_t *)0,
256 /* Set up to ignore some glob matches because the value of GLOBIGNORE
257 has changed. If GLOBIGNORE is being unset, we also need to disable
258 the globbing of filenames beginning with a `.'. */
260 setup_glob_ignore (name)
265 v = get_string_value (name);
266 setup_ignore_patterns (&globignore);
268 if (globignore.num_ignores)
269 glob_dot_filenames = 1;
271 glob_dot_filenames = 0;
275 should_ignore_glob_matches ()
277 return globignore.num_ignores;
280 /* Return 0 if NAME matches a pattern in the globignore.ignores list. */
282 glob_name_is_acceptable (name)
288 /* . and .. are never matched */
289 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
292 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
293 for (p = globignore.ignores; p->val; p++)
295 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
301 /* Internal function to test whether filenames in NAMES should be
302 ignored. NAME_FUNC is a pointer to a function to call with each
303 name. It returns non-zero if the name is acceptable to the particular
304 ignore function which called _ignore_names; zero if the name should
305 be removed from NAMES. */
308 ignore_globbed_names (names, name_func)
310 sh_ignore_func_t *name_func;
315 for (i = 0; names[i]; i++)
317 newnames = alloc_array (i + 1);
319 for (n = i = 0; names[i]; i++)
321 if ((*name_func) (names[i]))
322 newnames[n++] = names[i];
327 newnames[n] = (char *)NULL;
331 names[0] = (char *)NULL;
336 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
338 for (n = 0; newnames[n]; n++)
339 names[n] = newnames[n];
340 names[n] = (char *)NULL;
345 ignore_glob_matches (names)
348 if (globignore.num_ignores == 0)
351 ignore_globbed_names (names, glob_name_is_acceptable);
355 setup_ignore_patterns (ivp)
356 struct ignorevar *ivp;
358 int numitems, maxitems, ptr;
359 char *colon_bit, *this_ignoreval;
362 this_ignoreval = get_string_value (ivp->varname);
364 /* If nothing has changed then just exit now. */
365 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
366 (!this_ignoreval && !ivp->last_ignoreval))
369 /* Oops. The ignore variable has changed. Re-parse it. */
370 ivp->num_ignores = 0;
374 for (p = ivp->ignores; p->val; p++)
377 ivp->ignores = (struct ign *)NULL;
380 if (ivp->last_ignoreval)
382 free (ivp->last_ignoreval);
383 ivp->last_ignoreval = (char *)NULL;
386 if (this_ignoreval == 0 || *this_ignoreval == '\0')
389 ivp->last_ignoreval = savestring (this_ignoreval);
391 numitems = maxitems = ptr = 0;
393 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
395 if (numitems + 1 >= maxitems)
398 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
400 ivp->ignores[numitems].val = colon_bit;
401 ivp->ignores[numitems].len = strlen (colon_bit);
402 ivp->ignores[numitems].flags = 0;
404 (*ivp->item_func) (&ivp->ignores[numitems]);
407 ivp->ignores[numitems].val = (char *)NULL;
408 ivp->num_ignores = numitems;