]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/glob/glob.c
Imported from ../bash-2.05a.tar.gz.
[thirdparty/bash.git] / lib / glob / glob.c
1 /* File-name wildcard pattern matching for GNU.
2 Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
3
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 2, or (at your option)
7 any later version.
8
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.
13
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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
17
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. */
21
22 #include <config.h>
23
24 #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
25 #pragma alloca
26 #endif /* _AIX && RISC6000 && !__GNUC__ */
27
28 #if defined (SHELL)
29 # include "bashtypes.h"
30 #else
31 # include <sys/types.h>
32 #endif
33
34 #if defined (HAVE_UNISTD_H)
35 # include <unistd.h>
36 #endif
37
38 #if defined (SHELL)
39 # include "bashansi.h"
40 #else
41 # if defined (HAVE_STDLIB_H)
42 # include <stdlib.h>
43 # endif
44 # if defined (HAVE_STRING_H)
45 # include <string.h>
46 # else /* !HAVE_STRING_H */
47 # include <strings.h>
48 # endif /* !HAVE_STRING_H */
49 #endif
50
51 #if defined (HAVE_DIRENT_H)
52 # include <dirent.h>
53 # define D_NAMLEN(d) strlen ((d)->d_name)
54 #else /* !HAVE_DIRENT_H */
55 # define D_NAMLEN(d) ((d)->d_namlen)
56 # if defined (HAVE_SYS_NDIR_H)
57 # include <sys/ndir.h>
58 # endif
59 # if defined (HAVE_SYS_DIR_H)
60 # include <sys/dir.h>
61 # endif /* HAVE_SYS_DIR_H */
62 # if defined (HAVE_NDIR_H)
63 # include <ndir.h>
64 # endif
65 # if !defined (dirent)
66 # define dirent direct
67 # endif
68 #endif /* !HAVE_DIRENT_H */
69
70 #if defined (_POSIX_SOURCE) && !defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO)
71 /* Posix does not require that the d_ino field be present, and some
72 systems do not provide it. */
73 # define REAL_DIR_ENTRY(dp) 1
74 #else
75 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
76 #endif /* _POSIX_SOURCE */
77
78 #if !defined (HAVE_BCOPY) && !defined (bcopy)
79 # define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
80 #endif /* !HAVE_BCOPY && !bcopy */
81
82 #if defined (SHELL)
83 # include "posixstat.h"
84 #else /* !SHELL */
85 # include <sys/stat.h>
86 #endif /* !SHELL */
87
88 #include "filecntl.h"
89 #if !defined (F_OK)
90 # define F_OK 0
91 #endif
92
93 #if defined (SHELL)
94 # include "memalloc.h"
95 #endif
96
97 #include "strmatch.h"
98
99 #if !defined (HAVE_STDLIB_H) && !defined (SHELL)
100 extern char *malloc (), *realloc ();
101 extern void free ();
102 #endif /* !HAVE_STDLIB_H */
103
104 #if !defined (NULL)
105 # if defined (__STDC__)
106 # define NULL ((void *) 0)
107 # else
108 # define NULL 0x0
109 # endif /* __STDC__ */
110 #endif /* !NULL */
111
112 #if defined (SHELL)
113 extern void throw_to_top_level ();
114 extern int test_eaccess ();
115
116 extern int interrupt_state;
117 extern int extended_glob;
118 #endif /* SHELL */
119
120 /* Global variable which controls whether or not * matches .*.
121 Non-zero means don't match .*. */
122 int noglob_dot_filenames = 1;
123
124 /* Global variable which controls whether or not filename globbing
125 is done without regard to case. */
126 int glob_ignore_case = 0;
127
128 /* Global variable to return to signify an error in globbing. */
129 char *glob_error_return;
130
131 /* Return nonzero if PATTERN has any special globbing chars in it. */
132 int
133 glob_pattern_p (pattern)
134 const char *pattern;
135 {
136 register const char *p;
137 register char c;
138 int bopen;
139
140 p = pattern;
141 bopen = 0;
142
143 while ((c = *p++) != '\0')
144 switch (c)
145 {
146 case '?':
147 case '*':
148 return (1);
149
150 case '[': /* Only accept an open brace if there is a close */
151 bopen++; /* brace to match it. Bracket expressions must be */
152 continue; /* complete, according to Posix.2 */
153 case ']':
154 if (bopen)
155 return (1);
156 continue;
157
158 case '+': /* extended matching operators */
159 case '@':
160 case '!':
161 if (*p == '(') /*) */
162 return (1);
163 continue;
164
165 case '\\':
166 if (*p++ == '\0')
167 return (0);
168 }
169
170 return (0);
171 }
172
173 /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
174 static void
175 dequote_pathname (pathname)
176 char *pathname;
177 {
178 register int i, j;
179
180 for (i = j = 0; pathname && pathname[i]; )
181 {
182 if (pathname[i] == '\\')
183 i++;
184
185 pathname[j++] = pathname[i++];
186
187 if (!pathname[i - 1])
188 break;
189 }
190 pathname[j] = '\0';
191 }
192
193 \f
194
195 /* Test whether NAME exists. */
196
197 #if defined (HAVE_LSTAT)
198 # define GLOB_TESTNAME(name) (lstat (name, &finfo))
199 #else /* !HAVE_LSTAT */
200 # if defined (SHELL) && !defined (AFS)
201 # define GLOB_TESTNAME(name) (test_eaccess (nextname, F_OK))
202 # else /* !SHELL || AFS */
203 # define GLOB_TESTNAME(name) (access (nextname, F_OK))
204 # endif /* !SHELL || AFS */
205 #endif /* !HAVE_LSTAT */
206
207 /* Return 0 if DIR is a directory, -1 otherwise. */
208 static int
209 glob_testdir (dir)
210 char *dir;
211 {
212 struct stat finfo;
213
214 if (stat (dir, &finfo) < 0)
215 return (-1);
216
217 if (S_ISDIR (finfo.st_mode) == 0)
218 return (-1);
219
220 return (0);
221 }
222
223 /* Return a vector of names of files in directory DIR
224 whose names match glob pattern PAT.
225 The names are not in any particular order.
226 Wildcards at the beginning of PAT do not match an initial period.
227
228 The vector is terminated by an element that is a null pointer.
229
230 To free the space allocated, first free the vector's elements,
231 then free the vector.
232
233 Return 0 if cannot get enough memory to hold the pointer
234 and the names.
235
236 Return -1 if cannot access directory DIR.
237 Look in errno for more information. */
238
239 char **
240 glob_vector (pat, dir)
241 char *pat;
242 char *dir;
243 {
244 struct globval
245 {
246 struct globval *next;
247 char *name;
248 };
249
250 DIR *d;
251 register struct dirent *dp;
252 struct globval *lastlink;
253 register struct globval *nextlink;
254 register char *nextname, *npat;
255 unsigned int count;
256 int lose, skip;
257 register char **name_vector;
258 register unsigned int i;
259 int flags; /* Flags passed to strmatch (). */
260
261 lastlink = 0;
262 count = lose = skip = 0;
263
264 /* If PAT is empty, skip the loop, but return one (empty) filename. */
265 if (pat == 0 || *pat == '\0')
266 {
267 if (glob_testdir (dir) < 0)
268 return ((char **) &glob_error_return);
269
270 nextlink = (struct globval *)alloca (sizeof (struct globval));
271 nextlink->next = (struct globval *)0;
272 nextname = (char *) malloc (1);
273 if (nextname == 0)
274 lose = 1;
275 else
276 {
277 lastlink = nextlink;
278 nextlink->name = nextname;
279 nextname[0] = '\0';
280 count = 1;
281 }
282
283 skip = 1;
284 }
285
286 /* If the filename pattern (PAT) does not contain any globbing characters,
287 we can dispense with reading the directory, and just see if there is
288 a filename `DIR/PAT'. If there is, and we can access it, just make the
289 vector to return and bail immediately. */
290 if (skip == 0 && glob_pattern_p (pat) == 0)
291 {
292 int dirlen;
293 struct stat finfo;
294
295 if (glob_testdir (dir) < 0)
296 return ((char **) &glob_error_return);
297
298 dirlen = strlen (dir);
299 nextname = (char *)malloc (dirlen + strlen (pat) + 2);
300 npat = (char *)malloc (strlen (pat) + 1);
301 if (nextname == 0 || npat == 0)
302 lose = 1;
303 else
304 {
305 strcpy (npat, pat);
306 dequote_pathname (npat);
307
308 strcpy (nextname, dir);
309 nextname[dirlen++] = '/';
310 strcpy (nextname + dirlen, npat);
311
312 if (GLOB_TESTNAME (nextname) >= 0)
313 {
314 free (nextname);
315 nextlink = (struct globval *)alloca (sizeof (struct globval));
316 nextlink->next = (struct globval *)0;
317 lastlink = nextlink;
318 nextlink->name = npat;
319 count = 1;
320 }
321 else
322 {
323 free (nextname);
324 free (npat);
325 }
326 }
327
328 skip = 1;
329 }
330
331 if (skip == 0)
332 {
333 /* Open the directory, punting immediately if we cannot. If opendir
334 is not robust (i.e., it opens non-directories successfully), test
335 that DIR is a directory and punt if it's not. */
336 #if defined (OPENDIR_NOT_ROBUST)
337 if (glob_testdir (dir) < 0)
338 return ((char **) &glob_error_return);
339 #endif
340
341 d = opendir (dir);
342 if (d == NULL)
343 return ((char **) &glob_error_return);
344
345 /* Compute the flags that will be passed to strmatch(). We don't
346 need to do this every time through the loop. */
347 flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
348
349 #ifdef FNM_CASEFOLD
350 if (glob_ignore_case)
351 flags |= FNM_CASEFOLD;
352 #endif
353
354 #ifdef SHELL
355 if (extended_glob)
356 flags |= FNM_EXTMATCH;
357 #endif
358
359 /* Scan the directory, finding all names that match.
360 For each name that matches, allocate a struct globval
361 on the stack and store the name in it.
362 Chain those structs together; lastlink is the front of the chain. */
363 while (1)
364 {
365 #if defined (SHELL)
366 /* Make globbing interruptible in the shell. */
367 if (interrupt_state)
368 {
369 lose = 1;
370 break;
371 }
372 #endif /* SHELL */
373
374 dp = readdir (d);
375 if (dp == NULL)
376 break;
377
378 /* If this directory entry is not to be used, try again. */
379 if (REAL_DIR_ENTRY (dp) == 0)
380 continue;
381
382 /* If a leading dot need not be explicitly matched, and the pattern
383 doesn't start with a `.', don't match `.' or `..' */
384 #define dname dp->d_name
385 if (noglob_dot_filenames == 0 && pat[0] != '.' &&
386 (pat[0] != '\\' || pat[1] != '.') &&
387 (dname[0] == '.' &&
388 (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
389 #undef dname
390 continue;
391
392 /* If a dot must be explicity matched, check to see if they do. */
393 if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
394 (pat[0] != '\\' || pat[1] != '.'))
395 continue;
396
397 if (strmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
398 {
399 nextlink = (struct globval *) alloca (sizeof (struct globval));
400 nextlink->next = lastlink;
401 nextname = (char *) malloc (D_NAMLEN (dp) + 1);
402 if (nextname == NULL)
403 {
404 lose = 1;
405 break;
406 }
407 lastlink = nextlink;
408 nextlink->name = nextname;
409 bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
410 ++count;
411 }
412 }
413
414 (void) closedir (d);
415 }
416
417 if (lose == 0)
418 {
419 name_vector = (char **) malloc ((count + 1) * sizeof (char *));
420 lose |= name_vector == NULL;
421 }
422
423 /* Have we run out of memory? */
424 if (lose)
425 {
426 /* Here free the strings we have got. */
427 while (lastlink)
428 {
429 free (lastlink->name);
430 lastlink = lastlink->next;
431 }
432 #if defined (SHELL)
433 if (interrupt_state)
434 throw_to_top_level ();
435 #endif /* SHELL */
436
437 return ((char **)NULL);
438 }
439
440 /* Copy the name pointers from the linked list into the vector. */
441 for (i = 0; i < count; ++i)
442 {
443 name_vector[i] = lastlink->name;
444 lastlink = lastlink->next;
445 }
446
447 name_vector[count] = NULL;
448 return (name_vector);
449 }
450 \f
451 /* Return a new array which is the concatenation of each string in ARRAY
452 to DIR. This function expects you to pass in an allocated ARRAY, and
453 it takes care of free()ing that array. Thus, you might think of this
454 function as side-effecting ARRAY. */
455 static char **
456 glob_dir_to_array (dir, array)
457 char *dir, **array;
458 {
459 register unsigned int i, l;
460 int add_slash;
461 char **result;
462
463 l = strlen (dir);
464 if (l == 0)
465 return (array);
466
467 add_slash = dir[l - 1] != '/';
468
469 i = 0;
470 while (array[i] != NULL)
471 ++i;
472
473 result = (char **) malloc ((i + 1) * sizeof (char *));
474 if (result == NULL)
475 return (NULL);
476
477 for (i = 0; array[i] != NULL; i++)
478 {
479 result[i] = (char *) malloc (l + (add_slash ? 1 : 0)
480 + strlen (array[i]) + 1);
481 if (result[i] == NULL)
482 return (NULL);
483
484 strcpy (result[i], dir);
485 if (add_slash)
486 result[i][l] = '/';
487 strcpy (result[i] + l + add_slash, array[i]);
488 }
489 result[i] = NULL;
490
491 /* Free the input array. */
492 for (i = 0; array[i] != NULL; i++)
493 free (array[i]);
494 free ((char *) array);
495
496 return (result);
497 }
498 \f
499 /* Do globbing on PATHNAME. Return an array of pathnames that match,
500 marking the end of the array with a null-pointer as an element.
501 If no pathnames match, then the array is empty (first element is null).
502 If there isn't enough memory, then return NULL.
503 If a file system error occurs, return -1; `errno' has the error code. */
504 char **
505 glob_filename (pathname)
506 char *pathname;
507 {
508 char **result;
509 unsigned int result_size;
510 char *directory_name, *filename;
511 unsigned int directory_len;
512
513 result = (char **) malloc (sizeof (char *));
514 result_size = 1;
515 if (result == NULL)
516 return (NULL);
517
518 result[0] = NULL;
519
520 /* Find the filename. */
521 filename = strrchr (pathname, '/');
522 if (filename == NULL)
523 {
524 filename = pathname;
525 directory_name = "";
526 directory_len = 0;
527 }
528 else
529 {
530 directory_len = (filename - pathname) + 1;
531 directory_name = (char *) alloca (directory_len + 1);
532
533 bcopy (pathname, directory_name, directory_len);
534 directory_name[directory_len] = '\0';
535 ++filename;
536 }
537
538 /* If directory_name contains globbing characters, then we
539 have to expand the previous levels. Just recurse. */
540 if (glob_pattern_p (directory_name))
541 {
542 char **directories;
543 register unsigned int i;
544
545 if (directory_name[directory_len - 1] == '/')
546 directory_name[directory_len - 1] = '\0';
547
548 directories = glob_filename (directory_name);
549
550 if (directories == NULL)
551 goto memory_error;
552 else if (directories == (char **)&glob_error_return)
553 {
554 free ((char *) result);
555 return ((char **) &glob_error_return);
556 }
557 else if (*directories == NULL)
558 {
559 free ((char *) directories);
560 free ((char *) result);
561 return ((char **) &glob_error_return);
562 }
563
564 /* We have successfully globbed the preceding directory name.
565 For each name in DIRECTORIES, call glob_vector on it and
566 FILENAME. Concatenate the results together. */
567 for (i = 0; directories[i] != NULL; ++i)
568 {
569 char **temp_results;
570
571 /* Scan directory even on a NULL pathname. That way, `*h/'
572 returns only directories ending in `h', instead of all
573 files ending in `h' with a `/' appended. */
574 temp_results = glob_vector (filename, directories[i]);
575
576 /* Handle error cases. */
577 if (temp_results == NULL)
578 goto memory_error;
579 else if (temp_results == (char **)&glob_error_return)
580 /* This filename is probably not a directory. Ignore it. */
581 ;
582 else
583 {
584 char **array;
585 register unsigned int l;
586
587 array = glob_dir_to_array (directories[i], temp_results);
588 l = 0;
589 while (array[l] != NULL)
590 ++l;
591
592 result =
593 (char **)realloc (result, (result_size + l) * sizeof (char *));
594
595 if (result == NULL)
596 goto memory_error;
597
598 for (l = 0; array[l] != NULL; ++l)
599 result[result_size++ - 1] = array[l];
600
601 result[result_size - 1] = NULL;
602
603 /* Note that the elements of ARRAY are not freed. */
604 free ((char *) array);
605 }
606 }
607 /* Free the directories. */
608 for (i = 0; directories[i]; i++)
609 free (directories[i]);
610
611 free ((char *) directories);
612
613 return (result);
614 }
615
616 /* If there is only a directory name, return it. */
617 if (*filename == '\0')
618 {
619 result = (char **) realloc ((char *) result, 2 * sizeof (char *));
620 if (result == NULL)
621 return (NULL);
622 result[0] = (char *) malloc (directory_len + 1);
623 if (result[0] == NULL)
624 goto memory_error;
625 bcopy (directory_name, result[0], directory_len + 1);
626 result[1] = NULL;
627 return (result);
628 }
629 else
630 {
631 char **temp_results;
632
633 /* There are no unquoted globbing characters in DIRECTORY_NAME.
634 Dequote it before we try to open the directory since there may
635 be quoted globbing characters which should be treated verbatim. */
636 if (directory_len > 0)
637 dequote_pathname (directory_name);
638
639 /* We allocated a small array called RESULT, which we won't be using.
640 Free that memory now. */
641 free (result);
642
643 /* Just return what glob_vector () returns appended to the
644 directory name. */
645 temp_results =
646 glob_vector (filename, (directory_len == 0 ? "." : directory_name));
647
648 if (temp_results == NULL || temp_results == (char **)&glob_error_return)
649 return (temp_results);
650
651 return (glob_dir_to_array (directory_name, temp_results));
652 }
653
654 /* We get to memory_error if the program has run out of memory, or
655 if this is the shell, and we have been interrupted. */
656 memory_error:
657 if (result != NULL)
658 {
659 register unsigned int i;
660 for (i = 0; result[i] != NULL; ++i)
661 free (result[i]);
662 free ((char *) result);
663 }
664 #if defined (SHELL)
665 if (interrupt_state)
666 throw_to_top_level ();
667 #endif /* SHELL */
668 return (NULL);
669 }
670 \f
671 #if defined (TEST)
672
673 main (argc, argv)
674 int argc;
675 char **argv;
676 {
677 unsigned int i;
678
679 for (i = 1; i < argc; ++i)
680 {
681 char **value = glob_filename (argv[i]);
682 if (value == NULL)
683 puts ("Out of memory.");
684 else if (value == &glob_error_return)
685 perror (argv[i]);
686 else
687 for (i = 0; value[i] != NULL; i++)
688 puts (value[i]);
689 }
690
691 exit (0);
692 }
693 #endif /* TEST. */