diff options
-rw-r--r-- | glob/glob.c | 150 | ||||
-rw-r--r-- | glob/glob.h | 15 |
2 files changed, 129 insertions, 36 deletions
diff --git a/glob/glob.c b/glob/glob.c index 90dd9d9..6bd5628 100644 --- a/glob/glob.c +++ b/glob/glob.c @@ -37,8 +37,15 @@ Cambridge, MA 02139, USA. */ program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ -#if defined (_LIBC) || !defined (__GNU_LIBRARY__) +#define GLOB_INTERFACE_VERSION 1 +#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 +#include <gnu-versions.h> +#if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif +#ifndef ELIDE_CODE #ifdef STDC_HEADERS #include <stddef.h> @@ -53,6 +60,8 @@ Cambridge, MA 02139, USA. */ #endif #endif +#include <pwd.h> + #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) extern int errno; #endif @@ -211,10 +220,6 @@ extern char *alloca (); #undef GLOB_PERIOD #include <glob.h> -__ptr_t (*__glob_opendir_hook) __P ((const char *directory)); -const char *(*__glob_readdir_hook) __P ((__ptr_t stream)); -void (*__glob_closedir_hook) __P ((__ptr_t stream)); - static int glob_pattern_p __P ((const char *pattern, int quote)); static int glob_in_dir __P ((const char *pattern, const char *directory, int flags, @@ -250,6 +255,56 @@ glob (pattern, flags, errfunc, pglob) return -1; } + if (flags & GLOB_BRACE) + { + const char *begin = strchr (pattern, '{'); + if (begin != NULL) + { + const char *end = strchr (begin + 1, '}'); + if (end != NULL && end != begin + 1) + { + size_t restlen = strlen (end + 1) + 1; + const char *p, *comma; + char *buf; + size_t bufsz = 0; + int firstc; + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + } + firstc = pglob->gl_pathc; + for (p = begin + 1;; p = comma + 1) + { + int result; + comma = strchr (p, ','); + if (comma == NULL) + comma = strchr (p, '\0'); + if ((begin - pattern) + (comma - p) + 1 > bufsz) + { + if (bufsz * 2 < comma - p + 1) + bufsz *= 2; + else + bufsz = comma - p + 1; + buf = __alloca (bufsz); + } + memcpy (buf, pattern, begin - pattern); + memcpy (buf + (begin - pattern), p, comma - p); + memcpy (buf + (begin - pattern) + (comma - p), end, restlen); + result = glob (buf, (flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC) | + GLOB_APPEND), errfunc, pglob); + if (result && result != GLOB_NOMATCH) + return result; + if (*comma == '\0') + break; + } + if (pglob->gl_pathc == firstc && + !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + return GLOB_NOMATCH; + } + } + } + /* Find the filename. */ filename = strrchr (pattern, '/'); if (filename == NULL) @@ -291,6 +346,45 @@ glob (pattern, flags, errfunc, pglob) oldcount = pglob->gl_pathc; + pglob->gl_flags = flags; + if (!(flags & GLOB_ALTDIRFUNC)) + { + pglob->gl_closedir = (void (*) __P ((void *))) &closedir; + pglob->gl_readdir = (struct dirent *(*) __P ((void *))) &readdir; + pglob->gl_opendir = (__ptr_t (*) __P ((const char *))) &opendir; + pglob->gl_lstat = &lstat; + pglob->gl_stat = &stat; + } + + if ((flags & GLOB_TILDE) && dirname[0] == '~') + { + if (dirname[1] == '\0') + { + /* Look up home directory. */ + dirname = getenv ("HOME"); + if (dirname == NULL || dirname[0] == '\0') + { + extern char *getlogin (); + char *name = getlogin (); + if (name != NULL) + { + struct passwd *p = getpwnam (name); + if (p != NULL) + dirname = p->pw_dir; + } + } + if (dirname == NULL || dirname[0] == '\0') + dirname = (char *) "~"; /* No luck. */ + } + else + { + /* Look up specific user's home directory. */ + struct passwd *p = getpwnam (dirname + 1); + if (p != NULL) + dirname = p->pw_dir; + } + } + if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) { /* The directory name contains metacharacters, so we @@ -581,8 +675,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) { flags |= GLOB_MAGCHAR; - stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory) - : (__ptr_t) opendir (directory)); + stream = (*pglob->gl_opendir) (directory); if (stream == NULL) { if ((errfunc != NULL && (*errfunc) (directory, errno)) || @@ -594,29 +687,18 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) { const char *name; size_t len; - - if (__glob_readdir_hook) - { - name = (*__glob_readdir_hook) (stream); - if (name == NULL) - break; - len = 0; - } - else - { - struct dirent *d = readdir ((DIR *) stream); - if (d == NULL) - break; - if (! REAL_DIR_ENTRY (d)) - continue; - name = d->d_name; + struct dirent *d = (*pglob->gl_readdir) (stream); + if (d == NULL) + break; + if (! REAL_DIR_ENTRY (d)) + continue; + name = d->d_name; #ifdef HAVE_D_NAMLEN - len = d->d_namlen; + len = d->d_namlen; #else - len = 0; + len = 0; #endif - } - + if (fnmatch (pattern, name, (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0) @@ -638,6 +720,10 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) } } + if (nfound == 0 && (flags & GLOB_NOMAGIC) && + ! glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE))) + flags |= GLOB_NOCHECK; + if (nfound == 0 && (flags & GLOB_NOCHECK)) { size_t len = strlen (pattern); @@ -673,10 +759,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) if (stream != NULL) { int save = errno; - if (__glob_closedir_hook) - (*__glob_closedir_hook) (stream); - else - (void) closedir ((DIR *) stream); + (*pglob->gl_closedir) (stream); errno = save; } return nfound == 0 ? GLOB_NOMATCH : 0; @@ -684,10 +767,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) memory_error: { int save = errno; - if (__glob_closedir_hook) - (*__glob_closedir_hook) (stream); - else - (void) closedir ((DIR *) stream); + (*pglob->gl_closedir) (stream); errno = save; } while (names != NULL) diff --git a/glob/glob.h b/glob/glob.h index 05ad47f..ce48169 100644 --- a/glob/glob.h +++ b/glob/glob.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -51,6 +51,10 @@ extern "C" #if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_BSD_SOURCE) #define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ +#define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ +#define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ +#define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ +#define GLOB_TILDE (1 <<12)/* Expand ~user and ~ to home directories. */ #endif /* Error returns from `glob'. */ @@ -59,12 +63,21 @@ extern "C" #define GLOB_NOMATCH 3 /* No matches found. */ /* Structure describing a globbing run. */ +struct stat; typedef struct { int gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ int gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ + + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) __P ((void *)); + struct dirent *(*gl_readdir) __P ((void *)); + __ptr_t (*gl_opendir) __P ((const char *)); + int (*gl_lstat) __P ((const char *, struct stat *)); + int (*gl_stat) __P ((const char *, struct stat *)); } glob_t; /* Do glob searching for PATTERN, placing results in PGLOB. |