1 /* File-name wildcard pattern matching for GNU.
2 Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 1, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* To whomever it may concern: I have never seen the code which most
19 Unix programs use to perform this function. I wrote this from scratch
20 based on specifications for the pattern matching. --RMS. */
23 # if defined (HAVE_STDLIB_H)
26 # include "ansi_stdlib.h"
27 # endif /* HAVE_STDLIB_H */
31 #include <sys/types.h>
33 #if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
34 # if !defined (HAVE_DIRENT_H)
35 # define HAVE_DIRENT_H
36 # endif /* !HAVE_DIRENT_H */
37 #endif /* !SHELL && (_POSIX_VERSION || USGr3) */
39 #if defined (HAVE_DIRENT_H)
41 # if !defined (direct)
42 # define direct dirent
44 # define D_NAMLEN(d) strlen ((d)->d_name)
45 #else /* !HAVE_DIRENT_H */
46 # define D_NAMLEN(d) ((d)->d_namlen)
49 # include <sys/ndir.h>
50 # else /* !Xenix (but USG...) */
56 #endif /* !HAVE_DIRENT_H */
58 #if defined (_POSIX_SOURCE)
59 /* Posix does not require that the d_ino field be present, and some
60 systems do not provide it. */
61 # define REAL_DIR_ENTRY(dp) 1
63 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
64 #endif /* _POSIX_SOURCE */
66 #if defined (USG) || defined (NeXT)
67 # if !defined (HAVE_STRING_H)
68 # define HAVE_STRING_H
69 # endif /* !HAVE_STRING_H */
70 #endif /* USG || NeXT */
72 #if defined (HAVE_STRING_H)
74 #else /* !HAVE_STRING_H */
76 #endif /* !HAVE_STRING_H */
79 # if !defined (isc386)
82 # if defined (RISC6000)
84 # else /* !RISC6000 */
85 # define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
86 # endif /* !RISC6000 */
91 /* If the opendir () on your system lets you open non-directory files,
92 then we consider that not robust. Define OPENDIR_NOT_ROBUST in the
93 SYSDEP_CFLAGS for your machines entry in machines.h. */
94 #if defined (OPENDIR_NOT_ROBUST)
96 # include "posixstat.h"
98 # include <sys/stat.h>
100 #endif /* OPENDIR_NOT_ROBUST */
102 #if !defined (HAVE_STDLIB_H)
103 extern char *malloc (), *realloc ();
105 #endif /* !HAVE_STDLIB_H */
108 # if defined (__STDC__)
109 # define NULL ((void *) 0)
112 # endif /* __STDC__ */
116 extern int interrupt_state;
119 /* Global variable which controls whether or not * matches .*.
120 Non-zero means don't match .*. */
121 int noglob_dot_filenames = 1;
123 /* Global variable to return to signify an error in globbing. */
124 char *glob_error_return;
127 /* Return nonzero if PATTERN has any special globbing chars in it. */
129 glob_pattern_p (pattern)
132 register char *p = pattern;
136 while ((c = *p++) != '\0')
143 case '[': /* Only accept an open brace if there is a close */
144 open++; /* brace to match it. Bracket expressions must be */
145 continue; /* complete, according to Posix.2 */
159 /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
161 dequote_pathname (pathname)
166 for (i = j = 0; pathname && pathname[i]; )
168 if (pathname[i] == '\\')
171 pathname[j++] = pathname[i++];
173 if (!pathname[i - 1])
180 /* Return a vector of names of files in directory DIR
181 whose names match glob pattern PAT.
182 The names are not in any particular order.
183 Wildcards at the beginning of PAT do not match an initial period.
185 The vector is terminated by an element that is a null pointer.
187 To free the space allocated, first free the vector's elements,
188 then free the vector.
190 Return 0 if cannot get enough memory to hold the pointer
193 Return -1 if cannot access directory DIR.
194 Look in errno for more information. */
197 glob_vector (pat, dir)
203 struct globval *next;
208 register struct direct *dp;
209 struct globval *lastlink;
210 register struct globval *nextlink;
211 register char *nextname;
214 register char **name_vector;
215 register unsigned int i;
216 #if defined (OPENDIR_NOT_ROBUST)
219 if (stat (dir, &finfo) < 0)
220 return ((char **) &glob_error_return);
222 if (!S_ISDIR (finfo.st_mode))
223 return ((char **) &glob_error_return);
224 #endif /* OPENDIR_NOT_ROBUST */
228 return ((char **) &glob_error_return);
235 /* If PAT is empty, skip the loop, but return one (empty) filename. */
238 nextlink = (struct globval *)alloca (sizeof (struct globval));
239 nextlink->next = lastlink;
240 nextname = (char *) malloc (1);
246 nextlink->name = nextname;
253 /* Scan the directory, finding all names that match.
254 For each name that matches, allocate a struct globval
255 on the stack and store the name in it.
256 Chain those structs together; lastlink is the front of the chain. */
259 int flags; /* Flags passed to fnmatch (). */
261 /* Make globbing interruptible in the bash shell. */
274 /* If this directory entry is not to be used, try again. */
275 if (!REAL_DIR_ENTRY (dp))
278 /* If a dot must be explicity matched, check to see if they do. */
279 if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
282 flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
284 if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
286 nextlink = (struct globval *) alloca (sizeof (struct globval));
287 nextlink->next = lastlink;
288 nextname = (char *) malloc (D_NAMLEN (dp) + 1);
289 if (nextname == NULL)
295 nextlink->name = nextname;
296 bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
304 name_vector = (char **) malloc ((count + 1) * sizeof (char *));
305 lose |= name_vector == NULL;
308 /* Have we run out of memory? */
312 /* Here free the strings we have got. */
315 free (lastlink->name);
316 lastlink = lastlink->next;
320 throw_to_top_level ();
325 /* Copy the name pointers from the linked list into the vector. */
326 for (i = 0; i < count; ++i)
328 name_vector[i] = lastlink->name;
329 lastlink = lastlink->next;
332 name_vector[count] = NULL;
333 return (name_vector);
336 /* Return a new array which is the concatenation of each string in ARRAY
337 to DIR. This function expects you to pass in an allocated ARRAY, and
338 it takes care of free()ing that array. Thus, you might think of this
339 function as side-effecting ARRAY. */
341 glob_dir_to_array (dir, array)
344 register unsigned int i, l;
352 add_slash = dir[l - 1] != '/';
355 while (array[i] != NULL)
358 result = (char **) malloc ((i + 1) * sizeof (char *));
362 for (i = 0; array[i] != NULL; i++)
364 result[i] = (char *) malloc (l + (add_slash ? 1 : 0)
365 + strlen (array[i]) + 1);
366 if (result[i] == NULL)
368 sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
372 /* Free the input array. */
373 for (i = 0; array[i] != NULL; i++)
375 free ((char *) array);
380 /* Do globbing on PATHNAME. Return an array of pathnames that match,
381 marking the end of the array with a null-pointer as an element.
382 If no pathnames match, then the array is empty (first element is null).
383 If there isn't enough memory, then return NULL.
384 If a file system error occurs, return -1; `errno' has the error code. */
386 glob_filename (pathname)
390 unsigned int result_size;
391 char *directory_name, *filename;
392 unsigned int directory_len;
394 result = (char **) malloc (sizeof (char *));
401 /* Find the filename. */
402 filename = strrchr (pathname, '/');
403 if (filename == NULL)
411 directory_len = (filename - pathname) + 1;
412 directory_name = (char *) alloca (directory_len + 1);
414 bcopy (pathname, directory_name, directory_len);
415 directory_name[directory_len] = '\0';
419 /* If directory_name contains globbing characters, then we
420 have to expand the previous levels. Just recurse. */
421 if (glob_pattern_p (directory_name))
424 register unsigned int i;
426 if (directory_name[directory_len - 1] == '/')
427 directory_name[directory_len - 1] = '\0';
429 directories = glob_filename (directory_name);
431 if (directories == NULL)
433 else if (directories == (char **)&glob_error_return)
435 free ((char *)result);
436 return ((char **) &glob_error_return);
438 else if (*directories == NULL)
440 free ((char *) directories);
441 free ((char *) result);
442 return ((char **) &glob_error_return);
445 /* We have successfully globbed the preceding directory name.
446 For each name in DIRECTORIES, call glob_vector on it and
447 FILENAME. Concatenate the results together. */
448 for (i = 0; directories[i] != NULL; ++i)
452 /* Scan directory even on a NULL pathname. That way, `*h/'
453 returns only directories ending in `h', instead of all
454 files ending in `h' with a `/' appended. */
455 temp_results = glob_vector (filename, directories[i]);
457 /* Handle error cases. */
458 if (temp_results == NULL)
460 else if (temp_results == (char **)&glob_error_return)
461 /* This filename is probably not a directory. Ignore it. */
466 register unsigned int l;
468 array = glob_dir_to_array (directories[i], temp_results);
470 while (array[l] != NULL)
474 (char **)realloc (result, (result_size + l) * sizeof (char *));
479 for (l = 0; array[l] != NULL; ++l)
480 result[result_size++ - 1] = array[l];
482 result[result_size - 1] = NULL;
484 /* Note that the elements of ARRAY are not freed. */
485 free ((char *) array);
488 /* Free the directories. */
489 for (i = 0; directories[i]; i++)
490 free (directories[i]);
492 free ((char *) directories);
497 /* If there is only a directory name, return it. */
498 if (*filename == '\0')
500 result = (char **) realloc ((char *) result, 2 * sizeof (char *));
503 result[0] = (char *) malloc (directory_len + 1);
504 if (result[0] == NULL)
506 bcopy (directory_name, result[0], directory_len + 1);
514 /* There are no unquoted globbing characters in DIRECTORY_NAME.
515 Dequote it before we try to open the directory since there may
516 be quoted globbing characters which should be treated verbatim. */
517 if (directory_len > 0)
518 dequote_pathname (directory_name);
520 /* We allocated a small array called RESULT, which we won't be using.
521 Free that memory now. */
524 /* Just return what glob_vector () returns appended to the
527 glob_vector (filename, (directory_len == 0 ? "." : directory_name));
529 if (temp_results == NULL || temp_results == (char **)&glob_error_return)
530 return (temp_results);
532 return (glob_dir_to_array (directory_name, temp_results));
535 /* We get to memory_error if the program has run out of memory, or
536 if this is the shell, and we have been interrupted. */
540 register unsigned int i;
541 for (i = 0; result[i] != NULL; ++i)
543 free ((char *) result);
547 throw_to_top_level ();
560 for (i = 1; i < argc; ++i)
562 char **value = glob_filename (argv[i]);
564 puts ("Out of memory.");
565 else if (value == &glob_error_return)
568 for (i = 0; value[i] != NULL; i++)