blob: a498672f51ec668c266fb581a0a637b726b913c2 [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* pathexp.c -- The shell interface to the globbing library. */
2
Jari Aalto7117c2d2002-07-17 14:10:11 +00003/* Copyright (C) 1995-2002 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
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
Jari Aaltobb706242000-03-17 21:46:59 +000019 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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"
37
Jari Aaltof73dda02001-11-13 17:56:06 +000038#include <glob/strmatch.h>
Jari Aaltob72432f1999-02-19 17:11:39 +000039
Jari Aalto7117c2d2002-07-17 14:10:11 +000040static int glob_name_is_acceptable __P((const char *));
41static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
42
Jari Aaltob72432f1999-02-19 17:11:39 +000043#if defined (USE_POSIX_GLOB_LIBRARY)
44# include <glob.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000045typedef int posix_glob_errfunc_t __P((const char *, int));
Jari Aaltob72432f1999-02-19 17:11:39 +000046#else
47# include <glob/glob.h>
48#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000049
50/* Control whether * matches .files in globbing. */
51int glob_dot_filenames;
52
Jari Aaltocce855b1998-04-17 19:52:44 +000053/* Control whether the extended globbing features are enabled. */
54int extended_glob = 0;
55
Jari Aaltoccc6cda1996-12-23 17:02:34 +000056/* Return nonzero if STRING has any unquoted special globbing chars in it. */
57int
58unquoted_glob_pattern_p (string)
59 register char *string;
60{
61 register int c;
Jari Aalto7117c2d2002-07-17 14:10:11 +000062 char *send;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000063 int open;
64
Jari Aalto7117c2d2002-07-17 14:10:11 +000065 DECLARE_MBSTATE;
66
Jari Aaltoccc6cda1996-12-23 17:02:34 +000067 open = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +000068 send = string + strlen (string);
69
Jari Aaltoccc6cda1996-12-23 17:02:34 +000070 while (c = *string++)
71 {
72 switch (c)
73 {
74 case '?':
75 case '*':
76 return (1);
77
78 case '[':
79 open++;
80 continue;
81
82 case ']':
83 if (open)
84 return (1);
85 continue;
86
Jari Aaltocce855b1998-04-17 19:52:44 +000087 case '+':
88 case '@':
89 case '!':
90 if (*string == '(') /*)*/
91 return (1);
92 continue;
93
Jari Aaltoccc6cda1996-12-23 17:02:34 +000094 case CTLESC:
95 case '\\':
96 if (*string++ == '\0')
97 return (0);
98 }
Jari Aalto7117c2d2002-07-17 14:10:11 +000099
100 /* Advance one fewer byte than an entire multibyte character to
101 account for the auto-increment in the loop above. */
102#ifdef HANDLE_MULTIBYTE
103 string--;
104 ADVANCE_CHAR_P (string, send - string);
105 string++;
106#else
107 ADVANCE_CHAR_P (string, send - string);
108#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000109 }
110 return (0);
111}
112
113/* PATHNAME can contain characters prefixed by CTLESC; this indicates
114 that the character is to be quoted. We quote it here in the style
Jari Aaltocce855b1998-04-17 19:52:44 +0000115 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000116 we change quoted null strings (pathname[0] == CTLNUL) into empty
117 strings (pathname[0] == 0). If this is called after quote removal
Jari Aaltocce855b1998-04-17 19:52:44 +0000118 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000119 removal has not been done (for example, before attempting to match a
Jari Aaltocce855b1998-04-17 19:52:44 +0000120 pattern while executing a case statement), flags should include
121 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
122 to match a filename should be performed. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000123char *
Jari Aaltocce855b1998-04-17 19:52:44 +0000124quote_string_for_globbing (pathname, qflags)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000125 const char *pathname;
Jari Aaltocce855b1998-04-17 19:52:44 +0000126 int qflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000127{
128 char *temp;
Jari Aaltocce855b1998-04-17 19:52:44 +0000129 register int i, j;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000130
Jari Aaltof73dda02001-11-13 17:56:06 +0000131 temp = (char *)xmalloc (strlen (pathname) + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000132
Jari Aaltocce855b1998-04-17 19:52:44 +0000133 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000134 {
135 temp[0] = '\0';
136 return temp;
137 }
138
Jari Aaltocce855b1998-04-17 19:52:44 +0000139 for (i = j = 0; pathname[i]; i++)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000140 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000141 if (pathname[i] == CTLESC)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000142 {
143 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
144 continue;
Jari Aaltocce855b1998-04-17 19:52:44 +0000145 temp[j++] = '\\';
Jari Aalto7117c2d2002-07-17 14:10:11 +0000146 i++;
147 if (pathname[i] == '\0')
148 break;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000149 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000150 temp[j++] = pathname[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000151 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000152 temp[j] = '\0';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000153
154 return (temp);
155}
156
157char *
158quote_globbing_chars (string)
159 char *string;
160{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000161 size_t slen;
162 char *temp, *s, *t, *send;
163 DECLARE_MBSTATE;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000164
Jari Aalto7117c2d2002-07-17 14:10:11 +0000165 slen = strlen (string);
166 send = string + slen;
167
168 temp = (char *)xmalloc (slen * 2 + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000169 for (t = temp, s = string; *s; )
170 {
171 switch (*s)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000172 {
173 case '*':
174 case '[':
175 case ']':
176 case '?':
177 case '\\':
178 *t++ = '\\';
179 break;
180 case '+':
181 case '@':
182 case '!':
Jari Aaltocce855b1998-04-17 19:52:44 +0000183 if (s[1] == '(') /*(*/
184 *t++ = '\\';
185 break;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000186 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000187
188 /* Copy a single (possibly multibyte) character from s to t,
189 incrementing both. */
190 COPY_CHAR_P (t, s, send);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000191 }
192 *t = '\0';
193 return temp;
194}
195
196/* Call the glob library to do globbing on PATHNAME. */
197char **
198shell_glob_filename (pathname)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000199 const char *pathname;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000200{
201#if defined (USE_POSIX_GLOB_LIBRARY)
202 register int i;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000203 char *temp, **results;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000204 glob_t filenames;
205 int glob_flags;
206
Jari Aaltocce855b1998-04-17 19:52:44 +0000207 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000208
209 filenames.gl_offs = 0;
210
Jari Aaltob72432f1999-02-19 17:11:39 +0000211# if defined (GLOB_PERIOD)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000212 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
Jari Aaltob72432f1999-02-19 17:11:39 +0000213# else
214 glob_flags = 0;
215# endif /* !GLOB_PERIOD */
216
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000217 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
218
Jari Aaltof73dda02001-11-13 17:56:06 +0000219 i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000220
221 free (temp);
222
Jari Aalto28ef6c32001-04-06 19:14:31 +0000223 if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000224 return ((char **)NULL);
Jari Aaltob72432f1999-02-19 17:11:39 +0000225 else if (i == GLOB_NOMATCH)
226 filenames.gl_pathv = (char **)NULL;
227 else if (i != 0) /* other error codes not in POSIX.2 */
Jari Aaltocce855b1998-04-17 19:52:44 +0000228 filenames.gl_pathv = (char **)NULL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000229
Jari Aaltobb706242000-03-17 21:46:59 +0000230 results = filenames.gl_pathv;
231
232 if (results && ((GLOB_FAILED (results)) == 0))
233 {
234 if (should_ignore_glob_matches ())
235 ignore_glob_matches (results);
236 if (results && results[0])
Jari Aalto7117c2d2002-07-17 14:10:11 +0000237 strvec_sort (results);
Jari Aaltobb706242000-03-17 21:46:59 +0000238 else
239 {
240 FREE (results);
241 results = (char **)NULL;
242 }
243 }
244
245 return (results);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000246
247#else /* !USE_POSIX_GLOB_LIBRARY */
248
249 char *temp, **results;
250
251 noglob_dot_filenames = glob_dot_filenames == 0;
252
Jari Aaltocce855b1998-04-17 19:52:44 +0000253 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000254 results = glob_filename (temp, 0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000255 free (temp);
256
257 if (results && ((GLOB_FAILED (results)) == 0))
258 {
259 if (should_ignore_glob_matches ())
260 ignore_glob_matches (results);
261 if (results && results[0])
Jari Aalto7117c2d2002-07-17 14:10:11 +0000262 strvec_sort (results);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000263 else
264 {
265 FREE (results);
266 results = (char **)&glob_error_return;
267 }
268 }
269
270 return (results);
271#endif /* !USE_POSIX_GLOB_LIBRARY */
272}
273
274/* Stuff for GLOBIGNORE. */
275
276static struct ignorevar globignore =
277{
278 "GLOBIGNORE",
279 (struct ign *)0,
280 0,
281 (char *)0,
Jari Aaltof73dda02001-11-13 17:56:06 +0000282 (sh_iv_item_func_t *)0,
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000283};
284
285/* Set up to ignore some glob matches because the value of GLOBIGNORE
286 has changed. If GLOBIGNORE is being unset, we also need to disable
287 the globbing of filenames beginning with a `.'. */
288void
289setup_glob_ignore (name)
290 char *name;
291{
292 char *v;
293
294 v = get_string_value (name);
295 setup_ignore_patterns (&globignore);
296
297 if (globignore.num_ignores)
298 glob_dot_filenames = 1;
299 else if (v == 0)
300 glob_dot_filenames = 0;
301}
302
303int
304should_ignore_glob_matches ()
305{
306 return globignore.num_ignores;
307}
308
309/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
310static int
311glob_name_is_acceptable (name)
Jari Aaltof73dda02001-11-13 17:56:06 +0000312 const char *name;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000313{
314 struct ign *p;
Jari Aaltocce855b1998-04-17 19:52:44 +0000315 int flags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000316
317 /* . and .. are never matched */
318 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
319 return (0);
320
Jari Aaltocce855b1998-04-17 19:52:44 +0000321 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000322 for (p = globignore.ignores; p->val; p++)
323 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000324 if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000325 return (0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000326 }
327 return (1);
328}
329
330/* Internal function to test whether filenames in NAMES should be
331 ignored. NAME_FUNC is a pointer to a function to call with each
332 name. It returns non-zero if the name is acceptable to the particular
333 ignore function which called _ignore_names; zero if the name should
334 be removed from NAMES. */
335
336static void
337ignore_globbed_names (names, name_func)
338 char **names;
Jari Aaltof73dda02001-11-13 17:56:06 +0000339 sh_ignore_func_t *name_func;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000340{
341 char **newnames;
342 int n, i;
343
344 for (i = 0; names[i]; i++)
345 ;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000346 newnames = strvec_create (i + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000347
348 for (n = i = 0; names[i]; i++)
349 {
350 if ((*name_func) (names[i]))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000351 newnames[n++] = names[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000352 else
353 free (names[i]);
354 }
355
356 newnames[n] = (char *)NULL;
357
358 if (n == 0)
359 {
360 names[0] = (char *)NULL;
361 free (newnames);
362 return;
363 }
364
365 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
366 new array end. */
367 for (n = 0; newnames[n]; n++)
368 names[n] = newnames[n];
369 names[n] = (char *)NULL;
Jari Aaltod166f041997-06-05 14:59:13 +0000370 free (newnames);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000371}
372
373void
374ignore_glob_matches (names)
375 char **names;
376{
377 if (globignore.num_ignores == 0)
378 return;
379
380 ignore_globbed_names (names, glob_name_is_acceptable);
381}
382
383void
384setup_ignore_patterns (ivp)
385 struct ignorevar *ivp;
386{
387 int numitems, maxitems, ptr;
388 char *colon_bit, *this_ignoreval;
389 struct ign *p;
390
391 this_ignoreval = get_string_value (ivp->varname);
392
393 /* If nothing has changed then just exit now. */
394 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
395 (!this_ignoreval && !ivp->last_ignoreval))
396 return;
397
398 /* Oops. The ignore variable has changed. Re-parse it. */
399 ivp->num_ignores = 0;
400
401 if (ivp->ignores)
402 {
403 for (p = ivp->ignores; p->val; p++)
404 free(p->val);
405 free (ivp->ignores);
406 ivp->ignores = (struct ign *)NULL;
407 }
408
409 if (ivp->last_ignoreval)
410 {
411 free (ivp->last_ignoreval);
412 ivp->last_ignoreval = (char *)NULL;
413 }
414
415 if (this_ignoreval == 0 || *this_ignoreval == '\0')
416 return;
417
418 ivp->last_ignoreval = savestring (this_ignoreval);
419
420 numitems = maxitems = ptr = 0;
421
422 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
423 {
424 if (numitems + 1 >= maxitems)
425 {
426 maxitems += 10;
427 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
428 }
429 ivp->ignores[numitems].val = colon_bit;
430 ivp->ignores[numitems].len = strlen (colon_bit);
431 ivp->ignores[numitems].flags = 0;
432 if (ivp->item_func)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000433 (*ivp->item_func) (&ivp->ignores[numitems]);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000434 numitems++;
435 }
436 ivp->ignores[numitems].val = (char *)NULL;
437 ivp->num_ignores = numitems;
438}