1 /* pathexp.c -- The shell interface to the globbing library. */
3 /* Copyright (C) 1995-2009 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
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.
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.
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/>.
23 #include "bashtypes.h"
26 #if defined (HAVE_UNISTD_H)
39 #include <glob/strmatch.h>
41 static int glob_name_is_acceptable __P((const char *));
42 static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
43 static char *split_ignorespec __P((char *, int *));
45 #if defined (USE_POSIX_GLOB_LIBRARY)
47 typedef int posix_glob_errfunc_t __P((const char *, int));
49 # include <glob/glob.h>
52 /* Control whether * matches .files in globbing. */
53 int glob_dot_filenames;
55 /* Control whether the extended globbing features are enabled. */
56 int extended_glob = EXTGLOB_DEFAULT;
58 /* Control enabling special handling of `**' */
61 /* Return nonzero if STRING has any unquoted special globbing chars in it. */
63 unquoted_glob_pattern_p (string)
64 register char *string;
73 send = string + strlen (string);
95 if (*string == '(') /*)*/
101 if (*string++ == '\0')
105 /* Advance one fewer byte than an entire multibyte character to
106 account for the auto-increment in the loop above. */
107 #ifdef HANDLE_MULTIBYTE
109 ADVANCE_CHAR_P (string, send - string);
112 ADVANCE_CHAR_P (string, send - string);
118 /* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
119 be quoted to match itself. */
160 if (s[1] == '(') /*(*/
167 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
168 that the character is to be quoted. We quote it here in the style
169 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
170 we change quoted null strings (pathname[0] == CTLNUL) into empty
171 strings (pathname[0] == 0). If this is called after quote removal
172 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
173 removal has not been done (for example, before attempting to match a
174 pattern while executing a case statement), flags should include
175 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
176 to match a filename should be performed. */
178 quote_string_for_globbing (pathname, qflags)
179 const char *pathname;
185 temp = (char *)xmalloc (strlen (pathname) + 1);
187 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
193 for (i = j = 0; pathname[i]; i++)
195 if (pathname[i] == CTLESC)
197 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
199 if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
203 if (pathname[i] == '\0')
206 else if (pathname[i] == '\\')
210 if (pathname[i] == '\0')
213 temp[j++] = pathname[i];
221 quote_globbing_chars (string)
225 char *temp, *s, *t, *send;
228 slen = strlen (string);
229 send = string + slen;
231 temp = (char *)xmalloc (slen * 2 + 1);
232 for (t = temp, s = string; *s; )
237 /* Copy a single (possibly multibyte) character from s to t,
238 incrementing both. */
239 COPY_CHAR_P (t, s, send);
245 /* Call the glob library to do globbing on PATHNAME. */
247 shell_glob_filename (pathname)
248 const char *pathname;
250 #if defined (USE_POSIX_GLOB_LIBRARY)
252 char *temp, **results;
256 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
258 filenames.gl_offs = 0;
260 # if defined (GLOB_PERIOD)
261 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
264 # endif /* !GLOB_PERIOD */
266 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
268 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
272 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
273 return ((char **)NULL);
274 else if (i == GLOB_NOMATCH)
275 filenames.gl_pathv = (char **)NULL;
276 else if (i != 0) /* other error codes not in POSIX.2 */
277 filenames.gl_pathv = (char **)NULL;
279 results = filenames.gl_pathv;
281 if (results && ((GLOB_FAILED (results)) == 0))
283 if (should_ignore_glob_matches ())
284 ignore_glob_matches (results);
285 if (results && results[0])
286 strvec_sort (results);
290 results = (char **)NULL;
296 #else /* !USE_POSIX_GLOB_LIBRARY */
298 char *temp, **results;
300 noglob_dot_filenames = glob_dot_filenames == 0;
302 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
303 results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
306 if (results && ((GLOB_FAILED (results)) == 0))
308 if (should_ignore_glob_matches ())
309 ignore_glob_matches (results);
310 if (results && results[0])
311 strvec_sort (results);
315 results = (char **)&glob_error_return;
320 #endif /* !USE_POSIX_GLOB_LIBRARY */
323 /* Stuff for GLOBIGNORE. */
325 static struct ignorevar globignore =
331 (sh_iv_item_func_t *)0,
334 /* Set up to ignore some glob matches because the value of GLOBIGNORE
335 has changed. If GLOBIGNORE is being unset, we also need to disable
336 the globbing of filenames beginning with a `.'. */
338 setup_glob_ignore (name)
343 v = get_string_value (name);
344 setup_ignore_patterns (&globignore);
346 if (globignore.num_ignores)
347 glob_dot_filenames = 1;
349 glob_dot_filenames = 0;
353 should_ignore_glob_matches ()
355 return globignore.num_ignores;
358 /* Return 0 if NAME matches a pattern in the globignore.ignores list. */
360 glob_name_is_acceptable (name)
366 /* . and .. are never matched */
367 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
370 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
371 for (p = globignore.ignores; p->val; p++)
373 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
379 /* Internal function to test whether filenames in NAMES should be
380 ignored. NAME_FUNC is a pointer to a function to call with each
381 name. It returns non-zero if the name is acceptable to the particular
382 ignore function which called _ignore_names; zero if the name should
383 be removed from NAMES. */
386 ignore_globbed_names (names, name_func)
388 sh_ignore_func_t *name_func;
393 for (i = 0; names[i]; i++)
395 newnames = strvec_create (i + 1);
397 for (n = i = 0; names[i]; i++)
399 if ((*name_func) (names[i]))
400 newnames[n++] = names[i];
405 newnames[n] = (char *)NULL;
409 names[0] = (char *)NULL;
414 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
416 for (n = 0; newnames[n]; n++)
417 names[n] = newnames[n];
418 names[n] = (char *)NULL;
423 ignore_glob_matches (names)
426 if (globignore.num_ignores == 0)
429 ignore_globbed_names (names, glob_name_is_acceptable);
433 split_ignorespec (s, ip)
447 n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
448 t = substring (s, i, n);
457 setup_ignore_patterns (ivp)
458 struct ignorevar *ivp;
460 int numitems, maxitems, ptr;
461 char *colon_bit, *this_ignoreval;
464 this_ignoreval = get_string_value (ivp->varname);
466 /* If nothing has changed then just exit now. */
467 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
468 (!this_ignoreval && !ivp->last_ignoreval))
471 /* Oops. The ignore variable has changed. Re-parse it. */
472 ivp->num_ignores = 0;
476 for (p = ivp->ignores; p->val; p++)
479 ivp->ignores = (struct ign *)NULL;
482 if (ivp->last_ignoreval)
484 free (ivp->last_ignoreval);
485 ivp->last_ignoreval = (char *)NULL;
488 if (this_ignoreval == 0 || *this_ignoreval == '\0')
491 ivp->last_ignoreval = savestring (this_ignoreval);
493 numitems = maxitems = ptr = 0;
496 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
498 while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
501 if (numitems + 1 >= maxitems)
504 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
506 ivp->ignores[numitems].val = colon_bit;
507 ivp->ignores[numitems].len = strlen (colon_bit);
508 ivp->ignores[numitems].flags = 0;
510 (*ivp->item_func) (&ivp->ignores[numitems]);
513 ivp->ignores[numitems].val = (char *)NULL;
514 ivp->num_ignores = numitems;