1 /* pathexp.c -- The shell interface to the globbing library. */
3 /* Copyright (C) 1995-2014 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. QGLOB_REGEXP means we're
177 quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires
178 some special handling. */
180 quote_string_for_globbing (pathname, qflags)
181 const char *pathname;
186 int brack, cclass, collsym, equiv, c, last_was_backslash;
188 temp = (char *)xmalloc (2 * strlen (pathname) + 1);
190 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
196 brack = cclass = collsym = equiv = last_was_backslash = 0;
197 for (i = j = 0; pathname[i]; i++)
199 /* Fix for CTLESC at the end of the string? */
200 if (pathname[i] == CTLESC && pathname[i+1] == '\0')
202 temp[j++] = pathname[i++];
205 /* If we are parsing regexp, turn CTLESC CTLESC into CTLESC. It's not an
206 ERE special character, so we should just be able to pass it through. */
207 else if ((qflags & QGLOB_REGEXP) && pathname[i] == CTLESC && pathname[i+1] == CTLESC)
210 temp[j++] = pathname[i];
213 else if (pathname[i] == CTLESC)
215 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
217 /* What to do if preceding char is backslash? */
218 if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
222 if (pathname[i] == '\0')
225 else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/
228 temp[j++] = pathname[i++]; /* open bracket */
229 c = pathname[i++]; /* c == char after open bracket */
234 else if (c == CTLESC)
236 /* skip c, check for EOS, let assignment at end of loop */
237 /* pathname[i] == backslash-escaped character */
238 if (pathname[i] == 0)
240 temp[j++] = pathname[i++];
242 else if (c == '[' && pathname[i] == ':')
245 temp[j++] = pathname[i++];
248 else if (cclass && c == ':' && pathname[i] == ']')
251 temp[j++] = pathname[i++];
254 else if (c == '[' && pathname[i] == '=')
257 temp[j++] = pathname[i++];
258 if (pathname[i] == ']')
259 temp[j++] = pathname[i++]; /* right brack can be in equiv */
262 else if (equiv && c == '=' && pathname[i] == ']')
265 temp[j++] = pathname[i++];
268 else if (c == '[' && pathname[i] == '.')
271 temp[j++] = pathname[i++];
272 if (pathname[i] == ']')
273 temp[j++] = pathname[i++]; /* right brack can be in collsym */
276 else if (collsym && c == '.' && pathname[i] == ']')
279 temp[j++] = pathname[i++];
285 while ((c = pathname[i++]) != ']');
286 temp[j++] = c; /* closing right bracket */
287 i--; /* increment will happen above in loop */
288 continue; /* skip double assignment below */
290 else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0)
292 /* XXX - if not quoting regexp, use backslash as quote char. Should
293 we just pass it through without treating it as special? That is
294 what ksh93 seems to do. */
296 /* If we want to pass through backslash unaltered, comment out these
301 if (pathname[i] == '\0')
304 else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP))
305 last_was_backslash = 1;
306 temp[j++] = pathname[i];
315 quote_globbing_chars (string)
319 char *temp, *s, *t, *send;
322 slen = strlen (string);
323 send = string + slen;
325 temp = (char *)xmalloc (slen * 2 + 1);
326 for (t = temp, s = string; *s; )
331 /* Copy a single (possibly multibyte) character from s to t,
332 incrementing both. */
333 COPY_CHAR_P (t, s, send);
339 /* Call the glob library to do globbing on PATHNAME. */
341 shell_glob_filename (pathname)
342 const char *pathname;
344 #if defined (USE_POSIX_GLOB_LIBRARY)
346 char *temp, **results;
350 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
352 filenames.gl_offs = 0;
354 # if defined (GLOB_PERIOD)
355 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
358 # endif /* !GLOB_PERIOD */
360 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
362 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
366 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
367 return ((char **)NULL);
368 else if (i == GLOB_NOMATCH)
369 filenames.gl_pathv = (char **)NULL;
370 else if (i != 0) /* other error codes not in POSIX.2 */
371 filenames.gl_pathv = (char **)NULL;
373 results = filenames.gl_pathv;
375 if (results && ((GLOB_FAILED (results)) == 0))
377 if (should_ignore_glob_matches ())
378 ignore_glob_matches (results);
379 if (results && results[0])
380 strvec_sort (results);
384 results = (char **)NULL;
390 #else /* !USE_POSIX_GLOB_LIBRARY */
392 char *temp, **results;
394 noglob_dot_filenames = glob_dot_filenames == 0;
396 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
397 results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
400 if (results && ((GLOB_FAILED (results)) == 0))
402 if (should_ignore_glob_matches ())
403 ignore_glob_matches (results);
404 if (results && results[0])
405 strvec_sort (results);
409 results = (char **)&glob_error_return;
414 #endif /* !USE_POSIX_GLOB_LIBRARY */
417 /* Stuff for GLOBIGNORE. */
419 static struct ignorevar globignore =
425 (sh_iv_item_func_t *)0,
428 /* Set up to ignore some glob matches because the value of GLOBIGNORE
429 has changed. If GLOBIGNORE is being unset, we also need to disable
430 the globbing of filenames beginning with a `.'. */
432 setup_glob_ignore (name)
437 v = get_string_value (name);
438 setup_ignore_patterns (&globignore);
440 if (globignore.num_ignores)
441 glob_dot_filenames = 1;
443 glob_dot_filenames = 0;
447 should_ignore_glob_matches ()
449 return globignore.num_ignores;
452 /* Return 0 if NAME matches a pattern in the globignore.ignores list. */
454 glob_name_is_acceptable (name)
460 /* . and .. are never matched */
461 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
464 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
465 for (p = globignore.ignores; p->val; p++)
467 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
473 /* Internal function to test whether filenames in NAMES should be
474 ignored. NAME_FUNC is a pointer to a function to call with each
475 name. It returns non-zero if the name is acceptable to the particular
476 ignore function which called _ignore_names; zero if the name should
477 be removed from NAMES. */
480 ignore_globbed_names (names, name_func)
482 sh_ignore_func_t *name_func;
487 for (i = 0; names[i]; i++)
489 newnames = strvec_create (i + 1);
491 for (n = i = 0; names[i]; i++)
493 if ((*name_func) (names[i]))
494 newnames[n++] = names[i];
499 newnames[n] = (char *)NULL;
503 names[0] = (char *)NULL;
508 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
510 for (n = 0; newnames[n]; n++)
511 names[n] = newnames[n];
512 names[n] = (char *)NULL;
517 ignore_glob_matches (names)
520 if (globignore.num_ignores == 0)
523 ignore_globbed_names (names, glob_name_is_acceptable);
527 split_ignorespec (s, ip)
541 n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
542 t = substring (s, i, n);
551 setup_ignore_patterns (ivp)
552 struct ignorevar *ivp;
554 int numitems, maxitems, ptr;
555 char *colon_bit, *this_ignoreval;
558 this_ignoreval = get_string_value (ivp->varname);
560 /* If nothing has changed then just exit now. */
561 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
562 (!this_ignoreval && !ivp->last_ignoreval))
565 /* Oops. The ignore variable has changed. Re-parse it. */
566 ivp->num_ignores = 0;
570 for (p = ivp->ignores; p->val; p++)
573 ivp->ignores = (struct ign *)NULL;
576 if (ivp->last_ignoreval)
578 free (ivp->last_ignoreval);
579 ivp->last_ignoreval = (char *)NULL;
582 if (this_ignoreval == 0 || *this_ignoreval == '\0')
585 ivp->last_ignoreval = savestring (this_ignoreval);
587 numitems = maxitems = ptr = 0;
590 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
592 while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
595 if (numitems + 1 >= maxitems)
598 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
600 ivp->ignores[numitems].val = colon_bit;
601 ivp->ignores[numitems].len = strlen (colon_bit);
602 ivp->ignores[numitems].flags = 0;
604 (*ivp->item_func) (&ivp->ignores[numitems]);
607 ivp->ignores[numitems].val = (char *)NULL;
608 ivp->num_ignores = numitems;