| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* glob.c -- file-name wildcard pattern matching for Bash.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Copyright (C) 1985-2009 Free Software Foundation, Inc. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    This file is part of GNU Bash, the Bourne-Again SHell. | 
					
						
							|  |  |  |     | 
					
						
							|  |  |  |    Bash is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |    (at your option) any later version. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    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 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											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__ */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #include "bashtypes.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #include "bashansi.h"
 | 
					
						
							|  |  |  | #include "posixdir.h"
 | 
					
						
							|  |  |  | #include "posixstat.h"
 | 
					
						
							|  |  |  | #include "shmbutil.h"
 | 
					
						
							|  |  |  | #include "xmalloc.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "filecntl.h"
 | 
					
						
							|  |  |  | #if !defined (F_OK)
 | 
					
						
							|  |  |  | #  define F_OK 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #include "stdc.h"
 | 
					
						
							|  |  |  | #include "memalloc.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #include "shell.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #include "glob.h"
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "strmatch.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if !defined (HAVE_BCOPY) && !defined (bcopy)
 | 
					
						
							|  |  |  | #  define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
 | 
					
						
							|  |  |  | #endif /* !HAVE_BCOPY && !bcopy */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if !defined (NULL)
 | 
					
						
							|  |  |  | #  if defined (__STDC__)
 | 
					
						
							|  |  |  | #    define NULL ((void *) 0)
 | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | #    define NULL 0x0
 | 
					
						
							|  |  |  | #  endif /* __STDC__ */
 | 
					
						
							|  |  |  | #endif /* !NULL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if !defined (FREE)
 | 
					
						
							|  |  |  | #  define FREE(x)	if (x) free (x)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | /* Don't try to alloca() more than this much memory for `struct globval'
 | 
					
						
							|  |  |  |    in glob_vector() */ | 
					
						
							|  |  |  | #ifndef ALLOCA_MAX
 | 
					
						
							|  |  |  | #  define ALLOCA_MAX	100000
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | struct globval | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     struct globval *next; | 
					
						
							|  |  |  |     char *name; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | extern void throw_to_top_level __P((void)); | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | extern int sh_eaccess __P((char *, int)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | extern char *sh_makepath __P((const char *, const char *, int)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | extern int signal_is_pending __P((int)); | 
					
						
							|  |  |  | extern void run_pending_traps __P((void)); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | extern int extended_glob; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static struct globval finddirs_error_return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Some forward declarations. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static int skipname __P((char *, char *, int)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static int mbskipname __P((char *, char *, int)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							|  |  |  | static void udequote_pathname __P((char *)); | 
					
						
							|  |  |  | static void wdequote_pathname __P((char *)); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  define dequote_pathname udequote_pathname
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | static void dequote_pathname __P((char *)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static int glob_testdir __P((char *, int)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static char **glob_dir_to_array __P((char *, char **, int)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Make sure these names continue to agree with what's in smatch.c */ | 
					
						
							|  |  |  | extern char *glob_patscan __P((char *, char *, int)); | 
					
						
							|  |  |  | extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Compile `glob_loop.c' for single-byte characters. */ | 
					
						
							|  |  |  | #define CHAR	unsigned char
 | 
					
						
							|  |  |  | #define INT	int
 | 
					
						
							|  |  |  | #define L(CS)	CS
 | 
					
						
							|  |  |  | #define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p
 | 
					
						
							|  |  |  | #include "glob_loop.c"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Compile `glob_loop.c' again for multibyte characters. */ | 
					
						
							|  |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CHAR	wchar_t
 | 
					
						
							|  |  |  | #define INT	wint_t
 | 
					
						
							|  |  |  | #define L(CS)	L##CS
 | 
					
						
							|  |  |  | #define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p
 | 
					
						
							|  |  |  | #include "glob_loop.c"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* HANDLE_MULTIBYTE */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* And now a function that calls either the single-byte or multibyte version
 | 
					
						
							|  |  |  |    of internal_glob_pattern_p. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int | 
					
						
							|  |  |  | glob_pattern_p (pattern) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *pattern; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							|  |  |  |   size_t n; | 
					
						
							|  |  |  |   wchar_t *wpattern; | 
					
						
							|  |  |  |   int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (MB_CUR_MAX == 1) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     return (internal_glob_pattern_p ((unsigned char *)pattern)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Convert strings to wide chars, and call the multibyte version. */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   n = xdupmbstowcs (&wpattern, NULL, pattern); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (n == (size_t)-1) | 
					
						
							|  |  |  |     /* Oops.  Invalid multibyte sequence.  Try it as single-byte sequence. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     return (internal_glob_pattern_p ((unsigned char *)pattern)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   r = internal_glob_wpattern_p (wpattern); | 
					
						
							|  |  |  |   free (wpattern); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return r; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   return (internal_glob_pattern_p (pattern)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if EXTENDED_GLOB
 | 
					
						
							|  |  |  | /* Return 1 if all subpatterns in the extended globbing pattern PAT indicate
 | 
					
						
							|  |  |  |    that the name should be skipped.  XXX - doesn't handle pattern negation, | 
					
						
							|  |  |  |    not sure if it should */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | extglob_skipname (pat, dname, flags) | 
					
						
							|  |  |  |      char *pat, *dname; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   char *pp, *pe, *t, *se; | 
					
						
							|  |  |  |   int n, r, negate; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   negate = *pat == '!'; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   pp = pat + 2; | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   se = pp + strlen (pp) - 1;		/* end of string */ | 
					
						
							|  |  |  |   pe = glob_patscan (pp, se, 0);	/* end of extglob pattern (( */ | 
					
						
							|  |  |  |   /* we should check for invalid extglob pattern here */ | 
					
						
							|  |  |  |   /* if pe != se we have more of the pattern at the end of the extglob
 | 
					
						
							|  |  |  |      pattern. Check the easy case first ( */ | 
					
						
							|  |  |  |   if (pe == se && *pe == ')' && (t = strchr (pp, '|')) == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |       *pe = '\0'; | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |       r = mbskipname (pp, dname, flags); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       r = skipname (pp, dname, flags);	/*(*/ | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       *pe = ')'; | 
					
						
							|  |  |  |       return r; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* check every subpattern */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   while (t = glob_patscan (pp, pe, '|')) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       n = t[-1]; | 
					
						
							|  |  |  |       t[-1] = '\0'; | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |       r = mbskipname (pp, dname, flags); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       r = skipname (pp, dname, flags); | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       t[-1] = n; | 
					
						
							|  |  |  |       if (r == 0)	/* if any pattern says not skip, we don't skip */ | 
					
						
							|  |  |  |         return r; | 
					
						
							|  |  |  |       pp = t; | 
					
						
							|  |  |  |     }	/*(*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   /* glob_patscan might find end of pattern */ | 
					
						
							|  |  |  |   if (pp == se) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     return r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   /* but if it doesn't then we didn't match a leading dot */ | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Return 1 if DNAME should be skipped according to PAT.  Mostly concerned
 | 
					
						
							|  |  |  |    with matching leading `.'. */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | skipname (pat, dname, flags) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      char *pat; | 
					
						
							|  |  |  |      char *dname; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if EXTENDED_GLOB
 | 
					
						
							|  |  |  |   if (extglob_pattern_p (pat))		/* XXX */ | 
					
						
							|  |  |  |     return (extglob_skipname (pat, dname, flags)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   /* If a leading dot need not be explicitly matched, and the pattern
 | 
					
						
							|  |  |  |      doesn't start with a `.', don't match `.' or `..' */ | 
					
						
							|  |  |  |   if (noglob_dot_filenames == 0 && pat[0] != '.' && | 
					
						
							|  |  |  | 	(pat[0] != '\\' || pat[1] != '.') && | 
					
						
							|  |  |  | 	(dname[0] == '.' && | 
					
						
							|  |  |  | 	  (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0')))) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   /* If a dot must be explicitly matched, check to see if they do. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' && | 
					
						
							|  |  |  | 	(pat[0] != '\\' || pat[1] != '.')) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | wchkname (pat_wc, dn_wc) | 
					
						
							|  |  |  |      wchar_t *pat_wc, *dn_wc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* If a leading dot need not be explicitly matched, and the
 | 
					
						
							|  |  |  |      pattern doesn't start with a `.', don't match `.' or `..' */ | 
					
						
							|  |  |  |   if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' && | 
					
						
							|  |  |  | 	(pat_wc[0] != L'\\' || pat_wc[1] != L'.') && | 
					
						
							|  |  |  | 	(dn_wc[0] == L'.' && | 
					
						
							|  |  |  | 	  (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0')))) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If a leading dot must be explicitly matched, check to see if the
 | 
					
						
							|  |  |  |      pattern and dirname both have one. */ | 
					
						
							|  |  |  |  else if (noglob_dot_filenames && dn_wc[0] == L'.' && | 
					
						
							|  |  |  | 	pat_wc[0] != L'.' && | 
					
						
							|  |  |  | 	   (pat_wc[0] != L'\\' || pat_wc[1] != L'.')) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | wextglob_skipname (pat, dname, flags) | 
					
						
							|  |  |  |      wchar_t *pat, *dname; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if EXTENDED_GLOB
 | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   wchar_t *pp, *pe, *t, n, *se; | 
					
						
							|  |  |  |   int r, negate; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   negate = *pat == L'!'; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   pp = pat + 2; | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   se = pp + wcslen (pp) - 1;	/*(*/ | 
					
						
							|  |  |  |   pe = glob_patscan_wc (pp, se, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (pe == se && *pe == ')' && (t = wcschr (pp, L'|')) == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |       *pe = L'\0'; | 
					
						
							|  |  |  |       r = wchkname (pp, dname); /*(*/ | 
					
						
							|  |  |  |       *pe = L')'; | 
					
						
							|  |  |  |       return r; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* check every subpattern */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   while (t = glob_patscan_wc (pp, pe, '|')) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       n = t[-1]; | 
					
						
							|  |  |  |       t[-1] = L'\0'; | 
					
						
							|  |  |  |       r = wchkname (pp, dname); | 
					
						
							|  |  |  |       t[-1] = n; | 
					
						
							|  |  |  |       if (r == 0) | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  |       pp = t; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (pp == pe)		/* glob_patscan_wc might find end of pattern */ | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-28 11:54:45 -04:00
										 |  |  |   /* but if it doesn't then we didn't match a leading dot */ | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   return (wchkname (pat, dname)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Return 1 if DNAME should be skipped according to PAT.  Handles multibyte
 | 
					
						
							|  |  |  |    characters in PAT and DNAME.  Mostly concerned with matching leading `.'. */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | mbskipname (pat, dname, flags) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      char *pat, *dname; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int ret, ext; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   wchar_t *pat_wc, *dn_wc; | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   size_t pat_n, dn_n; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (mbsmbchar (dname) == 0 && mbsmbchar (pat) == 0) | 
					
						
							|  |  |  |     return (skipname (pat, dname, flags)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ext = 0; | 
					
						
							|  |  |  | #if EXTENDED_GLOB
 | 
					
						
							|  |  |  |   ext = extglob_pattern_p (pat); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-10 09:43:39 -04:00
										 |  |  |   pat_wc = dn_wc = (wchar_t *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   pat_n = xdupmbstowcs (&pat_wc, NULL, pat); | 
					
						
							| 
									
										
										
										
											2012-07-10 09:43:39 -04:00
										 |  |  |   if (pat_n != (size_t)-1) | 
					
						
							|  |  |  |     dn_n = xdupmbstowcs (&dn_wc, NULL, dname); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   ret = 0; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (pat_n != (size_t)-1 && dn_n !=(size_t)-1) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wchkname (pat_wc, dn_wc); | 
					
						
							| 
									
										
										
										
											2012-07-10 09:43:39 -04:00
										 |  |  |   else | 
					
						
							|  |  |  |     ret = skipname (pat, dname, flags); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   FREE (pat_wc); | 
					
						
							|  |  |  |   FREE (dn_wc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ret; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif /* HANDLE_MULTIBYTE */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */ | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | udequote_pathname (pathname) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *pathname; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i, j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = j = 0; pathname && pathname[i]; ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (pathname[i] == '\\') | 
					
						
							|  |  |  | 	i++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       pathname[j++] = pathname[i++]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (pathname[i - 1] == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   if (pathname) | 
					
						
							|  |  |  |     pathname[j] = '\0'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							|  |  |  | /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | wdequote_pathname (pathname) | 
					
						
							|  |  |  |      char *pathname; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   mbstate_t ps; | 
					
						
							|  |  |  |   size_t len, n; | 
					
						
							|  |  |  |   wchar_t *wpathname; | 
					
						
							|  |  |  |   int i, j; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   wchar_t *orig_wpathname; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   len = strlen (pathname); | 
					
						
							|  |  |  |   /* Convert the strings into wide characters.  */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   n = xdupmbstowcs (&wpathname, NULL, pathname); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (n == (size_t) -1) | 
					
						
							| 
									
										
										
										
											2012-07-10 09:43:39 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |       /* Something wrong.  Fall back to single-byte */ | 
					
						
							|  |  |  |       udequote_pathname (pathname); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   orig_wpathname = wpathname; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (i = j = 0; wpathname && wpathname[i]; ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (wpathname[i] == L'\\') | 
					
						
							|  |  |  | 	i++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       wpathname[j++] = wpathname[i++]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (wpathname[i - 1] == L'\0') | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   if (wpathname) | 
					
						
							|  |  |  |     wpathname[j] = L'\0'; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Convert the wide character string into unibyte character set. */ | 
					
						
							|  |  |  |   memset (&ps, '\0', sizeof(mbstate_t)); | 
					
						
							|  |  |  |   n = wcsrtombs(pathname, (const wchar_t **)&wpathname, len, &ps); | 
					
						
							|  |  |  |   pathname[len] = '\0'; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Can't just free wpathname here; wcsrtombs changes it in many cases. */ | 
					
						
							|  |  |  |   free (orig_wpathname); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | dequote_pathname (pathname) | 
					
						
							|  |  |  |      char *pathname; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (MB_CUR_MAX > 1) | 
					
						
							|  |  |  |     wdequote_pathname (pathname); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     udequote_pathname (pathname); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* HANDLE_MULTIBYTE */
 | 
					
						
							| 
									
										
										
										
											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 */
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #  if !defined (AFS)
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #    define GLOB_TESTNAME(name)  (sh_eaccess (name, F_OK))
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #  else /* AFS */
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #    define GLOB_TESTNAME(name)  (access (name, F_OK))
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #  endif /* AFS */
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif /* !HAVE_LSTAT */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return 0 if DIR is a directory, -1 otherwise. */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | glob_testdir (dir, flags) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |      char *dir; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   struct stat finfo; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int r; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /*itrace("glob_testdir: testing %s" flags = %d, dir, flags);*/ | 
					
						
							|  |  |  | #if defined (HAVE_LSTAT)
 | 
					
						
							|  |  |  |   r = (flags & GX_ALLDIRS) ? lstat (dir, &finfo) : stat (dir, &finfo); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   r = stat (dir, &finfo); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   if (r < 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     return (-1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (S_ISDIR (finfo.st_mode) == 0) | 
					
						
							|  |  |  |     return (-1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Recursively scan SDIR for directories matching PAT (PAT is always `**').
 | 
					
						
							|  |  |  |    FLAGS is simply passed down to the recursive call to glob_vector.  Returns | 
					
						
							|  |  |  |    a list of matching directory names.  EP, if non-null, is set to the last | 
					
						
							|  |  |  |    element of the returned list.  NP, if non-null, is set to the number of | 
					
						
							|  |  |  |    directories in the returned list.  These two variables exist for the | 
					
						
							|  |  |  |    convenience of the caller (always glob_vector). */ | 
					
						
							|  |  |  | static struct globval * | 
					
						
							|  |  |  | finddirs (pat, sdir, flags, ep, np) | 
					
						
							|  |  |  |      char *pat; | 
					
						
							|  |  |  |      char *sdir; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  |      struct globval **ep; | 
					
						
							|  |  |  |      int *np; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char **r, *n; | 
					
						
							|  |  |  |   int ndirs; | 
					
						
							|  |  |  |   struct globval *ret, *e, *g; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*itrace("finddirs: pat = `%s' sdir = `%s' flags = 0x%x", pat, sdir, flags);*/ | 
					
						
							|  |  |  |   e = ret = 0; | 
					
						
							|  |  |  |   r = glob_vector (pat, sdir, flags); | 
					
						
							|  |  |  |   if (r == 0 || r[0] == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (np) | 
					
						
							|  |  |  | 	*np = 0; | 
					
						
							|  |  |  |       if (ep) | 
					
						
							|  |  |  |         *ep = 0; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  |       if (r && r != &glob_error_return) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	free (r); | 
					
						
							|  |  |  |       return (struct globval *)0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   for (ndirs = 0; r[ndirs] != 0; ndirs++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g = (struct globval *) malloc (sizeof (struct globval)); | 
					
						
							|  |  |  |       if (g == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  while (ret)		/* free list built so far */ | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      g = ret->next; | 
					
						
							|  |  |  | 	      free (ret); | 
					
						
							|  |  |  | 	      ret = g; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  free (r); | 
					
						
							|  |  |  | 	  if (np) | 
					
						
							|  |  |  | 	    *np = 0; | 
					
						
							|  |  |  | 	  if (ep) | 
					
						
							|  |  |  | 	    *ep = 0; | 
					
						
							|  |  |  | 	  return (&finddirs_error_return); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       if (e == 0) | 
					
						
							|  |  |  | 	e = g; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g->next = ret; | 
					
						
							|  |  |  |       ret = g; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g->name = r[ndirs]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (r); | 
					
						
							|  |  |  |   if (ep) | 
					
						
							|  |  |  |     *ep = e; | 
					
						
							|  |  |  |   if (np) | 
					
						
							|  |  |  |     *np = ndirs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  |      	 | 
					
						
							| 
									
										
										
										
											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 ** | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | glob_vector (pat, dir, flags) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *pat; | 
					
						
							|  |  |  |      char *dir; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   DIR *d; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   register struct dirent *dp; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   struct globval *lastlink, *e, *dirlist; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   register struct globval *nextlink; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   register char *nextname, *npat, *subdir; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   unsigned int count; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   int lose, skip, ndirs, isdir, sdlen, add_current, patlen; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   register char **name_vector; | 
					
						
							|  |  |  |   register unsigned int i; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   int mflags;		/* Flags passed to strmatch (). */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int pflags;		/* flags passed to sh_makepath () */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   int nalloca; | 
					
						
							|  |  |  |   struct globval *firstmalloc, *tmplink; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   char *convfn; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   lastlink = 0; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   count = lose = skip = add_current = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   firstmalloc = 0; | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   nalloca = 0; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /*itrace("glob_vector: pat = `%s' dir = `%s' flags = 0x%x", pat, dir, flags);*/ | 
					
						
							| 
									
										
										
										
											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
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (glob_testdir (dir, 0) < 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	return ((char **) &glob_error_return); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       nextlink = (struct globval *)alloca (sizeof (struct globval)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (nextlink == NULL) | 
					
						
							|  |  |  | 	return ((char **) NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   patlen = (pat && *pat) ? strlen (pat) : 0; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (glob_testdir (dir, 0) < 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	return ((char **) &glob_error_return); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dirlen = strlen (dir); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |       nextname = (char *)malloc (dirlen + patlen + 2); | 
					
						
							|  |  |  |       npat = (char *)malloc (patlen + 1); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |       if (nextname == 0 || npat == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  FREE (nextname); | 
					
						
							|  |  |  | 	  FREE (npat); | 
					
						
							|  |  |  | 	  lose = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       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)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if (nextlink) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  nextlink->next = (struct globval *)0; | 
					
						
							|  |  |  | 		  lastlink = nextlink; | 
					
						
							|  |  |  | 		  nextlink->name = npat; | 
					
						
							|  |  |  | 		  count = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 		  free (npat); | 
					
						
							|  |  |  | 		  lose = 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)
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (glob_testdir (dir, 0) < 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	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. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       mflags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #ifdef FNM_CASEFOLD
 | 
					
						
							|  |  |  |       if (glob_ignore_case) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	mflags |= FNM_CASEFOLD; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (extended_glob) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	mflags |= FNM_EXTMATCH; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       add_current = ((flags & (GX_ALLDIRS|GX_ADDCURDIR)) == (GX_ALLDIRS|GX_ADDCURDIR)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       /* 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
										 |  |  | 	  /* Make globbing interruptible in the shell. */ | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	  if (interrupt_state || terminating_signal) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      lose = 1; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  else if (signal_is_pending (SIGINT))	/* XXX - make SIGINT traps responsive */ | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      lose = 1; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	  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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 	  if (dp->d_name == 0 || *dp->d_name == 0) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if HANDLE_MULTIBYTE
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name, flags)) | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  if (skipname (pat, dp->d_name, flags)) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  /* If we're only interested in directories, don't bother with files */ | 
					
						
							|  |  |  | 	  if (flags & (GX_MATCHDIRS|GX_ALLDIRS)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      pflags = (flags & GX_ALLDIRS) ? MP_RMDOT : 0; | 
					
						
							|  |  |  | 	      if (flags & GX_NULLDIR) | 
					
						
							|  |  |  | 		pflags |= MP_IGNDOT; | 
					
						
							|  |  |  | 	      subdir = sh_makepath (dir, dp->d_name, pflags); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      isdir = glob_testdir (subdir, flags); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	      if (isdir < 0 && (flags & GX_MATCHDIRS)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  free (subdir); | 
					
						
							|  |  |  | 		  continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if (flags & GX_ALLDIRS) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (isdir == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  dirlist = finddirs (pat, subdir, (flags & ~GX_ADDCURDIR), &e, &ndirs); | 
					
						
							|  |  |  | 		  if (dirlist == &finddirs_error_return) | 
					
						
							|  |  |  | 		    { | 
					
						
							|  |  |  | 		      free (subdir); | 
					
						
							|  |  |  | 		      lose = 1; | 
					
						
							|  |  |  | 		      break; | 
					
						
							|  |  |  | 		    } | 
					
						
							|  |  |  | 		  if (ndirs)		/* add recursive directories to list */ | 
					
						
							|  |  |  | 		    { | 
					
						
							|  |  |  | 		      if (firstmalloc == 0) | 
					
						
							|  |  |  | 		        firstmalloc = e; | 
					
						
							|  |  |  | 		      e->next = lastlink; | 
					
						
							|  |  |  | 		      lastlink = dirlist; | 
					
						
							|  |  |  | 		      count += ndirs; | 
					
						
							|  |  |  | 		    } | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      nextlink = (struct globval *) malloc (sizeof (struct globval)); | 
					
						
							|  |  |  | 	      if (firstmalloc == 0) | 
					
						
							|  |  |  | 		firstmalloc = nextlink; | 
					
						
							|  |  |  | 	      sdlen = strlen (subdir); | 
					
						
							|  |  |  | 	      nextname = (char *) malloc (sdlen + 1); | 
					
						
							|  |  |  | 	      if (nextlink == 0 || nextname == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 		  FREE (nextlink); | 
					
						
							|  |  |  | 		  FREE (nextname); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 		  free (subdir); | 
					
						
							|  |  |  | 		  lose = 1; | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      nextlink->next = lastlink; | 
					
						
							|  |  |  | 	      lastlink = nextlink; | 
					
						
							|  |  |  | 	      nextlink->name = nextname; | 
					
						
							|  |  |  | 	      bcopy (subdir, nextname, sdlen + 1); | 
					
						
							|  |  |  | 	      free (subdir); | 
					
						
							|  |  |  | 	      ++count; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  else if (flags & GX_MATCHDIRS) | 
					
						
							|  |  |  | 	    free (subdir); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp)); | 
					
						
							|  |  |  | 	  if (strmatch (pat, convfn, mflags) != FNM_NOMATCH) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	      if (nalloca < ALLOCA_MAX) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  nextlink = (struct globval *) alloca (sizeof (struct globval)); | 
					
						
							|  |  |  | 		  nalloca += sizeof (struct globval); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  nextlink = (struct globval *) malloc (sizeof (struct globval)); | 
					
						
							|  |  |  | 		  if (firstmalloc == 0) | 
					
						
							|  |  |  | 		    firstmalloc = nextlink; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	      nextname = (char *) malloc (D_NAMLEN (dp) + 1); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if (nextlink == 0 || nextname == 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 		  FREE (nextlink); | 
					
						
							|  |  |  | 		  FREE (nextname); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 		  lose = 1; | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      nextlink->next = lastlink; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	      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
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  |   /* compat: if GX_ADDCURDIR, add the passed directory also.  Add an empty
 | 
					
						
							|  |  |  |      directory name as a placeholder if GX_NULLDIR (in which case the passed | 
					
						
							|  |  |  |      directory name is "."). */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   if (add_current) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sdlen = strlen (dir); | 
					
						
							|  |  |  |       nextname = (char *)malloc (sdlen + 1); | 
					
						
							|  |  |  |       nextlink = (struct globval *) malloc (sizeof (struct globval)); | 
					
						
							|  |  |  |       if (nextlink == 0 || nextname == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  FREE (nextlink); | 
					
						
							|  |  |  | 	  FREE (nextname); | 
					
						
							|  |  |  | 	  lose = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  nextlink->name = nextname; | 
					
						
							|  |  |  | 	  nextlink->next = lastlink; | 
					
						
							|  |  |  | 	  lastlink = nextlink; | 
					
						
							|  |  |  | 	  if (flags & GX_NULLDIR) | 
					
						
							|  |  |  | 	    nextname[0] = '\0'; | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    bcopy (dir, nextname, sdlen + 1); | 
					
						
							|  |  |  | 	  ++count; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       tmplink = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       /* Here free the strings we have got.  */ | 
					
						
							|  |  |  |       while (lastlink) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	  /* Since we build the list in reverse order, the first N entries
 | 
					
						
							|  |  |  | 	     will be allocated with malloc, if firstmalloc is set, from | 
					
						
							|  |  |  | 	     lastlink to firstmalloc. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  if (firstmalloc) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (lastlink == firstmalloc) | 
					
						
							|  |  |  | 		firstmalloc = 0; | 
					
						
							|  |  |  | 	      tmplink = lastlink; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    tmplink = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  free (lastlink->name); | 
					
						
							|  |  |  | 	  lastlink = lastlink->next; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  FREE (tmplink); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* Don't call QUIT; here; let higher layers deal with it. */ | 
					
						
							| 
									
										
										
										
											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.  */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   for (tmplink = lastlink, i = 0; i < count; ++i) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       name_vector[i] = tmplink->name; | 
					
						
							|  |  |  |       tmplink = tmplink->next; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   name_vector[count] = NULL; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If we allocated some of the struct globvals, free them now. */ | 
					
						
							|  |  |  |   if (firstmalloc) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       tmplink = 0; | 
					
						
							|  |  |  |       while (lastlink) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  tmplink = lastlink; | 
					
						
							|  |  |  | 	  if (lastlink == firstmalloc) | 
					
						
							|  |  |  | 	    lastlink = firstmalloc = 0; | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    lastlink = lastlink->next; | 
					
						
							|  |  |  | 	  free (tmplink); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (name_vector); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* 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 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    function as side-effecting ARRAY.  This should handle GX_MARKDIRS. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | static char ** | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | glob_dir_to_array (dir, array, flags) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *dir, **array; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   register unsigned int i, l; | 
					
						
							|  |  |  |   int add_slash; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char **result, *new; | 
					
						
							|  |  |  |   struct stat sb; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   l = strlen (dir); | 
					
						
							|  |  |  |   if (l == 0) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (flags & GX_MARKDIRS) | 
					
						
							|  |  |  | 	for (i = 0; array[i]; i++) | 
					
						
							|  |  |  | 	  { | 
					
						
							|  |  |  | 	    if ((stat (array[i], &sb) == 0) && S_ISDIR (sb.st_mode)) | 
					
						
							|  |  |  | 	      { | 
					
						
							|  |  |  | 		l = strlen (array[i]); | 
					
						
							|  |  |  | 		new = (char *)realloc (array[i], l + 2); | 
					
						
							|  |  |  | 		if (new == 0) | 
					
						
							|  |  |  | 		  return NULL; | 
					
						
							|  |  |  | 		new[l] = '/'; | 
					
						
							|  |  |  | 		new[l+1] = '\0'; | 
					
						
							|  |  |  | 		array[i] = new; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  |       return (array); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       /* 3 == 1 for NUL, 1 for slash at end of DIR, 1 for GX_MARKDIRS */ | 
					
						
							|  |  |  |       result[i] = (char *) malloc (l + strlen (array[i]) + 3); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       if (result[i] == NULL) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  int ind; | 
					
						
							|  |  |  | 	  for (ind = 0; ind < i; ind++) | 
					
						
							|  |  |  | 	    free (result[ind]); | 
					
						
							|  |  |  | 	  free (result); | 
					
						
							|  |  |  | 	  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]); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (flags & GX_MARKDIRS) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      size_t rlen; | 
					
						
							|  |  |  | 	      rlen = strlen (result[i]); | 
					
						
							|  |  |  | 	      result[i][rlen] = '/'; | 
					
						
							|  |  |  | 	      result[i][rlen+1] = '\0'; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* 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 ** | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | glob_filename (pathname, flags) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *pathname; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   char **result; | 
					
						
							|  |  |  |   unsigned int result_size; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   char *directory_name, *filename, *dname; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   unsigned int directory_len; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   int free_dirname;			/* flag */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int dflags; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   result = (char **) malloc (sizeof (char *)); | 
					
						
							|  |  |  |   result_size = 1; | 
					
						
							|  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |     return (NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   result[0] = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   directory_name = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* Find the filename.  */ | 
					
						
							|  |  |  |   filename = strrchr (pathname, '/'); | 
					
						
							|  |  |  |   if (filename == NULL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       filename = pathname; | 
					
						
							|  |  |  |       directory_name = ""; | 
					
						
							|  |  |  |       directory_len = 0; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       free_dirname = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       directory_len = (filename - pathname) + 1; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       directory_name = (char *) malloc (directory_len + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (directory_name == 0)		/* allocation failed? */ | 
					
						
							|  |  |  | 	return (NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       bcopy (pathname, directory_name, directory_len); | 
					
						
							|  |  |  |       directory_name[directory_len] = '\0'; | 
					
						
							|  |  |  |       ++filename; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       free_dirname = 1; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If directory_name contains globbing characters, then we
 | 
					
						
							|  |  |  |      have to expand the previous levels.  Just recurse. */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (directory_len > 0 && glob_pattern_p (directory_name)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       char **directories, *d, *p; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       register unsigned int i; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       int all_starstar, last_starstar; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       all_starstar = last_starstar = 0; | 
					
						
							|  |  |  |       d = directory_name; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       dflags = flags & ~GX_MARKDIRS; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* Collapse a sequence of ** patterns separated by one or more slashes
 | 
					
						
							|  |  |  | 	 to a single ** terminated by a slash or NUL */ | 
					
						
							|  |  |  |       if ((flags & GX_GLOBSTAR) && d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0')) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  p = d; | 
					
						
							|  |  |  | 	  while (d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0')) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      p = d; | 
					
						
							|  |  |  | 	      if (d[2]) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  d += 3; | 
					
						
							|  |  |  | 		  while (*d == '/') | 
					
						
							|  |  |  | 		    d++; | 
					
						
							|  |  |  | 		  if (*d == 0) | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  if (*d == 0) | 
					
						
							|  |  |  | 	    all_starstar = 1; | 
					
						
							|  |  |  | 	  d = p; | 
					
						
							|  |  |  | 	  dflags |= GX_ALLDIRS|GX_ADDCURDIR; | 
					
						
							|  |  |  | 	  directory_len = strlen (d); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* If there is a non [star][star]/ component in directory_name, we
 | 
					
						
							|  |  |  | 	 still need to collapse trailing sequences of [star][star]/ into | 
					
						
							|  |  |  | 	 a single one and note that the directory name ends with [star][star], | 
					
						
							|  |  |  | 	 so we can compensate if filename is [star][star] */ | 
					
						
							|  |  |  |       if ((flags & GX_GLOBSTAR) && all_starstar == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  int dl, prev; | 
					
						
							|  |  |  | 	  prev = dl = directory_len; | 
					
						
							|  |  |  | 	  while (dl >= 4 && d[dl - 1] == '/' && | 
					
						
							|  |  |  | 			   d[dl - 2] == '*' && | 
					
						
							|  |  |  | 			   d[dl - 3] == '*' && | 
					
						
							|  |  |  | 			   d[dl - 4] == '/') | 
					
						
							|  |  |  | 	    prev = dl, dl -= 3; | 
					
						
							|  |  |  | 	  if (dl != directory_len) | 
					
						
							|  |  |  | 	    last_starstar = 1; | 
					
						
							|  |  |  | 	  directory_len = prev; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* If the directory name ends in [star][star]/ but the filename is
 | 
					
						
							|  |  |  | 	 [star][star], just remove the final [star][star] from the directory | 
					
						
							|  |  |  | 	 so we don't have to scan everything twice. */ | 
					
						
							|  |  |  |       if (last_starstar && directory_len > 4 && | 
					
						
							|  |  |  | 	    filename[0] == '*' && filename[1] == '*' && filename[2] == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  directory_len -= 3; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (d[directory_len - 1] == '/') | 
					
						
							|  |  |  | 	d[directory_len - 1] = '\0'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       directories = glob_filename (d, dflags); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (free_dirname) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free (directory_name); | 
					
						
							|  |  |  | 	  directory_name = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* If we have something like [star][star]/[star][star], it's no use to
 | 
					
						
							|  |  |  |          glob **, then do it again, and throw half the results away.  */ | 
					
						
							|  |  |  |       if (all_starstar && filename[0] == '*' && filename[1] == '*' && filename[2] == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free ((char *) directories); | 
					
						
							|  |  |  | 	  free (directory_name); | 
					
						
							|  |  |  | 	  directory_name = NULL; | 
					
						
							|  |  |  | 	  directory_len = 0; | 
					
						
							|  |  |  | 	  goto only_filename; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       /* 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; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  int shouldbreak; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  shouldbreak = 0; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	  /* XXX -- we've recursively scanned any directories resulting from
 | 
					
						
							|  |  |  | 	     a `**', so turn off the flag.  We turn it on again below if | 
					
						
							|  |  |  | 	     filename is `**' */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  /* Scan directory even on a NULL filename.  That way, `*h/'
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	     returns only directories ending in `h', instead of all | 
					
						
							|  |  |  | 	     files ending in `h' with a `/' appended. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  dname = directories[i]; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	  dflags = flags & ~(GX_MARKDIRS|GX_ALLDIRS|GX_ADDCURDIR); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0') | 
					
						
							|  |  |  | 	    dflags |= GX_ALLDIRS|GX_ADDCURDIR; | 
					
						
							|  |  |  | 	  if (dname[0] == '\0' && filename[0]) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      dflags |= GX_NULLDIR; | 
					
						
							|  |  |  | 	      dname = ".";	/* treat null directory name and non-null filename as current directory */ | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  temp_results = glob_vector (filename, dname, dflags); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  /* 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	      /* If we're expanding **, we don't need to glue the directory
 | 
					
						
							|  |  |  | 		 name to the results; we've already done it in glob_vector */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && (filename[2] == '\0' || filename[2] == '/')) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  /* When do we remove null elements from temp_results?  And
 | 
					
						
							|  |  |  | 		     how to avoid duplicate elements in the final result? */ | 
					
						
							|  |  |  | 		  /* If (dflags & GX_NULLDIR) glob_filename potentially left a
 | 
					
						
							|  |  |  | 		     NULL placeholder in the temp results just in case | 
					
						
							|  |  |  | 		     glob_vector/glob_dir_to_array did something with it, but | 
					
						
							|  |  |  | 		     if it didn't, and we're not supposed to be passing them | 
					
						
							|  |  |  | 		     through for some reason ((flags & GX_NULLDIR) == 0) we | 
					
						
							|  |  |  | 		     need to remove all the NULL elements from the beginning | 
					
						
							|  |  |  | 		     of TEMP_RESULTS. */ | 
					
						
							|  |  |  | 		  /* If we have a null directory name and ** as the filename,
 | 
					
						
							|  |  |  | 		     we have just searched for everything from the current | 
					
						
							|  |  |  | 		     directory on down. Break now (shouldbreak = 1) to avoid | 
					
						
							|  |  |  | 		     duplicate entries in the final result. */ | 
					
						
							|  |  |  | #define NULL_PLACEHOLDER(x)	((x) && *(x) && **(x) == 0)
 | 
					
						
							|  |  |  | 		  if ((dflags & GX_NULLDIR) && (flags & GX_NULLDIR) == 0 && | 
					
						
							|  |  |  | 			NULL_PLACEHOLDER (temp_results)) | 
					
						
							|  |  |  | #undef NULL_PLACEHOLDER
 | 
					
						
							|  |  |  | 		    { | 
					
						
							|  |  |  | 		      register int i, n; | 
					
						
							|  |  |  | 		      for (n = 0; temp_results[n] && *temp_results[n] == 0; n++) | 
					
						
							|  |  |  | 			; | 
					
						
							|  |  |  | 		      i = n; | 
					
						
							|  |  |  | 		      do | 
					
						
							|  |  |  | 			temp_results[i - n] = temp_results[i]; | 
					
						
							|  |  |  | 		      while (temp_results[i++] != 0); | 
					
						
							|  |  |  | 		      array = temp_results; | 
					
						
							|  |  |  | 		      shouldbreak = 1; | 
					
						
							|  |  |  | 		    } | 
					
						
							|  |  |  | 	          else | 
					
						
							|  |  |  | 		    array = temp_results; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	      else | 
					
						
							|  |  |  | 		array = glob_dir_to_array (directories[i], temp_results, flags); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      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.  */ | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	      if (array != temp_results) | 
					
						
							|  |  |  | 		free ((char *) array); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0') | 
					
						
							|  |  |  | 		free (temp_results);	/* expanding ** case above */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      if (shouldbreak) | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       /* Free the directories.  */ | 
					
						
							|  |  |  |       for (i = 0; directories[i]; i++) | 
					
						
							|  |  |  | 	free (directories[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       free ((char *) directories); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return (result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | only_filename: | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* 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); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       /* Handle GX_MARKDIRS here. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       result[0] = (char *) malloc (directory_len + 1); | 
					
						
							|  |  |  |       if (result[0] == NULL) | 
					
						
							|  |  |  | 	goto memory_error; | 
					
						
							|  |  |  |       bcopy (directory_name, result[0], directory_len + 1); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (free_dirname) | 
					
						
							|  |  |  | 	free (directory_name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       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. */ | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  |       /* If flags & GX_ALLDIRS, we're called recursively */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       dflags = flags & ~GX_MARKDIRS; | 
					
						
							|  |  |  |       if (directory_len == 0) | 
					
						
							|  |  |  | 	dflags |= GX_NULLDIR; | 
					
						
							|  |  |  |       if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0') | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  dflags |= GX_ALLDIRS|GX_ADDCURDIR; | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	  /* If we want all directories (dflags & GX_ALLDIRS) and we're not
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | 	     being called recursively as something like `echo [star][star]/[star].o' | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | 	     ((flags & GX_ALLDIRS) == 0), we want to prevent glob_vector from | 
					
						
							|  |  |  | 	     adding a null directory name to the front of the temp_results | 
					
						
							|  |  |  | 	     array.  We turn off ADDCURDIR if not called recursively and | 
					
						
							|  |  |  | 	     dlen == 0 */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	  if (directory_len == 0 && (flags & GX_ALLDIRS) == 0) | 
					
						
							|  |  |  | 	    dflags &= ~GX_ADDCURDIR; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       temp_results = glob_vector (filename, | 
					
						
							|  |  |  | 				  (directory_len == 0 ? "." : directory_name), | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 				  dflags); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (temp_results == NULL || temp_results == (char **)&glob_error_return) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  if (free_dirname) | 
					
						
							|  |  |  | 	    free (directory_name); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  QUIT;			/* XXX - shell */ | 
					
						
							|  |  |  | 	  run_pending_traps (); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  return (temp_results); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (free_dirname) | 
					
						
							|  |  |  | 	free (directory_name); | 
					
						
							|  |  |  |       return (result); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* 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); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   if (free_dirname && directory_name) | 
					
						
							|  |  |  |     free (directory_name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   QUIT; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   run_pending_traps (); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #if defined (TEST)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | main (argc, argv) | 
					
						
							|  |  |  |      int argc; | 
					
						
							|  |  |  |      char **argv; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 1; i < argc; ++i) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       char **value = glob_filename (argv[i], 0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       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.  */
 |