| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* File-name wildcard pattern matching for GNU.
 | 
					
						
							|  |  |  |  |    Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |  |    the Free Software Foundation; either version 2, or (at your option) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |    any later version. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  |    GNU General Public License for more details. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  |    along with this program; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |  |    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.  */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* To whomever it may concern: I have never seen the code which most
 | 
					
						
							|  |  |  |  |    Unix programs use to perform this function.  I wrote this from scratch | 
					
						
							|  |  |  |  |    based on specifications for the pattern matching.  --RMS.  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #include <config.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
 | 
					
						
							|  |  |  |  |   #pragma alloca
 | 
					
						
							|  |  |  |  | #endif /* _AIX && RISC6000 && !__GNUC__ */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  | #  include "bashtypes.h"
 | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | #  include <sys/types.h>
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  | #  include "bashansi.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #  if defined (HAVE_STDLIB_H)
 | 
					
						
							|  |  |  |  | #    include <stdlib.h>
 | 
					
						
							|  |  |  |  | #  endif
 | 
					
						
							|  |  |  |  | #  if defined (HAVE_STRING_H)
 | 
					
						
							|  |  |  |  | #    include <string.h>
 | 
					
						
							|  |  |  |  | #  else /* !HAVE_STRING_H */
 | 
					
						
							|  |  |  |  | #    include <strings.h>
 | 
					
						
							|  |  |  |  | #  endif /* !HAVE_STRING_H */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if defined (HAVE_DIRENT_H)
 | 
					
						
							|  |  |  |  | #  include <dirent.h>
 | 
					
						
							|  |  |  |  | #  define D_NAMLEN(d) strlen ((d)->d_name)
 | 
					
						
							|  |  |  |  | #else /* !HAVE_DIRENT_H */
 | 
					
						
							|  |  |  |  | #  define D_NAMLEN(d) ((d)->d_namlen)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #  if defined (HAVE_SYS_NDIR_H)
 | 
					
						
							|  |  |  |  | #    include <sys/ndir.h>
 | 
					
						
							|  |  |  |  | #  endif
 | 
					
						
							|  |  |  |  | #  if defined (HAVE_SYS_DIR_H)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | #    include <sys/dir.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #  endif /* HAVE_SYS_DIR_H */
 | 
					
						
							|  |  |  |  | #  if defined (HAVE_NDIR_H)
 | 
					
						
							|  |  |  |  | #    include <ndir.h>
 | 
					
						
							|  |  |  |  | #  endif
 | 
					
						
							|  |  |  |  | #  if !defined (dirent)
 | 
					
						
							|  |  |  |  | #    define dirent direct
 | 
					
						
							|  |  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | #endif /* !HAVE_DIRENT_H */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  | #if defined (_POSIX_SOURCE) && !defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* Posix does not require that the d_ino field be present, and some
 | 
					
						
							|  |  |  |  |    systems do not provide it. */ | 
					
						
							|  |  |  |  | #  define REAL_DIR_ENTRY(dp) 1
 | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | #  define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
 | 
					
						
							|  |  |  |  | #endif /* _POSIX_SOURCE */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | #if !defined (HAVE_BCOPY) && !defined (bcopy)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #  define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | #endif /* !HAVE_BCOPY && !bcopy */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  | #  include "posixstat.h"
 | 
					
						
							|  |  |  |  | #else /* !SHELL */
 | 
					
						
							|  |  |  |  | #  include <sys/stat.h>
 | 
					
						
							|  |  |  |  | #endif /* !SHELL */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #include "filecntl.h"
 | 
					
						
							|  |  |  |  | #if !defined (F_OK)
 | 
					
						
							|  |  |  |  | #  define F_OK 0
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  | #  include "memalloc.h"
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  | #include "strmatch.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #if !defined (HAVE_STDLIB_H) && !defined (SHELL)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | extern char *malloc (), *realloc (); | 
					
						
							|  |  |  |  | extern void free (); | 
					
						
							|  |  |  |  | #endif /* !HAVE_STDLIB_H */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if !defined (NULL)
 | 
					
						
							|  |  |  |  | #  if defined (__STDC__)
 | 
					
						
							|  |  |  |  | #    define NULL ((void *) 0)
 | 
					
						
							|  |  |  |  | #  else
 | 
					
						
							|  |  |  |  | #    define NULL 0x0
 | 
					
						
							|  |  |  |  | #  endif /* __STDC__ */
 | 
					
						
							|  |  |  |  | #endif /* !NULL */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if defined (SHELL)
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | extern void throw_to_top_level (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | extern int test_eaccess (); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | extern int interrupt_state; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | extern int extended_glob; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | #endif /* SHELL */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Global variable which controls whether or not * matches .*.
 | 
					
						
							|  |  |  |  |    Non-zero means don't match .*.  */ | 
					
						
							|  |  |  |  | int noglob_dot_filenames = 1; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | /* Global variable which controls whether or not filename globbing
 | 
					
						
							|  |  |  |  |    is done without regard to case. */ | 
					
						
							|  |  |  |  | int glob_ignore_case = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* Global variable to return to signify an error in globbing. */ | 
					
						
							|  |  |  |  | char *glob_error_return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Return nonzero if PATTERN has any special globbing chars in it.  */ | 
					
						
							|  |  |  |  | int | 
					
						
							|  |  |  |  | glob_pattern_p (pattern) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  |      const char *pattern; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  |   register const char *p; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   register char c; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |   int bopen; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   p = pattern; | 
					
						
							|  |  |  |  |   bopen = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   while ((c = *p++) != '\0') | 
					
						
							|  |  |  |  |     switch (c) | 
					
						
							|  |  |  |  |       { | 
					
						
							|  |  |  |  |       case '?': | 
					
						
							|  |  |  |  |       case '*': | 
					
						
							|  |  |  |  | 	return (1); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       case '[':		/* Only accept an open brace if there is a close */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	bopen++;	/* brace to match it.  Bracket expressions must be */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	continue;	/* complete, according to Posix.2 */ | 
					
						
							|  |  |  |  |       case ']': | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	if (bopen) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	  return (1); | 
					
						
							|  |  |  |  | 	continue;       | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       case '+':		/* extended matching operators */ | 
					
						
							|  |  |  |  |       case '@': | 
					
						
							|  |  |  |  |       case '!': | 
					
						
							|  |  |  |  | 	if (*p == '(')	/*) */ | 
					
						
							|  |  |  |  | 	  return (1); | 
					
						
							|  |  |  |  | 	continue; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |       case '\\': | 
					
						
							|  |  |  |  | 	if (*p++ == '\0') | 
					
						
							|  |  |  |  | 	  return (0); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return (0); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */ | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | dequote_pathname (pathname) | 
					
						
							|  |  |  |  |      char *pathname; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   register int i, j; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (i = j = 0; pathname && pathname[i]; ) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (pathname[i] == '\\') | 
					
						
							|  |  |  |  | 	i++; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       pathname[j++] = pathname[i++]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (!pathname[i - 1]) | 
					
						
							|  |  |  |  | 	break; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   pathname[j] = '\0'; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Test whether NAME exists. */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if defined (HAVE_LSTAT)
 | 
					
						
							|  |  |  |  | #  define GLOB_TESTNAME(name)  (lstat (name, &finfo))
 | 
					
						
							|  |  |  |  | #else /* !HAVE_LSTAT */
 | 
					
						
							|  |  |  |  | #  if defined (SHELL) && !defined (AFS)
 | 
					
						
							|  |  |  |  | #    define GLOB_TESTNAME(name)  (test_eaccess (nextname, F_OK))
 | 
					
						
							|  |  |  |  | #  else /* !SHELL || AFS */
 | 
					
						
							|  |  |  |  | #    define GLOB_TESTNAME(name)  (access (nextname, F_OK))
 | 
					
						
							|  |  |  |  | #  endif /* !SHELL || AFS */
 | 
					
						
							|  |  |  |  | #endif /* !HAVE_LSTAT */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Return 0 if DIR is a directory, -1 otherwise. */ | 
					
						
							|  |  |  |  | static int | 
					
						
							|  |  |  |  | glob_testdir (dir) | 
					
						
							|  |  |  |  |      char *dir; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   struct stat finfo; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (stat (dir, &finfo) < 0) | 
					
						
							|  |  |  |  |     return (-1); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (S_ISDIR (finfo.st_mode) == 0) | 
					
						
							|  |  |  |  |     return (-1); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return (0); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* Return a vector of names of files in directory DIR
 | 
					
						
							|  |  |  |  |    whose names match glob pattern PAT. | 
					
						
							|  |  |  |  |    The names are not in any particular order. | 
					
						
							|  |  |  |  |    Wildcards at the beginning of PAT do not match an initial period. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    The vector is terminated by an element that is a null pointer. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    To free the space allocated, first free the vector's elements, | 
					
						
							|  |  |  |  |    then free the vector. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    Return 0 if cannot get enough memory to hold the pointer | 
					
						
							|  |  |  |  |    and the names. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    Return -1 if cannot access directory DIR. | 
					
						
							|  |  |  |  |    Look in errno for more information.  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | char ** | 
					
						
							|  |  |  |  | glob_vector (pat, dir) | 
					
						
							|  |  |  |  |      char *pat; | 
					
						
							|  |  |  |  |      char *dir; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   struct globval | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       struct globval *next; | 
					
						
							|  |  |  |  |       char *name; | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   DIR *d; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |   register struct dirent *dp; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   struct globval *lastlink; | 
					
						
							|  |  |  |  |   register struct globval *nextlink; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  |   register char *nextname, *npat; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   unsigned int count; | 
					
						
							|  |  |  |  |   int lose, skip; | 
					
						
							|  |  |  |  |   register char **name_vector; | 
					
						
							|  |  |  |  |   register unsigned int i; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  |   int flags;		/* Flags passed to strmatch (). */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   lastlink = 0; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |   count = lose = skip = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* If PAT is empty, skip the loop, but return one (empty) filename. */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |   if (pat == 0 || *pat == '\0') | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       if (glob_testdir (dir) < 0) | 
					
						
							|  |  |  |  | 	return ((char **) &glob_error_return); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |       nextlink = (struct globval *)alloca (sizeof (struct globval)); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       nextlink->next = (struct globval *)0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |       nextname = (char *) malloc (1); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       if (nextname == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	lose = 1; | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  lastlink = nextlink; | 
					
						
							|  |  |  |  | 	  nextlink->name = nextname; | 
					
						
							|  |  |  |  | 	  nextname[0] = '\0'; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	  count = 1; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |       skip = 1; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |   /* If the filename pattern (PAT) does not contain any globbing characters,
 | 
					
						
							|  |  |  |  |      we can dispense with reading the directory, and just see if there is | 
					
						
							|  |  |  |  |      a filename `DIR/PAT'.  If there is, and we can access it, just make the | 
					
						
							|  |  |  |  |      vector to return and bail immediately. */ | 
					
						
							|  |  |  |  |   if (skip == 0 && glob_pattern_p (pat) == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       int dirlen; | 
					
						
							|  |  |  |  |       struct stat finfo; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (glob_testdir (dir) < 0) | 
					
						
							|  |  |  |  | 	return ((char **) &glob_error_return); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       dirlen = strlen (dir); | 
					
						
							|  |  |  |  |       nextname = (char *)malloc (dirlen + strlen (pat) + 2); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  |       npat = (char *)malloc (strlen (pat) + 1); | 
					
						
							|  |  |  |  |       if (nextname == 0 || npat == 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	lose = 1; | 
					
						
							|  |  |  |  |       else | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | 	  strcpy (npat, pat); | 
					
						
							|  |  |  |  | 	  dequote_pathname (npat); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	  strcpy (nextname, dir); | 
					
						
							|  |  |  |  | 	  nextname[dirlen++] = '/'; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | 	  strcpy (nextname + dirlen, npat); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	  if (GLOB_TESTNAME (nextname) >= 0) | 
					
						
							|  |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      free (nextname); | 
					
						
							|  |  |  |  | 	      nextlink = (struct globval *)alloca (sizeof (struct globval)); | 
					
						
							|  |  |  |  | 	      nextlink->next = (struct globval *)0; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | 	      lastlink = nextlink; | 
					
						
							|  |  |  |  | 	      nextlink->name = npat; | 
					
						
							|  |  |  |  | 	      count = 1; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	    } | 
					
						
							|  |  |  |  | 	  else | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      free (nextname); | 
					
						
							|  |  |  |  | 	      free (npat); | 
					
						
							|  |  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       skip = 1; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |   if (skip == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       /* Open the directory, punting immediately if we cannot.  If opendir
 | 
					
						
							|  |  |  |  | 	 is not robust (i.e., it opens non-directories successfully), test | 
					
						
							|  |  |  |  | 	 that DIR is a directory and punt if it's not. */ | 
					
						
							|  |  |  |  | #if defined (OPENDIR_NOT_ROBUST)
 | 
					
						
							|  |  |  |  |       if (glob_testdir (dir) < 0) | 
					
						
							|  |  |  |  | 	return ((char **) &glob_error_return); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |       d = opendir (dir); | 
					
						
							|  |  |  |  |       if (d == NULL) | 
					
						
							|  |  |  |  | 	return ((char **) &glob_error_return); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  |       /* Compute the flags that will be passed to strmatch().  We don't
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |  | 	 need to do this every time through the loop. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |       flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #ifdef FNM_CASEFOLD
 | 
					
						
							|  |  |  |  |       if (glob_ignore_case) | 
					
						
							|  |  |  |  | 	flags |= FNM_CASEFOLD; | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #ifdef SHELL
 | 
					
						
							|  |  |  |  |       if (extended_glob) | 
					
						
							|  |  |  |  | 	flags |= FNM_EXTMATCH; | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Scan the directory, finding all names that match.
 | 
					
						
							|  |  |  |  | 	 For each name that matches, allocate a struct globval | 
					
						
							|  |  |  |  | 	 on the stack and store the name in it. | 
					
						
							|  |  |  |  | 	 Chain those structs together; lastlink is the front of the chain.  */ | 
					
						
							|  |  |  |  |       while (1) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  | 	  /* Make globbing interruptible in the shell. */ | 
					
						
							|  |  |  |  | 	  if (interrupt_state) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      lose = 1; | 
					
						
							|  |  |  |  | 	      break; | 
					
						
							|  |  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #endif /* SHELL */
 | 
					
						
							|  |  |  |  | 	   | 
					
						
							|  |  |  |  | 	  dp = readdir (d); | 
					
						
							|  |  |  |  | 	  if (dp == NULL) | 
					
						
							|  |  |  |  | 	    break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	  /* If this directory entry is not to be used, try again. */ | 
					
						
							|  |  |  |  | 	  if (REAL_DIR_ENTRY (dp) == 0) | 
					
						
							|  |  |  |  | 	    continue; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |  | 	  /* If a leading dot need not be explicitly matched, and the pattern
 | 
					
						
							|  |  |  |  | 	     doesn't start with a `.', don't match `.' or `..' */ | 
					
						
							|  |  |  |  | #define dname dp->d_name
 | 
					
						
							|  |  |  |  | 	  if (noglob_dot_filenames == 0 && pat[0] != '.' && | 
					
						
							|  |  |  |  | 		(pat[0] != '\\' || pat[1] != '.') && | 
					
						
							|  |  |  |  | 		(dname[0] == '.' && | 
					
						
							|  |  |  |  | 		  (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0')))) | 
					
						
							|  |  |  |  | #undef dname
 | 
					
						
							|  |  |  |  | 	    continue; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	  /* If a dot must be explicity matched, check to see if they do. */ | 
					
						
							|  |  |  |  | 	  if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' && | 
					
						
							|  |  |  |  | 		(pat[0] != '\\' || pat[1] != '.')) | 
					
						
							|  |  |  |  | 	    continue; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |  | 	  if (strmatch (pat, dp->d_name, flags) != FNM_NOMATCH) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      nextlink = (struct globval *) alloca (sizeof (struct globval)); | 
					
						
							|  |  |  |  | 	      nextlink->next = lastlink; | 
					
						
							|  |  |  |  | 	      nextname = (char *) malloc (D_NAMLEN (dp) + 1); | 
					
						
							|  |  |  |  | 	      if (nextname == NULL) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		  lose = 1; | 
					
						
							|  |  |  |  | 		  break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	      lastlink = nextlink; | 
					
						
							|  |  |  |  | 	      nextlink->name = nextname; | 
					
						
							|  |  |  |  | 	      bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1); | 
					
						
							|  |  |  |  | 	      ++count; | 
					
						
							|  |  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       (void) closedir (d); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  |   if (lose == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       name_vector = (char **) malloc ((count + 1) * sizeof (char *)); | 
					
						
							|  |  |  |  |       lose |= name_vector == NULL; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Have we run out of memory?	 */ | 
					
						
							|  |  |  |  |   if (lose) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       /* Here free the strings we have got.  */ | 
					
						
							|  |  |  |  |       while (lastlink) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  free (lastlink->name); | 
					
						
							|  |  |  |  | 	  lastlink = lastlink->next; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  |       if (interrupt_state) | 
					
						
							|  |  |  |  | 	throw_to_top_level (); | 
					
						
							|  |  |  |  | #endif /* SHELL */
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       return ((char **)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Copy the name pointers from the linked list into the vector.  */ | 
					
						
							|  |  |  |  |   for (i = 0; i < count; ++i) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       name_vector[i] = lastlink->name; | 
					
						
							|  |  |  |  |       lastlink = lastlink->next; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   name_vector[count] = NULL; | 
					
						
							|  |  |  |  |   return (name_vector); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  |  | 
					
						
							|  |  |  |  | /* Return a new array which is the concatenation of each string in ARRAY
 | 
					
						
							|  |  |  |  |    to DIR.  This function expects you to pass in an allocated ARRAY, and | 
					
						
							|  |  |  |  |    it takes care of free()ing that array.  Thus, you might think of this | 
					
						
							|  |  |  |  |    function as side-effecting ARRAY. */ | 
					
						
							|  |  |  |  | static char ** | 
					
						
							|  |  |  |  | glob_dir_to_array (dir, array) | 
					
						
							|  |  |  |  |      char *dir, **array; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   register unsigned int i, l; | 
					
						
							|  |  |  |  |   int add_slash; | 
					
						
							|  |  |  |  |   char **result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   l = strlen (dir); | 
					
						
							|  |  |  |  |   if (l == 0) | 
					
						
							|  |  |  |  |     return (array); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   add_slash = dir[l - 1] != '/'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   i = 0; | 
					
						
							|  |  |  |  |   while (array[i] != NULL) | 
					
						
							|  |  |  |  |     ++i; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   result = (char **) malloc ((i + 1) * sizeof (char *)); | 
					
						
							|  |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     return (NULL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (i = 0; array[i] != NULL; i++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       result[i] = (char *) malloc (l + (add_slash ? 1 : 0) | 
					
						
							|  |  |  |  | 				   + strlen (array[i]) + 1); | 
					
						
							|  |  |  |  |       if (result[i] == NULL) | 
					
						
							|  |  |  |  | 	return (NULL); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |       strcpy (result[i], dir); | 
					
						
							|  |  |  |  |       if (add_slash) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |  | 	result[i][l] = '/'; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |       strcpy (result[i] + l + add_slash, array[i]); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   result[i] = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Free the input array.  */ | 
					
						
							|  |  |  |  |   for (i = 0; array[i] != NULL; i++) | 
					
						
							|  |  |  |  |     free (array[i]); | 
					
						
							|  |  |  |  |   free ((char *) array); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return (result); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  |  | 
					
						
							|  |  |  |  | /* Do globbing on PATHNAME.  Return an array of pathnames that match,
 | 
					
						
							|  |  |  |  |    marking the end of the array with a null-pointer as an element. | 
					
						
							|  |  |  |  |    If no pathnames match, then the array is empty (first element is null). | 
					
						
							|  |  |  |  |    If there isn't enough memory, then return NULL. | 
					
						
							|  |  |  |  |    If a file system error occurs, return -1; `errno' has the error code.  */ | 
					
						
							|  |  |  |  | char ** | 
					
						
							|  |  |  |  | glob_filename (pathname) | 
					
						
							|  |  |  |  |      char *pathname; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   char **result; | 
					
						
							|  |  |  |  |   unsigned int result_size; | 
					
						
							|  |  |  |  |   char *directory_name, *filename; | 
					
						
							|  |  |  |  |   unsigned int directory_len; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   result = (char **) malloc (sizeof (char *)); | 
					
						
							|  |  |  |  |   result_size = 1; | 
					
						
							|  |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     return (NULL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   result[0] = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Find the filename.  */ | 
					
						
							|  |  |  |  |   filename = strrchr (pathname, '/'); | 
					
						
							|  |  |  |  |   if (filename == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       filename = pathname; | 
					
						
							|  |  |  |  |       directory_name = ""; | 
					
						
							|  |  |  |  |       directory_len = 0; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       directory_len = (filename - pathname) + 1; | 
					
						
							|  |  |  |  |       directory_name = (char *) alloca (directory_len + 1); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       bcopy (pathname, directory_name, directory_len); | 
					
						
							|  |  |  |  |       directory_name[directory_len] = '\0'; | 
					
						
							|  |  |  |  |       ++filename; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* If directory_name contains globbing characters, then we
 | 
					
						
							|  |  |  |  |      have to expand the previous levels.  Just recurse. */ | 
					
						
							|  |  |  |  |   if (glob_pattern_p (directory_name)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       char **directories; | 
					
						
							|  |  |  |  |       register unsigned int i; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (directory_name[directory_len - 1] == '/') | 
					
						
							|  |  |  |  | 	directory_name[directory_len - 1] = '\0'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       directories = glob_filename (directory_name); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (directories == NULL) | 
					
						
							|  |  |  |  | 	goto memory_error; | 
					
						
							|  |  |  |  |       else if (directories == (char **)&glob_error_return) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 	  free ((char *) result); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	  return ((char **) &glob_error_return); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  |       else if (*directories == NULL) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  free ((char *) directories); | 
					
						
							|  |  |  |  | 	  free ((char *) result); | 
					
						
							|  |  |  |  | 	  return ((char **) &glob_error_return); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* We have successfully globbed the preceding directory name.
 | 
					
						
							|  |  |  |  | 	 For each name in DIRECTORIES, call glob_vector on it and | 
					
						
							|  |  |  |  | 	 FILENAME.  Concatenate the results together.  */ | 
					
						
							|  |  |  |  |       for (i = 0; directories[i] != NULL; ++i) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  char **temp_results; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	  /* Scan directory even on a NULL pathname.  That way, `*h/'
 | 
					
						
							|  |  |  |  | 	     returns only directories ending in `h', instead of all | 
					
						
							|  |  |  |  | 	     files ending in `h' with a `/' appended. */ | 
					
						
							|  |  |  |  | 	  temp_results = glob_vector (filename, directories[i]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	  /* Handle error cases. */ | 
					
						
							|  |  |  |  | 	  if (temp_results == NULL) | 
					
						
							|  |  |  |  | 	    goto memory_error; | 
					
						
							|  |  |  |  | 	  else if (temp_results == (char **)&glob_error_return) | 
					
						
							|  |  |  |  | 	    /* This filename is probably not a directory.  Ignore it.  */ | 
					
						
							|  |  |  |  | 	    ; | 
					
						
							|  |  |  |  | 	  else | 
					
						
							|  |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      char **array; | 
					
						
							|  |  |  |  | 	      register unsigned int l; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	      array = glob_dir_to_array (directories[i], temp_results); | 
					
						
							|  |  |  |  | 	      l = 0; | 
					
						
							|  |  |  |  | 	      while (array[l] != NULL) | 
					
						
							|  |  |  |  | 		++l; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	      result = | 
					
						
							|  |  |  |  | 		(char **)realloc (result, (result_size + l) * sizeof (char *)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	      if (result == NULL) | 
					
						
							|  |  |  |  | 		goto memory_error; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	      for (l = 0; array[l] != NULL; ++l) | 
					
						
							|  |  |  |  | 		result[result_size++ - 1] = array[l]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	      result[result_size - 1] = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	      /* Note that the elements of ARRAY are not freed.  */ | 
					
						
							|  |  |  |  | 	      free ((char *) array); | 
					
						
							|  |  |  |  | 	    } | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  |       /* Free the directories.  */ | 
					
						
							|  |  |  |  |       for (i = 0; directories[i]; i++) | 
					
						
							|  |  |  |  | 	free (directories[i]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       free ((char *) directories); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       return (result); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* If there is only a directory name, return it. */ | 
					
						
							|  |  |  |  |   if (*filename == '\0') | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       result = (char **) realloc ((char *) result, 2 * sizeof (char *)); | 
					
						
							|  |  |  |  |       if (result == NULL) | 
					
						
							|  |  |  |  | 	return (NULL); | 
					
						
							|  |  |  |  |       result[0] = (char *) malloc (directory_len + 1); | 
					
						
							|  |  |  |  |       if (result[0] == NULL) | 
					
						
							|  |  |  |  | 	goto memory_error; | 
					
						
							|  |  |  |  |       bcopy (directory_name, result[0], directory_len + 1); | 
					
						
							|  |  |  |  |       result[1] = NULL; | 
					
						
							|  |  |  |  |       return (result); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       char **temp_results; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* There are no unquoted globbing characters in DIRECTORY_NAME.
 | 
					
						
							|  |  |  |  | 	 Dequote it before we try to open the directory since there may | 
					
						
							|  |  |  |  | 	 be quoted globbing characters which should be treated verbatim. */ | 
					
						
							|  |  |  |  |       if (directory_len > 0) | 
					
						
							|  |  |  |  | 	dequote_pathname (directory_name); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* We allocated a small array called RESULT, which we won't be using.
 | 
					
						
							|  |  |  |  | 	 Free that memory now. */ | 
					
						
							|  |  |  |  |       free (result); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Just return what glob_vector () returns appended to the
 | 
					
						
							|  |  |  |  | 	 directory name. */ | 
					
						
							|  |  |  |  |       temp_results = | 
					
						
							|  |  |  |  | 	glob_vector (filename, (directory_len == 0 ? "." : directory_name)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (temp_results == NULL || temp_results == (char **)&glob_error_return) | 
					
						
							|  |  |  |  | 	return (temp_results); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       return (glob_dir_to_array (directory_name, temp_results)); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* We get to memory_error if the program has run out of memory, or
 | 
					
						
							|  |  |  |  |      if this is the shell, and we have been interrupted. */ | 
					
						
							|  |  |  |  |  memory_error: | 
					
						
							|  |  |  |  |   if (result != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       register unsigned int i; | 
					
						
							|  |  |  |  |       for (i = 0; result[i] != NULL; ++i) | 
					
						
							|  |  |  |  | 	free (result[i]); | 
					
						
							|  |  |  |  |       free ((char *) result); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | #if defined (SHELL)
 | 
					
						
							|  |  |  |  |   if (interrupt_state) | 
					
						
							|  |  |  |  |     throw_to_top_level (); | 
					
						
							|  |  |  |  | #endif /* SHELL */
 | 
					
						
							|  |  |  |  |   return (NULL); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  |  | 
					
						
							|  |  |  |  | #if defined (TEST)
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | main (argc, argv) | 
					
						
							|  |  |  |  |      int argc; | 
					
						
							|  |  |  |  |      char **argv; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   unsigned int i; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (i = 1; i < argc; ++i) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       char **value = glob_filename (argv[i]); | 
					
						
							|  |  |  |  |       if (value == NULL) | 
					
						
							|  |  |  |  | 	puts ("Out of memory."); | 
					
						
							|  |  |  |  |       else if (value == &glob_error_return) | 
					
						
							|  |  |  |  | 	perror (argv[i]); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  | 	for (i = 0; value[i] != NULL; i++) | 
					
						
							|  |  |  |  | 	  puts (value[i]); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   exit (0); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | #endif	/* TEST.  */
 |