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;
189
temp = (char *)xmalloc (2 * strlen (pathname) + 1);
191
if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
197
brack = cclass = collsym = equiv = last_was_backslash = 0;
198
for (i = j = 0; pathname[i]; i++)
200
/* Fix for CTLESC at the end of the string? */
201
if (pathname[i] == CTLESC && pathname[i+1] == '\0')
203
temp[j++] = pathname[i++];
206
/* If we are parsing regexp, turn CTLESC CTLESC into CTLESC. It's not an
207
ERE special character, so we should just be able to pass it through. */
208
else if ((qflags & QGLOB_REGEXP) && pathname[i] == CTLESC && pathname[i+1] == CTLESC)
211
temp[j++] = pathname[i];
214
else if (pathname[i] == CTLESC)
216
if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
218
/* What to do if preceding char is backslash? */
219
if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
223
if (pathname[i] == '\0')
226
else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/
229
temp[j++] = pathname[i++]; /* open bracket */
232
c = pathname[i++]; /* c == char after open bracket */
237
else if (c == CTLESC)
239
/* skip c, check for EOS, let assignment at end of loop */
240
/* pathname[i] == backslash-escaped character */
241
if (pathname[i] == 0)
243
temp[j++] = pathname[i++];
245
else if (c == '[' && pathname[i] == ':')
248
temp[j++] = pathname[i++];
251
else if (cclass && c == ':' && pathname[i] == ']')
254
temp[j++] = pathname[i++];
257
else if (c == '[' && pathname[i] == '=')
260
temp[j++] = pathname[i++];
261
if (pathname[i] == ']')
262
temp[j++] = pathname[i++]; /* right brack can be in equiv */
265
else if (equiv && c == '=' && pathname[i] == ']')
268
temp[j++] = pathname[i++];
271
else if (c == '[' && pathname[i] == '.')
274
temp[j++] = pathname[i++];
275
if (pathname[i] == ']')
276
temp[j++] = pathname[i++]; /* right brack can be in collsym */
279
else if (collsym && c == '.' && pathname[i] == ']')
282
temp[j++] = pathname[i++];
288
while (((c = pathname[i++]) != ']') && c != 0);
290
/* If we don't find the closing bracket before we hit the end of
291
the string, rescan string without treating it as a bracket
292
expression (has implications for backslash and special ERE
296
i = savei - 1; /* -1 for autoincrement above */
301
temp[j++] = c; /* closing right bracket */
302
i--; /* increment will happen above in loop */
303
continue; /* skip double assignment below */
305
else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0)
307
/* XXX - if not quoting regexp, use backslash as quote char. Should
308
we just pass it through without treating it as special? That is
309
what ksh93 seems to do. */
311
/* If we want to pass through backslash unaltered, comment out these
316
if (pathname[i] == '\0')
319
else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP))
320
last_was_backslash = 1;
321
temp[j++] = pathname[i];
330
quote_globbing_chars (string)
335
const char *s, *send;
338
slen = strlen (string);
339
send = string + slen;
341
temp = (char *)xmalloc (slen * 2 + 1);
342
for (t = temp, s = string; *s; )
347
/* Copy a single (possibly multibyte) character from s to t,
348
incrementing both. */
349
COPY_CHAR_P (t, s, send);
355
/* Call the glob library to do globbing on PATHNAME. */
357
shell_glob_filename (pathname)
358
const char *pathname;
360
#if defined (USE_POSIX_GLOB_LIBRARY)
362
char *temp, **results;
366
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
368
filenames.gl_offs = 0;
370
# if defined (GLOB_PERIOD)
371
glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
374
# endif /* !GLOB_PERIOD */
376
glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
378
i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
382
if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
383
return ((char **)NULL);
384
else if (i == GLOB_NOMATCH)
385
filenames.gl_pathv = (char **)NULL;
386
else if (i != 0) /* other error codes not in POSIX.2 */
387
filenames.gl_pathv = (char **)NULL;
389
results = filenames.gl_pathv;
391
if (results && ((GLOB_FAILED (results)) == 0))
393
if (should_ignore_glob_matches ())
394
ignore_glob_matches (results);
395
if (results && results[0])
396
strvec_sort (results);
400
results = (char **)NULL;
406
#else /* !USE_POSIX_GLOB_LIBRARY */
408
char *temp, **results;
410
noglob_dot_filenames = glob_dot_filenames == 0;
412
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
413
results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
416
if (results && ((GLOB_FAILED (results)) == 0))
418
if (should_ignore_glob_matches ())
419
ignore_glob_matches (results);
420
if (results && results[0])
421
strvec_sort (results);
425
results = (char **)&glob_error_return;
430
#endif /* !USE_POSIX_GLOB_LIBRARY */
433
/* Stuff for GLOBIGNORE. */
435
static struct ignorevar globignore =
441
(sh_iv_item_func_t *)0,
444
/* Set up to ignore some glob matches because the value of GLOBIGNORE
445
has changed. If GLOBIGNORE is being unset, we also need to disable
446
the globbing of filenames beginning with a `.'. */
448
setup_glob_ignore (name)
453
v = get_string_value (name);
454
setup_ignore_patterns (&globignore);
456
if (globignore.num_ignores)
457
glob_dot_filenames = 1;
459
glob_dot_filenames = 0;
463
should_ignore_glob_matches ()
465
return globignore.num_ignores;
468
/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
470
glob_name_is_acceptable (name)
476
/* . and .. are never matched */
477
if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
480
flags = FNM_PATHNAME | FNMATCH_EXTFLAG | FNMATCH_NOCASEGLOB;
481
for (p = globignore.ignores; p->val; p++)
483
if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
489
/* Internal function to test whether filenames in NAMES should be
490
ignored. NAME_FUNC is a pointer to a function to call with each
491
name. It returns non-zero if the name is acceptable to the particular
492
ignore function which called _ignore_names; zero if the name should
493
be removed from NAMES. */
496
ignore_globbed_names (names, name_func)
498
sh_ignore_func_t *name_func;
503
for (i = 0; names[i]; i++)
505
newnames = strvec_create (i + 1);
507
for (n = i = 0; names[i]; i++)
509
if ((*name_func) (names[i]))
510
newnames[n++] = names[i];
515
newnames[n] = (char *)NULL;
519
names[0] = (char *)NULL;
524
/* Copy the acceptable names from NEWNAMES back to NAMES and set the
526
for (n = 0; newnames[n]; n++)
527
names[n] = newnames[n];
528
names[n] = (char *)NULL;
533
ignore_glob_matches (names)
536
if (globignore.num_ignores == 0)
539
ignore_globbed_names (names, glob_name_is_acceptable);
543
split_ignorespec (s, ip)
557
n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB|SD_GLOB);
558
t = substring (s, i, n);
567
setup_ignore_patterns (ivp)
568
struct ignorevar *ivp;
570
int numitems, maxitems, ptr;
571
char *colon_bit, *this_ignoreval;
574
this_ignoreval = get_string_value (ivp->varname);
576
/* If nothing has changed then just exit now. */
577
if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
578
(!this_ignoreval && !ivp->last_ignoreval))
581
/* Oops. The ignore variable has changed. Re-parse it. */
582
ivp->num_ignores = 0;
586
for (p = ivp->ignores; p->val; p++)
589
ivp->ignores = (struct ign *)NULL;
592
if (ivp->last_ignoreval)
594
free (ivp->last_ignoreval);
595
ivp->last_ignoreval = (char *)NULL;
598
if (this_ignoreval == 0 || *this_ignoreval == '\0')
601
ivp->last_ignoreval = savestring (this_ignoreval);
603
numitems = maxitems = ptr = 0;
606
while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
608
while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
611
if (numitems + 1 >= maxitems)
614
ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
616
ivp->ignores[numitems].val = colon_bit;
617
ivp->ignores[numitems].len = strlen (colon_bit);
618
ivp->ignores[numitems].flags = 0;
620
(*ivp->item_func) (&ivp->ignores[numitems]);
623
ivp->ignores[numitems].val = (char *)NULL;
624
ivp->num_ignores = numitems;