blob: 42f21e4c86edbb0d977ee75f941b5fd654bda4e0 [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* pathexp.c -- The shell interface to the globbing library. */
2
Jari Aalto31859422009-01-12 13:36:28 +00003/* Copyright (C) 1995-2009 Free Software Foundation, Inc.
Jari Aaltoccc6cda1996-12-23 17:02:34 +00004
5 This file is part of GNU Bash, the Bourne Again SHell.
6
Jari Aalto31859422009-01-12 13:36:28 +00007 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.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 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.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000016
Jari Aalto31859422009-01-12 13:36:28 +000017 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*/
Jari Aaltoccc6cda1996-12-23 17:02:34 +000020
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
Jari Aalto7117c2d2002-07-17 14:10:11 +000036#include "shmbutil.h"
Jari Aalto31859422009-01-12 13:36:28 +000037#include "bashintl.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000038
Jari Aaltof73dda02001-11-13 17:56:06 +000039#include <glob/strmatch.h>
Jari Aaltob72432f1999-02-19 17:11:39 +000040
Jari Aalto7117c2d2002-07-17 14:10:11 +000041static int glob_name_is_acceptable __P((const char *));
42static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
Chet Ramey495aee42011-11-22 19:11:26 -050043static char *split_ignorespec __P((char *, int *));
Jari Aalto7117c2d2002-07-17 14:10:11 +000044
Jari Aaltob72432f1999-02-19 17:11:39 +000045#if defined (USE_POSIX_GLOB_LIBRARY)
46# include <glob.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000047typedef int posix_glob_errfunc_t __P((const char *, int));
Jari Aaltob72432f1999-02-19 17:11:39 +000048#else
49# include <glob/glob.h>
50#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000051
52/* Control whether * matches .files in globbing. */
53int glob_dot_filenames;
54
Jari Aaltocce855b1998-04-17 19:52:44 +000055/* Control whether the extended globbing features are enabled. */
Chet Ramey00018032011-11-21 20:51:19 -050056int extended_glob = EXTGLOB_DEFAULT;
Jari Aaltocce855b1998-04-17 19:52:44 +000057
Jari Aalto31859422009-01-12 13:36:28 +000058/* Control enabling special handling of `**' */
59int glob_star = 0;
60
Jari Aaltoccc6cda1996-12-23 17:02:34 +000061/* 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;
Jari Aalto7117c2d2002-07-17 14:10:11 +000067 char *send;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000068 int open;
69
Jari Aalto7117c2d2002-07-17 14:10:11 +000070 DECLARE_MBSTATE;
71
Jari Aaltoccc6cda1996-12-23 17:02:34 +000072 open = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +000073 send = string + strlen (string);
74
Jari Aaltoccc6cda1996-12-23 17:02:34 +000075 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
Jari Aaltocce855b1998-04-17 19:52:44 +000092 case '+':
93 case '@':
94 case '!':
95 if (*string == '(') /*)*/
96 return (1);
97 continue;
98
Jari Aaltoccc6cda1996-12-23 17:02:34 +000099 case CTLESC:
100 case '\\':
101 if (*string++ == '\0')
102 return (0);
103 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000104
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
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000114 }
115 return (0);
116}
117
Jari Aaltof1be6662008-11-18 13:15:12 +0000118/* 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
Jari Aalto31859422009-01-12 13:36:28 +0000145int
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 '!':
160 if (s[1] == '(') /*(*/
161 return 1;
162 break;
163 }
164 return 0;
165}
166
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000167/* PATHNAME can contain characters prefixed by CTLESC; this indicates
168 that the character is to be quoted. We quote it here in the style
Jari Aaltocce855b1998-04-17 19:52:44 +0000169 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000170 we change quoted null strings (pathname[0] == CTLNUL) into empty
171 strings (pathname[0] == 0). If this is called after quote removal
Jari Aaltocce855b1998-04-17 19:52:44 +0000172 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000173 removal has not been done (for example, before attempting to match a
Jari Aaltocce855b1998-04-17 19:52:44 +0000174 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. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000177char *
Jari Aaltocce855b1998-04-17 19:52:44 +0000178quote_string_for_globbing (pathname, qflags)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000179 const char *pathname;
Jari Aaltocce855b1998-04-17 19:52:44 +0000180 int qflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000181{
182 char *temp;
Jari Aaltocce855b1998-04-17 19:52:44 +0000183 register int i, j;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000184
Jari Aaltof73dda02001-11-13 17:56:06 +0000185 temp = (char *)xmalloc (strlen (pathname) + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000186
Jari Aaltocce855b1998-04-17 19:52:44 +0000187 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000188 {
189 temp[0] = '\0';
190 return temp;
191 }
192
Jari Aaltocce855b1998-04-17 19:52:44 +0000193 for (i = j = 0; pathname[i]; i++)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000194 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000195 if (pathname[i] == CTLESC)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000196 {
197 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
198 continue;
Jari Aaltof1be6662008-11-18 13:15:12 +0000199 if ((qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
200 continue;
Jari Aaltocce855b1998-04-17 19:52:44 +0000201 temp[j++] = '\\';
Jari Aalto7117c2d2002-07-17 14:10:11 +0000202 i++;
203 if (pathname[i] == '\0')
204 break;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000205 }
Jari Aalto31859422009-01-12 13:36:28 +0000206 else if (pathname[i] == '\\')
207 {
208 temp[j++] = '\\';
209 i++;
210 if (pathname[i] == '\0')
211 break;
212 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000213 temp[j++] = pathname[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000214 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000215 temp[j] = '\0';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000216
217 return (temp);
218}
219
220char *
221quote_globbing_chars (string)
222 char *string;
223{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000224 size_t slen;
225 char *temp, *s, *t, *send;
226 DECLARE_MBSTATE;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000227
Jari Aalto7117c2d2002-07-17 14:10:11 +0000228 slen = strlen (string);
229 send = string + slen;
230
231 temp = (char *)xmalloc (slen * 2 + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000232 for (t = temp, s = string; *s; )
233 {
Jari Aalto31859422009-01-12 13:36:28 +0000234 if (glob_char_p (s))
235 *t++ = '\\';
Jari Aalto7117c2d2002-07-17 14:10:11 +0000236
237 /* Copy a single (possibly multibyte) character from s to t,
238 incrementing both. */
239 COPY_CHAR_P (t, s, send);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000240 }
241 *t = '\0';
242 return temp;
243}
244
245/* Call the glob library to do globbing on PATHNAME. */
246char **
247shell_glob_filename (pathname)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000248 const char *pathname;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000249{
250#if defined (USE_POSIX_GLOB_LIBRARY)
251 register int i;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000252 char *temp, **results;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000253 glob_t filenames;
254 int glob_flags;
255
Jari Aaltocce855b1998-04-17 19:52:44 +0000256 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000257
258 filenames.gl_offs = 0;
259
Jari Aaltob72432f1999-02-19 17:11:39 +0000260# if defined (GLOB_PERIOD)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000261 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
Jari Aaltob72432f1999-02-19 17:11:39 +0000262# else
263 glob_flags = 0;
264# endif /* !GLOB_PERIOD */
265
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000266 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
267
Jari Aaltof73dda02001-11-13 17:56:06 +0000268 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000269
270 free (temp);
271
Jari Aalto28ef6c32001-04-06 19:14:31 +0000272 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000273 return ((char **)NULL);
Jari Aaltob72432f1999-02-19 17:11:39 +0000274 else if (i == GLOB_NOMATCH)
275 filenames.gl_pathv = (char **)NULL;
276 else if (i != 0) /* other error codes not in POSIX.2 */
Jari Aaltocce855b1998-04-17 19:52:44 +0000277 filenames.gl_pathv = (char **)NULL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000278
Jari Aaltobb706242000-03-17 21:46:59 +0000279 results = filenames.gl_pathv;
280
281 if (results && ((GLOB_FAILED (results)) == 0))
282 {
283 if (should_ignore_glob_matches ())
284 ignore_glob_matches (results);
285 if (results && results[0])
Jari Aalto7117c2d2002-07-17 14:10:11 +0000286 strvec_sort (results);
Jari Aaltobb706242000-03-17 21:46:59 +0000287 else
288 {
289 FREE (results);
290 results = (char **)NULL;
291 }
292 }
293
294 return (results);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000295
296#else /* !USE_POSIX_GLOB_LIBRARY */
297
298 char *temp, **results;
299
300 noglob_dot_filenames = glob_dot_filenames == 0;
301
Jari Aaltocce855b1998-04-17 19:52:44 +0000302 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
Jari Aalto31859422009-01-12 13:36:28 +0000303 results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000304 free (temp);
305
306 if (results && ((GLOB_FAILED (results)) == 0))
307 {
308 if (should_ignore_glob_matches ())
309 ignore_glob_matches (results);
310 if (results && results[0])
Jari Aalto7117c2d2002-07-17 14:10:11 +0000311 strvec_sort (results);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000312 else
313 {
314 FREE (results);
315 results = (char **)&glob_error_return;
316 }
317 }
318
319 return (results);
320#endif /* !USE_POSIX_GLOB_LIBRARY */
321}
322
323/* Stuff for GLOBIGNORE. */
324
325static struct ignorevar globignore =
326{
327 "GLOBIGNORE",
328 (struct ign *)0,
329 0,
330 (char *)0,
Jari Aaltof73dda02001-11-13 17:56:06 +0000331 (sh_iv_item_func_t *)0,
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000332};
333
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 `.'. */
337void
338setup_glob_ignore (name)
339 char *name;
340{
341 char *v;
342
343 v = get_string_value (name);
344 setup_ignore_patterns (&globignore);
345
346 if (globignore.num_ignores)
347 glob_dot_filenames = 1;
348 else if (v == 0)
349 glob_dot_filenames = 0;
350}
351
352int
353should_ignore_glob_matches ()
354{
355 return globignore.num_ignores;
356}
357
358/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
359static int
360glob_name_is_acceptable (name)
Jari Aaltof73dda02001-11-13 17:56:06 +0000361 const char *name;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000362{
363 struct ign *p;
Jari Aaltocce855b1998-04-17 19:52:44 +0000364 int flags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000365
366 /* . and .. are never matched */
367 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
368 return (0);
369
Jari Aaltocce855b1998-04-17 19:52:44 +0000370 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000371 for (p = globignore.ignores; p->val; p++)
372 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000373 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000374 return (0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000375 }
376 return (1);
377}
378
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. */
384
385static void
386ignore_globbed_names (names, name_func)
387 char **names;
Jari Aaltof73dda02001-11-13 17:56:06 +0000388 sh_ignore_func_t *name_func;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000389{
390 char **newnames;
391 int n, i;
392
393 for (i = 0; names[i]; i++)
394 ;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000395 newnames = strvec_create (i + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000396
397 for (n = i = 0; names[i]; i++)
398 {
399 if ((*name_func) (names[i]))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000400 newnames[n++] = names[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000401 else
402 free (names[i]);
403 }
404
405 newnames[n] = (char *)NULL;
406
407 if (n == 0)
408 {
409 names[0] = (char *)NULL;
410 free (newnames);
411 return;
412 }
413
414 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
415 new array end. */
416 for (n = 0; newnames[n]; n++)
417 names[n] = newnames[n];
418 names[n] = (char *)NULL;
Jari Aaltod166f041997-06-05 14:59:13 +0000419 free (newnames);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000420}
421
422void
423ignore_glob_matches (names)
424 char **names;
425{
426 if (globignore.num_ignores == 0)
427 return;
428
429 ignore_globbed_names (names, glob_name_is_acceptable);
430}
431
Chet Ramey495aee42011-11-22 19:11:26 -0500432static char *
433split_ignorespec (s, ip)
434 char *s;
435 int *ip;
436{
437 char *t;
438 int n, i;
439
440 if (s == 0)
441 return 0;
442
443 i = *ip;
444 if (s[i] == 0)
445 return 0;
446
447 n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
448 t = substring (s, i, n);
449
450 if (s[n] == ':')
451 n++;
452 *ip = n;
453 return t;
454}
455
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000456void
457setup_ignore_patterns (ivp)
458 struct ignorevar *ivp;
459{
460 int numitems, maxitems, ptr;
461 char *colon_bit, *this_ignoreval;
462 struct ign *p;
463
464 this_ignoreval = get_string_value (ivp->varname);
465
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))
469 return;
470
471 /* Oops. The ignore variable has changed. Re-parse it. */
472 ivp->num_ignores = 0;
473
474 if (ivp->ignores)
475 {
476 for (p = ivp->ignores; p->val; p++)
477 free(p->val);
478 free (ivp->ignores);
479 ivp->ignores = (struct ign *)NULL;
480 }
481
482 if (ivp->last_ignoreval)
483 {
484 free (ivp->last_ignoreval);
485 ivp->last_ignoreval = (char *)NULL;
486 }
487
488 if (this_ignoreval == 0 || *this_ignoreval == '\0')
489 return;
490
491 ivp->last_ignoreval = savestring (this_ignoreval);
492
493 numitems = maxitems = ptr = 0;
494
Chet Ramey495aee42011-11-22 19:11:26 -0500495#if 0
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000496 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
Chet Ramey495aee42011-11-22 19:11:26 -0500497#else
498 while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
499#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000500 {
501 if (numitems + 1 >= maxitems)
502 {
503 maxitems += 10;
504 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
505 }
506 ivp->ignores[numitems].val = colon_bit;
507 ivp->ignores[numitems].len = strlen (colon_bit);
508 ivp->ignores[numitems].flags = 0;
509 if (ivp->item_func)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000510 (*ivp->item_func) (&ivp->ignores[numitems]);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000511 numitems++;
512 }
513 ivp->ignores[numitems].val = (char *)NULL;
514 ivp->num_ignores = numitems;
515}