]> git.ipfire.org Git - thirdparty/bash.git/blame - pathexp.c
Bash-4.3 patch 32
[thirdparty/bash.git] / pathexp.c
CommitLineData
ccc6cda3
JA
1/* pathexp.c -- The shell interface to the globbing library. */
2
ac50fbac 3/* Copyright (C) 1995-2014 Free Software Foundation, Inc.
ccc6cda3
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
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.
ccc6cda3 11
3185942a
JA
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.
ccc6cda3 16
3185942a
JA
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*/
ccc6cda3
JA
20
21#include "config.h"
22
23#include "bashtypes.h"
24#include <stdio.h>
25
26#if defined (HAVE_UNISTD_H)
27# include <unistd.h>
28#endif
29
30#include "bashansi.h"
31
32#include "shell.h"
33#include "pathexp.h"
34#include "flags.h"
35
7117c2d2 36#include "shmbutil.h"
3185942a 37#include "bashintl.h"
7117c2d2 38
f73dda09 39#include <glob/strmatch.h>
b72432fd 40
7117c2d2
JA
41static int glob_name_is_acceptable __P((const char *));
42static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
495aee44 43static char *split_ignorespec __P((char *, int *));
ac50fbac 44
b72432fd
JA
45#if defined (USE_POSIX_GLOB_LIBRARY)
46# include <glob.h>
f73dda09 47typedef int posix_glob_errfunc_t __P((const char *, int));
b72432fd
JA
48#else
49# include <glob/glob.h>
50#endif
ccc6cda3
JA
51
52/* Control whether * matches .files in globbing. */
53int glob_dot_filenames;
54
cce855bc 55/* Control whether the extended globbing features are enabled. */
0001803f 56int extended_glob = EXTGLOB_DEFAULT;
cce855bc 57
3185942a
JA
58/* Control enabling special handling of `**' */
59int glob_star = 0;
60
ccc6cda3
JA
61/* Return nonzero if STRING has any unquoted special globbing chars in it. */
62int
63unquoted_glob_pattern_p (string)
64 register char *string;
65{
66 register int c;
7117c2d2 67 char *send;
ccc6cda3
JA
68 int open;
69
7117c2d2
JA
70 DECLARE_MBSTATE;
71
ccc6cda3 72 open = 0;
7117c2d2
JA
73 send = string + strlen (string);
74
ccc6cda3
JA
75 while (c = *string++)
76 {
77 switch (c)
78 {
79 case '?':
80 case '*':
81 return (1);
82
83 case '[':
84 open++;
85 continue;
86
87 case ']':
88 if (open)
89 return (1);
90 continue;
91
cce855bc
JA
92 case '+':
93 case '@':
94 case '!':
95 if (*string == '(') /*)*/
96 return (1);
97 continue;
98
ccc6cda3
JA
99 case CTLESC:
100 case '\\':
101 if (*string++ == '\0')
102 return (0);
103 }
7117c2d2
JA
104
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
108 string--;
109 ADVANCE_CHAR_P (string, send - string);
110 string++;
111#else
112 ADVANCE_CHAR_P (string, send - string);
113#endif
ccc6cda3
JA
114 }
115 return (0);
116}
117
f1be666c
JA
118/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
119 be quoted to match itself. */
120static inline int
121ere_char (c)
122 int c;
123{
124 switch (c)
125 {
126 case '.':
127 case '[':
128 case '\\':
129 case '(':
130 case ')':
131 case '*':
132 case '+':
133 case '?':
134 case '{':
135 case '|':
136 case '^':
137 case '$':
138 return 1;
139 default:
140 return 0;
141 }
142 return (0);
143}
144
3185942a
JA
145int
146glob_char_p (s)
147 const char *s;
148{
149 switch (*s)
150 {
151 case '*':
152 case '[':
153 case ']':
154 case '?':
155 case '\\':
156 return 1;
157 case '+':
158 case '@':
159 case '!':
ac50fbac 160 if (s[1] == '(') /*(*/
3185942a
JA
161 return 1;
162 break;
163 }
164 return 0;
165}
166
ccc6cda3
JA
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
cce855bc 169 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
ccc6cda3
JA
170 we change quoted null strings (pathname[0] == CTLNUL) into empty
171 strings (pathname[0] == 0). If this is called after quote removal
cce855bc 172 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
ccc6cda3 173 removal has not been done (for example, before attempting to match a
cce855bc
JA
174 pattern while executing a case statement), flags should include
175 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
ac50fbac
CR
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. */
ccc6cda3 179char *
cce855bc 180quote_string_for_globbing (pathname, qflags)
28ef6c31 181 const char *pathname;
cce855bc 182 int qflags;
ccc6cda3
JA
183{
184 char *temp;
cce855bc 185 register int i, j;
ac50fbac 186 int brack, cclass, collsym, equiv, c, last_was_backslash;
ccc6cda3 187
ac50fbac 188 temp = (char *)xmalloc (2 * strlen (pathname) + 1);
ccc6cda3 189
cce855bc 190 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
ccc6cda3
JA
191 {
192 temp[0] = '\0';
193 return temp;
194 }
195
ac50fbac 196 brack = cclass = collsym = equiv = last_was_backslash = 0;
cce855bc 197 for (i = j = 0; pathname[i]; i++)
ccc6cda3 198 {
ac50fbac
CR
199 /* Fix for CTLESC at the end of the string? */
200 if (pathname[i] == CTLESC && pathname[i+1] == '\0')
201 {
202 temp[j++] = pathname[i++];
203 break;
204 }
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)
208 {
209 i++;
210 temp[j++] = pathname[i];
211 continue;
212 }
213 else if (pathname[i] == CTLESC)
28ef6c31
JA
214 {
215 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
216 continue;
ac50fbac 217 /* What to do if preceding char is backslash? */
25db9a70 218 if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
f1be666c 219 continue;
cce855bc 220 temp[j++] = '\\';
7117c2d2
JA
221 i++;
222 if (pathname[i] == '\0')
223 break;
28ef6c31 224 }
ac50fbac
CR
225 else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/
226 {
227 brack = 1;
228 temp[j++] = pathname[i++]; /* open bracket */
229 c = pathname[i++]; /* c == char after open bracket */
230 do
231 {
232 if (c == 0)
233 goto endpat;
234 else if (c == CTLESC)
235 {
236 /* skip c, check for EOS, let assignment at end of loop */
237 /* pathname[i] == backslash-escaped character */
238 if (pathname[i] == 0)
239 goto endpat;
240 temp[j++] = pathname[i++];
241 }
242 else if (c == '[' && pathname[i] == ':')
243 {
244 temp[j++] = c;
245 temp[j++] = pathname[i++];
246 cclass = 1;
247 }
248 else if (cclass && c == ':' && pathname[i] == ']')
249 {
250 temp[j++] = c;
251 temp[j++] = pathname[i++];
252 cclass = 0;
253 }
254 else if (c == '[' && pathname[i] == '=')
255 {
256 temp[j++] = c;
257 temp[j++] = pathname[i++];
258 if (pathname[i] == ']')
259 temp[j++] = pathname[i++]; /* right brack can be in equiv */
260 equiv = 1;
261 }
262 else if (equiv && c == '=' && pathname[i] == ']')
263 {
264 temp[j++] = c;
265 temp[j++] = pathname[i++];
266 equiv = 0;
267 }
268 else if (c == '[' && pathname[i] == '.')
269 {
270 temp[j++] = c;
271 temp[j++] = pathname[i++];
272 if (pathname[i] == ']')
273 temp[j++] = pathname[i++]; /* right brack can be in collsym */
274 collsym = 1;
275 }
276 else if (collsym && c == '.' && pathname[i] == ']')
277 {
278 temp[j++] = c;
279 temp[j++] = pathname[i++];
280 collsym = 0;
281 }
282 else
283 temp[j++] = c;
284 }
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 */
289 }
290 else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0)
3185942a 291 {
ac50fbac
CR
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. */
295
296 /* If we want to pass through backslash unaltered, comment out these
297 lines. */
3185942a 298 temp[j++] = '\\';
ac50fbac 299
3185942a
JA
300 i++;
301 if (pathname[i] == '\0')
302 break;
303 }
ac50fbac
CR
304 else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP))
305 last_was_backslash = 1;
7117c2d2 306 temp[j++] = pathname[i];
ccc6cda3 307 }
ac50fbac 308endpat:
cce855bc 309 temp[j] = '\0';
ccc6cda3
JA
310
311 return (temp);
312}
313
314char *
315quote_globbing_chars (string)
316 char *string;
317{
7117c2d2
JA
318 size_t slen;
319 char *temp, *s, *t, *send;
320 DECLARE_MBSTATE;
321
322 slen = strlen (string);
323 send = string + slen;
ccc6cda3 324
7117c2d2 325 temp = (char *)xmalloc (slen * 2 + 1);
ccc6cda3
JA
326 for (t = temp, s = string; *s; )
327 {
3185942a
JA
328 if (glob_char_p (s))
329 *t++ = '\\';
7117c2d2
JA
330
331 /* Copy a single (possibly multibyte) character from s to t,
ac50fbac 332 incrementing both. */
7117c2d2 333 COPY_CHAR_P (t, s, send);
ccc6cda3
JA
334 }
335 *t = '\0';
336 return temp;
337}
338
339/* Call the glob library to do globbing on PATHNAME. */
340char **
341shell_glob_filename (pathname)
28ef6c31 342 const char *pathname;
ccc6cda3
JA
343{
344#if defined (USE_POSIX_GLOB_LIBRARY)
345 register int i;
28ef6c31 346 char *temp, **results;
ccc6cda3
JA
347 glob_t filenames;
348 int glob_flags;
349
cce855bc 350 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
ccc6cda3
JA
351
352 filenames.gl_offs = 0;
353
b72432fd 354# if defined (GLOB_PERIOD)
ccc6cda3 355 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
b72432fd
JA
356# else
357 glob_flags = 0;
358# endif /* !GLOB_PERIOD */
359
ccc6cda3
JA
360 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
361
f73dda09 362 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
ccc6cda3
JA
363
364 free (temp);
365
28ef6c31 366 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
ccc6cda3 367 return ((char **)NULL);
b72432fd
JA
368 else if (i == GLOB_NOMATCH)
369 filenames.gl_pathv = (char **)NULL;
370 else if (i != 0) /* other error codes not in POSIX.2 */
cce855bc 371 filenames.gl_pathv = (char **)NULL;
ccc6cda3 372
bb70624e
JA
373 results = filenames.gl_pathv;
374
375 if (results && ((GLOB_FAILED (results)) == 0))
376 {
377 if (should_ignore_glob_matches ())
378 ignore_glob_matches (results);
379 if (results && results[0])
7117c2d2 380 strvec_sort (results);
bb70624e
JA
381 else
382 {
383 FREE (results);
384 results = (char **)NULL;
385 }
386 }
387
388 return (results);
ccc6cda3
JA
389
390#else /* !USE_POSIX_GLOB_LIBRARY */
391
392 char *temp, **results;
393
394 noglob_dot_filenames = glob_dot_filenames == 0;
395
cce855bc 396 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
3185942a 397 results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
ccc6cda3
JA
398 free (temp);
399
400 if (results && ((GLOB_FAILED (results)) == 0))
401 {
402 if (should_ignore_glob_matches ())
403 ignore_glob_matches (results);
404 if (results && results[0])
7117c2d2 405 strvec_sort (results);
ccc6cda3
JA
406 else
407 {
408 FREE (results);
409 results = (char **)&glob_error_return;
410 }
411 }
412
413 return (results);
414#endif /* !USE_POSIX_GLOB_LIBRARY */
415}
416
417/* Stuff for GLOBIGNORE. */
418
419static struct ignorevar globignore =
420{
421 "GLOBIGNORE",
422 (struct ign *)0,
423 0,
424 (char *)0,
f73dda09 425 (sh_iv_item_func_t *)0,
ccc6cda3
JA
426};
427
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 `.'. */
431void
432setup_glob_ignore (name)
433 char *name;
434{
435 char *v;
436
437 v = get_string_value (name);
438 setup_ignore_patterns (&globignore);
439
440 if (globignore.num_ignores)
441 glob_dot_filenames = 1;
442 else if (v == 0)
443 glob_dot_filenames = 0;
444}
445
446int
447should_ignore_glob_matches ()
448{
449 return globignore.num_ignores;
450}
451
452/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
453static int
454glob_name_is_acceptable (name)
f73dda09 455 const char *name;
ccc6cda3
JA
456{
457 struct ign *p;
cce855bc 458 int flags;
ccc6cda3
JA
459
460 /* . and .. are never matched */
461 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
462 return (0);
463
cce855bc 464 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
ccc6cda3
JA
465 for (p = globignore.ignores; p->val; p++)
466 {
f73dda09 467 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
28ef6c31 468 return (0);
ccc6cda3
JA
469 }
470 return (1);
471}
472
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. */
478
479static void
480ignore_globbed_names (names, name_func)
481 char **names;
f73dda09 482 sh_ignore_func_t *name_func;
ccc6cda3
JA
483{
484 char **newnames;
485 int n, i;
486
487 for (i = 0; names[i]; i++)
488 ;
7117c2d2 489 newnames = strvec_create (i + 1);
ccc6cda3
JA
490
491 for (n = i = 0; names[i]; i++)
492 {
493 if ((*name_func) (names[i]))
28ef6c31 494 newnames[n++] = names[i];
ccc6cda3
JA
495 else
496 free (names[i]);
497 }
498
499 newnames[n] = (char *)NULL;
500
501 if (n == 0)
502 {
503 names[0] = (char *)NULL;
504 free (newnames);
505 return;
506 }
507
508 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
509 new array end. */
510 for (n = 0; newnames[n]; n++)
511 names[n] = newnames[n];
512 names[n] = (char *)NULL;
d166f048 513 free (newnames);
ccc6cda3
JA
514}
515
516void
517ignore_glob_matches (names)
518 char **names;
519{
520 if (globignore.num_ignores == 0)
521 return;
522
523 ignore_globbed_names (names, glob_name_is_acceptable);
524}
525
495aee44
CR
526static char *
527split_ignorespec (s, ip)
528 char *s;
529 int *ip;
530{
531 char *t;
532 int n, i;
533
534 if (s == 0)
535 return 0;
536
537 i = *ip;
538 if (s[i] == 0)
539 return 0;
540
541 n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
542 t = substring (s, i, n);
543
544 if (s[n] == ':')
545 n++;
546 *ip = n;
547 return t;
548}
549
ccc6cda3
JA
550void
551setup_ignore_patterns (ivp)
552 struct ignorevar *ivp;
553{
554 int numitems, maxitems, ptr;
555 char *colon_bit, *this_ignoreval;
556 struct ign *p;
557
558 this_ignoreval = get_string_value (ivp->varname);
559
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))
563 return;
564
565 /* Oops. The ignore variable has changed. Re-parse it. */
566 ivp->num_ignores = 0;
567
568 if (ivp->ignores)
569 {
570 for (p = ivp->ignores; p->val; p++)
571 free(p->val);
572 free (ivp->ignores);
573 ivp->ignores = (struct ign *)NULL;
574 }
575
576 if (ivp->last_ignoreval)
577 {
578 free (ivp->last_ignoreval);
579 ivp->last_ignoreval = (char *)NULL;
580 }
581
582 if (this_ignoreval == 0 || *this_ignoreval == '\0')
583 return;
584
585 ivp->last_ignoreval = savestring (this_ignoreval);
586
587 numitems = maxitems = ptr = 0;
588
495aee44 589#if 0
ccc6cda3 590 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
495aee44
CR
591#else
592 while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
593#endif
ccc6cda3
JA
594 {
595 if (numitems + 1 >= maxitems)
596 {
597 maxitems += 10;
598 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
599 }
600 ivp->ignores[numitems].val = colon_bit;
601 ivp->ignores[numitems].len = strlen (colon_bit);
602 ivp->ignores[numitems].flags = 0;
603 if (ivp->item_func)
28ef6c31 604 (*ivp->item_func) (&ivp->ignores[numitems]);
ccc6cda3
JA
605 numitems++;
606 }
607 ivp->ignores[numitems].val = (char *)NULL;
608 ivp->num_ignores = numitems;
609}