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>
38 #if defined (USE_POSIX_GLOB_LIBRARY)
41 # include <glob/glob.h>
44 /* Control whether * matches .files in globbing. */
45 int glob_dot_filenames;
47 /* Control whether the extended globbing features are enabled. */
48 int extended_glob = 0;
50 /* Return nonzero if STRING has any unquoted special globbing chars in it. */
52 unquoted_glob_pattern_p (string)
53 register char *string;
79 if (*string == '(') /*)*/
85 if (*string++ == '\0')
92 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
93 that the character is to be quoted. We quote it here in the style
94 that the glob library recognizes. If flags includes QGLOB_CVTNULL,
95 we change quoted null strings (pathname[0] == CTLNUL) into empty
96 strings (pathname[0] == 0). If this is called after quote removal
97 is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
98 removal has not been done (for example, before attempting to match a
99 pattern while executing a case statement), flags should include
100 QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
101 to match a filename should be performed. */
103 quote_string_for_globbing (pathname, qflags)
110 temp = xmalloc (strlen (pathname) + 1);
112 if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
118 for (i = j = 0; pathname[i]; i++)
120 if (pathname[i] == CTLESC)
122 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
127 temp[j++] = pathname[i];
135 quote_globbing_chars (string)
140 temp = xmalloc (strlen (string) * 2 + 1);
141 for (t = temp, s = string; *s; )
155 if (s[1] == '(') /*(*/
165 /* Call the glob library to do globbing on PATHNAME. */
167 shell_glob_filename (pathname)
170 #if defined (USE_POSIX_GLOB_LIBRARY)
172 char *temp, **return_value;
176 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
178 filenames.gl_offs = 0;
180 # if defined (GLOB_PERIOD)
181 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
184 # endif /* !GLOB_PERIOD */
186 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
188 i = glob (temp, glob_flags, (Function *)NULL, &filenames);
192 if (i == GLOB_NOSPACE || i == GLOB_ABEND)
193 return ((char **)NULL);
194 else if (i == GLOB_NOMATCH)
195 filenames.gl_pathv = (char **)NULL;
196 else if (i != 0) /* other error codes not in POSIX.2 */
197 filenames.gl_pathv = (char **)NULL;
199 return (filenames.gl_pathv);
201 #else /* !USE_POSIX_GLOB_LIBRARY */
203 char *temp, **results;
205 noglob_dot_filenames = glob_dot_filenames == 0;
207 temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
209 results = glob_filename (temp);
212 if (results && ((GLOB_FAILED (results)) == 0))
214 if (should_ignore_glob_matches ())
215 ignore_glob_matches (results);
216 if (results && results[0])
217 sort_char_array (results);
221 results = (char **)&glob_error_return;
226 #endif /* !USE_POSIX_GLOB_LIBRARY */
229 /* Stuff for GLOBIGNORE. */
231 static struct ignorevar globignore =
240 /* Set up to ignore some glob matches because the value of GLOBIGNORE
241 has changed. If GLOBIGNORE is being unset, we also need to disable
242 the globbing of filenames beginning with a `.'. */
244 setup_glob_ignore (name)
249 v = get_string_value (name);
250 setup_ignore_patterns (&globignore);
252 if (globignore.num_ignores)
253 glob_dot_filenames = 1;
255 glob_dot_filenames = 0;
259 should_ignore_glob_matches ()
261 return globignore.num_ignores;
264 /* Return 0 if NAME matches a pattern in the globignore.ignores list. */
266 glob_name_is_acceptable (name)
272 /* . and .. are never matched */
273 if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
276 flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
277 for (p = globignore.ignores; p->val; p++)
279 if (fnmatch (p->val, name, flags) != FNM_NOMATCH)
285 /* Internal function to test whether filenames in NAMES should be
286 ignored. NAME_FUNC is a pointer to a function to call with each
287 name. It returns non-zero if the name is acceptable to the particular
288 ignore function which called _ignore_names; zero if the name should
289 be removed from NAMES. */
292 ignore_globbed_names (names, name_func)
299 for (i = 0; names[i]; i++)
301 newnames = (char **)xmalloc ((i + 1) * sizeof (char *));
303 for (n = i = 0; names[i]; i++)
305 if ((*name_func) (names[i]))
306 newnames[n++] = names[i];
311 newnames[n] = (char *)NULL;
315 names[0] = (char *)NULL;
320 /* Copy the acceptable names from NEWNAMES back to NAMES and set the
322 for (n = 0; newnames[n]; n++)
323 names[n] = newnames[n];
324 names[n] = (char *)NULL;
329 ignore_glob_matches (names)
332 if (globignore.num_ignores == 0)
335 ignore_globbed_names (names, glob_name_is_acceptable);
339 setup_ignore_patterns (ivp)
340 struct ignorevar *ivp;
342 int numitems, maxitems, ptr;
343 char *colon_bit, *this_ignoreval;
346 this_ignoreval = get_string_value (ivp->varname);
348 /* If nothing has changed then just exit now. */
349 if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
350 (!this_ignoreval && !ivp->last_ignoreval))
353 /* Oops. The ignore variable has changed. Re-parse it. */
354 ivp->num_ignores = 0;
358 for (p = ivp->ignores; p->val; p++)
361 ivp->ignores = (struct ign *)NULL;
364 if (ivp->last_ignoreval)
366 free (ivp->last_ignoreval);
367 ivp->last_ignoreval = (char *)NULL;
370 if (this_ignoreval == 0 || *this_ignoreval == '\0')
373 ivp->last_ignoreval = savestring (this_ignoreval);
375 numitems = maxitems = ptr = 0;
377 while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
379 if (numitems + 1 >= maxitems)
382 ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
384 ivp->ignores[numitems].val = colon_bit;
385 ivp->ignores[numitems].len = strlen (colon_bit);
386 ivp->ignores[numitems].flags = 0;
388 (*ivp->item_func) (&ivp->ignores[numitems]);
391 ivp->ignores[numitems].val = (char *)NULL;
392 ivp->num_ignores = numitems;