1 /* pathexp.c -- The shell interface to the globbing library. */
3 /* Copyright (C) 1995 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 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
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
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
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include "bashtypes.h"
26 #if defined (HAVE_UNISTD_H)
36 #include <glob/fnmatch.h>
37 #include <glob/glob.h>
39 /* Control whether * matches .files in globbing. */
40 int glob_dot_filenames;
42 /* Control whether the extended globbing features are enabled. */
43 int extended_glob = 0;
45 /* Return nonzero if STRING has any unquoted special globbing chars in it. */
47 unquoted_glob_pattern_p (string)
48 register char *string;
74 if (*string == '(') /*)*/
80 if (*string++ == '\0')
87 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
88 that the character is to be quoted. We quote it here in the style
89 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
90 we change quoted null strings (pathname[0] == CTLNUL) into empty
91 strings (pathname[0] == 0). If this is called after quote removal
92 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
93 removal has not been done (for example, before attempting to match a
94 pattern while executing a case statement), flags should include
95 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
96 to match a filename should be performed. */
98 quote_string_for_globbing (pathname, qflags)
105 temp = xmalloc (strlen (pathname) + 1);
107 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
113 for (i = j = 0; pathname[i]; i++)
115 if (pathname[i] == CTLESC)
117 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
122 temp[j++] = pathname[i];
130 quote_globbing_chars (string)
135 temp = xmalloc (strlen (string) * 2 + 1);
136 for (t = temp, s = string; *s; )
150 if (s[1] == '(') /*(*/
160 /* Call the glob library to do globbing on PATHNAME. */
162 shell_glob_filename (pathname)
165 #if defined (USE_POSIX_GLOB_LIBRARY)
167 char *temp, **return_value;
171 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
173 filenames.gl_offs = 0;
175 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
176 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
178 i = glob (temp, glob_flags, (Function *)NULL, &filenames);
182 if (i == GLOB_NOSPACE || i == GLOB_ABEND)
183 return ((char **)NULL);
185 if (i == GLOB_NOMATCH)
186 filenames.gl_pathv = (char **)NULL;
188 return (filenames.gl_pathv);
190 #else /* !USE_POSIX_GLOB_LIBRARY */
192 char *temp, **results;
194 noglob_dot_filenames = glob_dot_filenames == 0;
196 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
198 results = glob_filename (temp);
201 if (results && ((GLOB_FAILED (results)) == 0))
203 if (should_ignore_glob_matches ())
204 ignore_glob_matches (results);
205 if (results && results[0])
206 sort_char_array (results);
210 results = (char **)&glob_error_return;
215 #endif /* !USE_POSIX_GLOB_LIBRARY */
218 /* Stuff for GLOBIGNORE. */
220 static struct ignorevar globignore =
229 /* Set up to ignore some glob matches because the value of GLOBIGNORE
230 has changed. If GLOBIGNORE is being unset, we also need to disable
231 the globbing of filenames beginning with a `.'. */
233 setup_glob_ignore (name)
238 v = get_string_value (name);
239 setup_ignore_patterns (&globignore);
241 if (globignore.num_ignores)
242 glob_dot_filenames = 1;
244 glob_dot_filenames = 0;
248 should_ignore_glob_matches ()
250 return globignore.num_ignores;
253 /* Return 0 if NAME matches a pattern in the globignore.ignores list. */
255 glob_name_is_acceptable (name)
261 /* . and .. are never matched */
262 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
265 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
266 for (p = globignore.ignores; p->val; p++)
268 if (fnmatch (p->val, name, flags) != FNM_NOMATCH)
274 /* Internal function to test whether filenames in NAMES should be
275 ignored. NAME_FUNC is a pointer to a function to call with each
276 name. It returns non-zero if the name is acceptable to the particular
277 ignore function which called _ignore_names; zero if the name should
278 be removed from NAMES. */
281 ignore_globbed_names (names, name_func)
288 for (i = 0; names[i]; i++)
290 newnames = (char **)xmalloc ((i + 1) * sizeof (char *));
292 for (n = i = 0; names[i]; i++)
294 if ((*name_func) (names[i]))
295 newnames[n++] = names[i];
300 newnames[n] = (char *)NULL;
304 names[0] = (char *)NULL;
309 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
311 for (n = 0; newnames[n]; n++)
312 names[n] = newnames[n];
313 names[n] = (char *)NULL;
318 ignore_glob_matches (names)
321 if (globignore.num_ignores == 0)
324 ignore_globbed_names (names, glob_name_is_acceptable);
328 setup_ignore_patterns (ivp)
329 struct ignorevar *ivp;
331 int numitems, maxitems, ptr;
332 char *colon_bit, *this_ignoreval;
335 this_ignoreval = get_string_value (ivp->varname);
337 /* If nothing has changed then just exit now. */
338 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
339 (!this_ignoreval && !ivp->last_ignoreval))
342 /* Oops. The ignore variable has changed. Re-parse it. */
343 ivp->num_ignores = 0;
347 for (p = ivp->ignores; p->val; p++)
350 ivp->ignores = (struct ign *)NULL;
353 if (ivp->last_ignoreval)
355 free (ivp->last_ignoreval);
356 ivp->last_ignoreval = (char *)NULL;
359 if (this_ignoreval == 0 || *this_ignoreval == '\0')
362 ivp->last_ignoreval = savestring (this_ignoreval);
364 numitems = maxitems = ptr = 0;
366 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
368 if (numitems + 1 >= maxitems)
371 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
373 ivp->ignores[numitems].val = colon_bit;
374 ivp->ignores[numitems].len = strlen (colon_bit);
375 ivp->ignores[numitems].flags = 0;
377 (*ivp->item_func) (&ivp->ignores[numitems]);
380 ivp->ignores[numitems].val = (char *)NULL;
381 ivp->num_ignores = numitems;