Imported from ../bash-1.14.7.tar.gz.
This commit is contained in:
commit
726f63884d
402 changed files with 150297 additions and 0 deletions
13
lib/glob/ChangeLog
Normal file
13
lib/glob/ChangeLog
Normal file
|
@ -0,0 +1,13 @@
|
|||
Thu Oct 29 08:58:12 1992 Brian Fox (bfox@cubit)
|
||||
|
||||
* glob.c (glob_filename): Fix tiny memory leak. Rework some
|
||||
comments.
|
||||
|
||||
Mon Jul 20 10:57:36 1992 Brian Fox (bfox@cubit)
|
||||
|
||||
* glob.c: (glob_filename) Change use of rindex () to strrchr ().
|
||||
|
||||
Thu Jul 9 10:02:47 1992 Brian Fox (bfox@cubit)
|
||||
|
||||
* fnmatch.c: (fnmatch) Only process `[' as the start of a bracket
|
||||
expression if there is a closing `]' present in the string.
|
95
lib/glob/Makefile
Normal file
95
lib/glob/Makefile
Normal file
|
@ -0,0 +1,95 @@
|
|||
## -*- text -*- ####################################################
|
||||
# #
|
||||
# Makefile for the GNU Glob Library. #
|
||||
# #
|
||||
####################################################################
|
||||
|
||||
# This Makefile is hand made from a template file, found in
|
||||
# ../template. Each library must provide several Makefile
|
||||
# targets: `all', `clean', `documentation', `install', and
|
||||
# `what-tar'. The `what-tar' target reports the names of the
|
||||
# files that need to be included in a tarfile to build the full
|
||||
# code and documentation for this library.
|
||||
|
||||
# Please note that the values for INCLUDES, CC, AR, RM, CP,
|
||||
# RANLIB, and selfdir are passed in from ../Makefile, and do
|
||||
# not need to be defined here.
|
||||
srcdir = .
|
||||
VPATH = .:$(srcdir)
|
||||
|
||||
# Here is a rule for making .o files from .c files that doesn't force
|
||||
# the type of the machine (like -sun3) into the flags.
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(INCLUDES) $(LOCAL_DEFINES) $(CPPFLAGS) $<
|
||||
|
||||
# LOCAL_DEFINES are flags that are specific to this library.
|
||||
# Define -DUSG if you are using a System V operating system.
|
||||
LOCAL_DEFINES = $(LOCAL_INCLUDES) #-DUSG
|
||||
|
||||
# For libraries which include headers from other libraries.
|
||||
LOCAL_INCLUDES = -I..
|
||||
|
||||
# The name of the library target.
|
||||
LIBRARY_NAME = libglob.a
|
||||
|
||||
# The C code source files for this library.
|
||||
CSOURCES = $(srcdir)glob.c $(srcdir)fnmatch.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES = $(srcdir)fnmatch.h
|
||||
|
||||
OBJECTS = glob.o fnmatch.o
|
||||
|
||||
# The texinfo files which document this library.
|
||||
DOCSOURCE = doc/glob.texi
|
||||
DOCOBJECT = doc/glob.dvi
|
||||
DOCSUPPORT = doc/Makefile
|
||||
DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
|
||||
|
||||
SUPPORT = Makefile ChangeLog $(DOCSUPPORT)
|
||||
|
||||
SOURCES = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
|
||||
|
||||
THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
|
||||
|
||||
######################################################################
|
||||
|
||||
all: $(LIBRARY_NAME)
|
||||
|
||||
$(LIBRARY_NAME): $(OBJECTS)
|
||||
$(RM) -f $@
|
||||
$(AR) cq $@ $(OBJECTS)
|
||||
-[ -n "$(RANLIB)" ] && $(RANLIB) $@
|
||||
|
||||
what-tar:
|
||||
@for file in $(THINGS_TO_TAR); do \
|
||||
echo $(selfdir)$$file; \
|
||||
done
|
||||
|
||||
documentation: force
|
||||
-(cd doc && $(MAKE) $(MFLAGS))
|
||||
|
||||
force:
|
||||
|
||||
# The rule for 'includes' is written funny so that the if statement
|
||||
# always returns TRUE unless there really was an error installing the
|
||||
# include files.
|
||||
install:
|
||||
-$(MV) $(bindir)/$(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME)-old
|
||||
$(CP) $(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME)
|
||||
-[ -n "$(RANLIB)" ] && $(RANLIB) -t $(bindir)/$(LIBRARY_NAME)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(LIBRARY_NAME)
|
||||
-(cd doc && $(MAKE) $(MFLAGS) $@)
|
||||
|
||||
maintainer-clean realclean mostlyclean distclean: clean
|
||||
-(cd doc && $(MAKE) $(MFLAGS) $@)
|
||||
|
||||
######################################################################
|
||||
# #
|
||||
# Dependencies for the object files which make up this library. #
|
||||
# #
|
||||
######################################################################
|
||||
|
||||
fnmatch.o: fnmatch.c fnmatch.h
|
5
lib/glob/doc/Makefile
Normal file
5
lib/glob/doc/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
all:
|
||||
cp glob.texi glob.info
|
||||
|
||||
maintainer-clean realclean distclean clean:
|
||||
rm -f glob.?? glob.info
|
1
lib/glob/doc/glob.texi
Normal file
1
lib/glob/doc/glob.texi
Normal file
|
@ -0,0 +1 @@
|
|||
Nothing happens here.
|
189
lib/glob/fnmatch.c
Normal file
189
lib/glob/fnmatch.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/* Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include "fnmatch.h"
|
||||
|
||||
#if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
|
||||
# if !defined (errno)
|
||||
extern int errno;
|
||||
# endif /* !errno */
|
||||
#endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, FNM_NOMATCH if not. */
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
char *pattern;
|
||||
char *string;
|
||||
int flags;
|
||||
{
|
||||
register char *p = pattern, *n = string;
|
||||
register char c;
|
||||
|
||||
if ((flags & ~__FNM_FLAGS) != 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
if (*n == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
else if ((flags & FNM_PATHNAME) && *n == '/')
|
||||
return (FNM_NOMATCH);
|
||||
else if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
c = *p++;
|
||||
if (*n != c)
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
|
||||
if (((flags & FNM_PATHNAME) && *n == '/') ||
|
||||
(c == '?' && *n == '\0'))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
if (c == '\0')
|
||||
return (0);
|
||||
|
||||
{
|
||||
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
|
||||
for (--p; *n != '\0'; ++n)
|
||||
if ((c == '[' || *n == c1) &&
|
||||
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
|
||||
return (0);
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
case '[':
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
register int not;
|
||||
|
||||
if (*n == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
/* Make sure there is a closing `]'. If there isn't, the `['
|
||||
is just a character to be matched. */
|
||||
{
|
||||
register char *np;
|
||||
|
||||
for (np = p; np && *np && *np != ']'; np++);
|
||||
|
||||
if (np && !*np)
|
||||
{
|
||||
if (*n != '[')
|
||||
return (FNM_NOMATCH);
|
||||
goto next_char;
|
||||
}
|
||||
}
|
||||
|
||||
not = (*p == '!' || *p == '^');
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
register char cstart = c, cend = c;
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
cstart = cend = *p++;
|
||||
|
||||
if (c == '\0')
|
||||
/* [ (unterminated) loses. */
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
c = *p++;
|
||||
|
||||
if ((flags & FNM_PATHNAME) && c == '/')
|
||||
/* [/] can never match. */
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return (FNM_NOMATCH);
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if (*n >= cstart && *n <= cend)
|
||||
goto matched;
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
if (!not)
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
next_char:
|
||||
break;
|
||||
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != ']')
|
||||
{
|
||||
if (c == '\0')
|
||||
/* [... (unterminated) loses. */
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
/* 1003.2d11 is unclear if this is right. %%% */
|
||||
++p;
|
||||
}
|
||||
if (not)
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c != *n)
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
if (*n == '\0')
|
||||
return (0);
|
||||
|
||||
return (FNM_NOMATCH);
|
||||
}
|
36
lib/glob/fnmatch.h
Normal file
36
lib/glob/fnmatch.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */
|
||||
#define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */
|
||||
#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch();
|
||||
|
||||
#endif /* fnmatch.h */
|
574
lib/glob/glob.c
Normal file
574
lib/glob/glob.c
Normal file
|
@ -0,0 +1,574 @@
|
|||
/* File-name wildcard pattern matching for GNU.
|
||||
Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* 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. */
|
||||
|
||||
#if defined (SHELL)
|
||||
# if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
# else
|
||||
# include "ansi_stdlib.h"
|
||||
# endif /* HAVE_STDLIB_H */
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
|
||||
# if !defined (HAVE_DIRENT_H)
|
||||
# define HAVE_DIRENT_H
|
||||
# endif /* !HAVE_DIRENT_H */
|
||||
#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
|
||||
|
||||
#if defined (HAVE_DIRENT_H)
|
||||
# include <dirent.h>
|
||||
# if !defined (direct)
|
||||
# define direct dirent
|
||||
# endif /* !direct */
|
||||
# define D_NAMLEN(d) strlen ((d)->d_name)
|
||||
#else /* !HAVE_DIRENT_H */
|
||||
# define D_NAMLEN(d) ((d)->d_namlen)
|
||||
# if defined (USG)
|
||||
# if defined (Xenix)
|
||||
# include <sys/ndir.h>
|
||||
# else /* !Xenix (but USG...) */
|
||||
# include "ndir.h"
|
||||
# endif /* !Xenix */
|
||||
# else /* !USG */
|
||||
# include <sys/dir.h>
|
||||
# endif /* !USG */
|
||||
#endif /* !HAVE_DIRENT_H */
|
||||
|
||||
#if defined (_POSIX_SOURCE)
|
||||
/* Posix does not require that the d_ino field be present, and some
|
||||
systems do not provide it. */
|
||||
# define REAL_DIR_ENTRY(dp) 1
|
||||
#else
|
||||
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
|
||||
#endif /* _POSIX_SOURCE */
|
||||
|
||||
#if defined (USG) || defined (NeXT)
|
||||
# if !defined (HAVE_STRING_H)
|
||||
# define HAVE_STRING_H
|
||||
# endif /* !HAVE_STRING_H */
|
||||
#endif /* USG || NeXT */
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else /* !HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
#if defined (USG)
|
||||
# if !defined (isc386)
|
||||
# include <memory.h>
|
||||
# endif /* !isc386 */
|
||||
# if defined (RISC6000)
|
||||
extern void bcopy ();
|
||||
# else /* !RISC6000 */
|
||||
# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
|
||||
# endif /* !RISC6000 */
|
||||
#endif /* USG */
|
||||
|
||||
#include "fnmatch.h"
|
||||
|
||||
/* If the opendir () on your system lets you open non-directory files,
|
||||
then we consider that not robust. Define OPENDIR_NOT_ROBUST in the
|
||||
SYSDEP_CFLAGS for your machines entry in machines.h. */
|
||||
#if defined (OPENDIR_NOT_ROBUST)
|
||||
# if defined (SHELL)
|
||||
# include "posixstat.h"
|
||||
# else /* !SHELL */
|
||||
# include <sys/stat.h>
|
||||
# endif /* !SHELL */
|
||||
#endif /* OPENDIR_NOT_ROBUST */
|
||||
|
||||
#if !defined (HAVE_STDLIB_H)
|
||||
extern char *malloc (), *realloc ();
|
||||
extern void free ();
|
||||
#endif /* !HAVE_STDLIB_H */
|
||||
|
||||
#if !defined (NULL)
|
||||
# if defined (__STDC__)
|
||||
# define NULL ((void *) 0)
|
||||
# else
|
||||
# define NULL 0x0
|
||||
# endif /* __STDC__ */
|
||||
#endif /* !NULL */
|
||||
|
||||
#if defined (SHELL)
|
||||
extern int interrupt_state;
|
||||
#endif /* SHELL */
|
||||
|
||||
/* Global variable which controls whether or not * matches .*.
|
||||
Non-zero means don't match .*. */
|
||||
int noglob_dot_filenames = 1;
|
||||
|
||||
/* Global variable to return to signify an error in globbing. */
|
||||
char *glob_error_return;
|
||||
|
||||
|
||||
/* Return nonzero if PATTERN has any special globbing chars in it. */
|
||||
int
|
||||
glob_pattern_p (pattern)
|
||||
char *pattern;
|
||||
{
|
||||
register char *p = pattern;
|
||||
register char c;
|
||||
int open = 0;
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
case '*':
|
||||
return (1);
|
||||
|
||||
case '[': /* Only accept an open brace if there is a close */
|
||||
open++; /* brace to match it. Bracket expressions must be */
|
||||
continue; /* complete, according to Posix.2 */
|
||||
case ']':
|
||||
if (open)
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case '\\':
|
||||
if (*p++ == '\0')
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
|
||||
static void
|
||||
dequote_pathname (pathname)
|
||||
char *pathname;
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
for (i = j = 0; pathname && pathname[i]; )
|
||||
{
|
||||
if (pathname[i] == '\\')
|
||||
i++;
|
||||
|
||||
pathname[j++] = pathname[i++];
|
||||
|
||||
if (!pathname[i - 1])
|
||||
break;
|
||||
}
|
||||
pathname[j] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* Return a vector of names of files in directory DIR
|
||||
whose names match glob pattern PAT.
|
||||
The names are not in any particular order.
|
||||
Wildcards at the beginning of PAT do not match an initial period.
|
||||
|
||||
The vector is terminated by an element that is a null pointer.
|
||||
|
||||
To free the space allocated, first free the vector's elements,
|
||||
then free the vector.
|
||||
|
||||
Return 0 if cannot get enough memory to hold the pointer
|
||||
and the names.
|
||||
|
||||
Return -1 if cannot access directory DIR.
|
||||
Look in errno for more information. */
|
||||
|
||||
char **
|
||||
glob_vector (pat, dir)
|
||||
char *pat;
|
||||
char *dir;
|
||||
{
|
||||
struct globval
|
||||
{
|
||||
struct globval *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
DIR *d;
|
||||
register struct direct *dp;
|
||||
struct globval *lastlink;
|
||||
register struct globval *nextlink;
|
||||
register char *nextname;
|
||||
unsigned int count;
|
||||
int lose, skip;
|
||||
register char **name_vector;
|
||||
register unsigned int i;
|
||||
#if defined (OPENDIR_NOT_ROBUST)
|
||||
struct stat finfo;
|
||||
|
||||
if (stat (dir, &finfo) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
if (!S_ISDIR (finfo.st_mode))
|
||||
return ((char **) &glob_error_return);
|
||||
#endif /* OPENDIR_NOT_ROBUST */
|
||||
|
||||
d = opendir (dir);
|
||||
if (d == NULL)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
lastlink = 0;
|
||||
count = 0;
|
||||
lose = 0;
|
||||
skip = 0;
|
||||
|
||||
/* If PAT is empty, skip the loop, but return one (empty) filename. */
|
||||
if (!pat || !*pat)
|
||||
{
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
nextlink->next = lastlink;
|
||||
nextname = (char *) malloc (1);
|
||||
if (!nextname)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
nextname[0] = '\0';
|
||||
count++;
|
||||
}
|
||||
skip = 1;
|
||||
}
|
||||
|
||||
/* 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 (!skip)
|
||||
{
|
||||
int flags; /* Flags passed to fnmatch (). */
|
||||
#if defined (SHELL)
|
||||
/* Make globbing interruptible in the bash shell. */
|
||||
if (interrupt_state)
|
||||
{
|
||||
closedir (d);
|
||||
lose = 1;
|
||||
goto lost;
|
||||
}
|
||||
#endif /* SHELL */
|
||||
|
||||
dp = readdir (d);
|
||||
if (dp == NULL)
|
||||
break;
|
||||
|
||||
/* If this directory entry is not to be used, try again. */
|
||||
if (!REAL_DIR_ENTRY (dp))
|
||||
continue;
|
||||
|
||||
/* If a dot must be explicity matched, check to see if they do. */
|
||||
if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
|
||||
continue;
|
||||
|
||||
flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
|
||||
|
||||
if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
|
||||
{
|
||||
nextlink = (struct globval *) alloca (sizeof (struct globval));
|
||||
nextlink->next = lastlink;
|
||||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextname == NULL)
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
(void) closedir (d);
|
||||
|
||||
if (!lose)
|
||||
{
|
||||
name_vector = (char **) malloc ((count + 1) * sizeof (char *));
|
||||
lose |= name_vector == NULL;
|
||||
}
|
||||
|
||||
/* Have we run out of memory? */
|
||||
lost:
|
||||
if (lose)
|
||||
{
|
||||
/* Here free the strings we have got. */
|
||||
while (lastlink)
|
||||
{
|
||||
free (lastlink->name);
|
||||
lastlink = lastlink->next;
|
||||
}
|
||||
#if defined (SHELL)
|
||||
if (interrupt_state)
|
||||
throw_to_top_level ();
|
||||
#endif /* SHELL */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Copy the name pointers from the linked list into the vector. */
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
name_vector[i] = lastlink->name;
|
||||
lastlink = lastlink->next;
|
||||
}
|
||||
|
||||
name_vector[count] = NULL;
|
||||
return (name_vector);
|
||||
}
|
||||
|
||||
/* Return a new array which is the concatenation of each string in ARRAY
|
||||
to DIR. This function expects you to pass in an allocated ARRAY, and
|
||||
it takes care of free()ing that array. Thus, you might think of this
|
||||
function as side-effecting ARRAY. */
|
||||
static char **
|
||||
glob_dir_to_array (dir, array)
|
||||
char *dir, **array;
|
||||
{
|
||||
register unsigned int i, l;
|
||||
int add_slash;
|
||||
char **result;
|
||||
|
||||
l = strlen (dir);
|
||||
if (l == 0)
|
||||
return (array);
|
||||
|
||||
add_slash = dir[l - 1] != '/';
|
||||
|
||||
i = 0;
|
||||
while (array[i] != NULL)
|
||||
++i;
|
||||
|
||||
result = (char **) malloc ((i + 1) * sizeof (char *));
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
for (i = 0; array[i] != NULL; i++)
|
||||
{
|
||||
result[i] = (char *) malloc (l + (add_slash ? 1 : 0)
|
||||
+ strlen (array[i]) + 1);
|
||||
if (result[i] == NULL)
|
||||
return (NULL);
|
||||
sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
|
||||
}
|
||||
result[i] = NULL;
|
||||
|
||||
/* Free the input array. */
|
||||
for (i = 0; array[i] != NULL; i++)
|
||||
free (array[i]);
|
||||
free ((char *) array);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Do globbing on PATHNAME. Return an array of pathnames that match,
|
||||
marking the end of the array with a null-pointer as an element.
|
||||
If no pathnames match, then the array is empty (first element is null).
|
||||
If there isn't enough memory, then return NULL.
|
||||
If a file system error occurs, return -1; `errno' has the error code. */
|
||||
char **
|
||||
glob_filename (pathname)
|
||||
char *pathname;
|
||||
{
|
||||
char **result;
|
||||
unsigned int result_size;
|
||||
char *directory_name, *filename;
|
||||
unsigned int directory_len;
|
||||
|
||||
result = (char **) malloc (sizeof (char *));
|
||||
result_size = 1;
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
result[0] = NULL;
|
||||
|
||||
/* Find the filename. */
|
||||
filename = strrchr (pathname, '/');
|
||||
if (filename == NULL)
|
||||
{
|
||||
filename = pathname;
|
||||
directory_name = "";
|
||||
directory_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
directory_len = (filename - pathname) + 1;
|
||||
directory_name = (char *) alloca (directory_len + 1);
|
||||
|
||||
bcopy (pathname, directory_name, directory_len);
|
||||
directory_name[directory_len] = '\0';
|
||||
++filename;
|
||||
}
|
||||
|
||||
/* If directory_name contains globbing characters, then we
|
||||
have to expand the previous levels. Just recurse. */
|
||||
if (glob_pattern_p (directory_name))
|
||||
{
|
||||
char **directories;
|
||||
register unsigned int i;
|
||||
|
||||
if (directory_name[directory_len - 1] == '/')
|
||||
directory_name[directory_len - 1] = '\0';
|
||||
|
||||
directories = glob_filename (directory_name);
|
||||
|
||||
if (directories == NULL)
|
||||
goto memory_error;
|
||||
else if (directories == (char **)&glob_error_return)
|
||||
{
|
||||
free ((char *)result);
|
||||
return ((char **) &glob_error_return);
|
||||
}
|
||||
else if (*directories == NULL)
|
||||
{
|
||||
free ((char *) directories);
|
||||
free ((char *) result);
|
||||
return ((char **) &glob_error_return);
|
||||
}
|
||||
|
||||
/* We have successfully globbed the preceding directory name.
|
||||
For each name in DIRECTORIES, call glob_vector on it and
|
||||
FILENAME. Concatenate the results together. */
|
||||
for (i = 0; directories[i] != NULL; ++i)
|
||||
{
|
||||
char **temp_results;
|
||||
|
||||
/* Scan directory even on a NULL pathname. That way, `*h/'
|
||||
returns only directories ending in `h', instead of all
|
||||
files ending in `h' with a `/' appended. */
|
||||
temp_results = glob_vector (filename, directories[i]);
|
||||
|
||||
/* Handle error cases. */
|
||||
if (temp_results == NULL)
|
||||
goto memory_error;
|
||||
else if (temp_results == (char **)&glob_error_return)
|
||||
/* This filename is probably not a directory. Ignore it. */
|
||||
;
|
||||
else
|
||||
{
|
||||
char **array;
|
||||
register unsigned int l;
|
||||
|
||||
array = glob_dir_to_array (directories[i], temp_results);
|
||||
l = 0;
|
||||
while (array[l] != NULL)
|
||||
++l;
|
||||
|
||||
result =
|
||||
(char **)realloc (result, (result_size + l) * sizeof (char *));
|
||||
|
||||
if (result == NULL)
|
||||
goto memory_error;
|
||||
|
||||
for (l = 0; array[l] != NULL; ++l)
|
||||
result[result_size++ - 1] = array[l];
|
||||
|
||||
result[result_size - 1] = NULL;
|
||||
|
||||
/* Note that the elements of ARRAY are not freed. */
|
||||
free ((char *) array);
|
||||
}
|
||||
}
|
||||
/* Free the directories. */
|
||||
for (i = 0; directories[i]; i++)
|
||||
free (directories[i]);
|
||||
|
||||
free ((char *) directories);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* If there is only a directory name, return it. */
|
||||
if (*filename == '\0')
|
||||
{
|
||||
result = (char **) realloc ((char *) result, 2 * sizeof (char *));
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
result[0] = (char *) malloc (directory_len + 1);
|
||||
if (result[0] == NULL)
|
||||
goto memory_error;
|
||||
bcopy (directory_name, result[0], directory_len + 1);
|
||||
result[1] = NULL;
|
||||
return (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
char **temp_results;
|
||||
|
||||
/* There are no unquoted globbing characters in DIRECTORY_NAME.
|
||||
Dequote it before we try to open the directory since there may
|
||||
be quoted globbing characters which should be treated verbatim. */
|
||||
if (directory_len > 0)
|
||||
dequote_pathname (directory_name);
|
||||
|
||||
/* We allocated a small array called RESULT, which we won't be using.
|
||||
Free that memory now. */
|
||||
free (result);
|
||||
|
||||
/* Just return what glob_vector () returns appended to the
|
||||
directory name. */
|
||||
temp_results =
|
||||
glob_vector (filename, (directory_len == 0 ? "." : directory_name));
|
||||
|
||||
if (temp_results == NULL || temp_results == (char **)&glob_error_return)
|
||||
return (temp_results);
|
||||
|
||||
return (glob_dir_to_array (directory_name, temp_results));
|
||||
}
|
||||
|
||||
/* We get to memory_error if the program has run out of memory, or
|
||||
if this is the shell, and we have been interrupted. */
|
||||
memory_error:
|
||||
if (result != NULL)
|
||||
{
|
||||
register unsigned int i;
|
||||
for (i = 0; result[i] != NULL; ++i)
|
||||
free (result[i]);
|
||||
free ((char *) result);
|
||||
}
|
||||
#if defined (SHELL)
|
||||
if (interrupt_state)
|
||||
throw_to_top_level ();
|
||||
#endif /* SHELL */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#if defined (TEST)
|
||||
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
char **value = glob_filename (argv[i]);
|
||||
if (value == NULL)
|
||||
puts ("Out of memory.");
|
||||
else if (value == &glob_error_return)
|
||||
perror (argv[i]);
|
||||
else
|
||||
for (i = 0; value[i] != NULL; i++)
|
||||
puts (value[i]);
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
#endif /* TEST. */
|
50
lib/glob/ndir.h
Normal file
50
lib/glob/ndir.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* <dir.h> -- definitions for 4.2BSD-compatible directory access.
|
||||
last edit: 09-Jul-1983 D A Gwyn. */
|
||||
|
||||
#if defined (VMS)
|
||||
# if !defined (FAB$C_BID)
|
||||
# include <fab.h>
|
||||
# endif
|
||||
# if !defined (NAM$C_BID)
|
||||
# include <nam.h>
|
||||
# endif
|
||||
# if !defined (RMS$_SUC)
|
||||
# include <rmsdef.h>
|
||||
# endif
|
||||
# include "dir.h"
|
||||
#endif /* VMS */
|
||||
|
||||
/* Size of directory block. */
|
||||
#define DIRBLKSIZ 512
|
||||
|
||||
/* NOTE: MAXNAMLEN must be one less than a multiple of 4 */
|
||||
|
||||
#if defined (VMS)
|
||||
# define MAXNAMLEN (DIR$S_NAME + 7) /* 80 plus room for version #. */
|
||||
# define MAXFULLSPEC NAM$C_MAXRSS /* Maximum full spec */
|
||||
#else
|
||||
# define MAXNAMLEN 15 /* Maximum filename length. */
|
||||
#endif /* VMS */
|
||||
|
||||
/* Data from readdir (). */
|
||||
struct direct {
|
||||
long d_ino; /* Inode number of entry. */
|
||||
unsigned short d_reclen; /* Length of this record. */
|
||||
unsigned short d_namlen; /* Length of string in d_name. */
|
||||
char d_name[MAXNAMLEN + 1]; /* Name of file. */
|
||||
};
|
||||
|
||||
/* Stream data from opendir (). */
|
||||
typedef struct {
|
||||
int dd_fd; /* File descriptor. */
|
||||
int dd_loc; /* Offset in block. */
|
||||
int dd_size; /* Amount of valid data. */
|
||||
char dd_buf[DIRBLKSIZ]; /* Directory block. */
|
||||
} DIR;
|
||||
|
||||
extern DIR *opendir ();
|
||||
extern struct direct *readdir ();
|
||||
extern long telldir ();
|
||||
extern void seekdir (), closedir ();
|
||||
|
||||
#define rewinddir(dirp) seekdir (dirp, 0L)
|
Loading…
Add table
Add a link
Reference in a new issue