summaryrefslogtreecommitdiff
path: root/glob.c
diff options
context:
space:
mode:
authortim <tim>1997-05-14 15:30:41 +0000
committerToby Goodwin <toby@paccrat.org>2015-05-16 21:23:00 +0100
commit53cf1b1c1c3f0c2b5067afccc2976b99a574a089 (patch)
treea31f167c3779362e29ab377d662052b6257253a8 /glob.c
parentb87bfedf65c289bf0ee5338c9e10492b70b1e8e0 (diff)
Initial revision
Diffstat (limited to 'glob.c')
-rw-r--r--glob.c278
1 files changed, 0 insertions, 278 deletions
diff --git a/glob.c b/glob.c
deleted file mode 100644
index 043f767..0000000
--- a/glob.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* glob.c: rc's (ugly) globber. This code is not elegant, but it works */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "rc.h"
-
-/* Lifted from autoconf documentation.*/
-#if HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif
-
-static List *dmatch(char *, char *, char *);
-static List *doglob(char *, char *);
-static List *lglob(List *, char *, char *, size_t);
-static List *sort(List *);
-
-/*
- Matches a list of words s against a list of patterns p. Returns true iff
- a pattern in p matches a word in s. () matches (), but otherwise null
- patterns match nothing.
-*/
-
-extern bool lmatch(List *s, List *p) {
- List *q;
- int i;
- bool okay;
- if (s == NULL) {
- if (p == NULL) /* null matches null */
- return TRUE;
- for (; p != NULL; p = p->n) { /* one or more stars match null */
- if (*p->w != '\0') { /* the null string is a special case; it does *not* match () */
- okay = TRUE;
- for (i = 0; p->w[i] != '\0'; i++)
- if (p->w[i] != '*' || p->m[i] != 1) {
- okay = FALSE;
- break;
- }
- if (okay)
- return TRUE;
- }
- }
- return FALSE;
- }
- for (; s != NULL; s = s->n)
- for (q = p; q != NULL; q = q->n)
- if (match(q->w, q->m, s->w))
- return TRUE;
- return FALSE;
-}
-
-/*
- Globs a list; checks to see if each element in the list has a metacharacter. If it
- does, it is globbed, and the output is sorted.
-*/
-
-extern List *glob(List *s) {
- List *top, *r;
- bool meta;
- for (r = s, meta = FALSE; r != NULL; r = r->n)
- if (r->m != NULL)
- meta = TRUE;
- if (!meta)
- return s; /* don't copy lists with no metacharacters in them */
- for (top = r = NULL; s != NULL; s = s->n) {
- if (s->m == NULL) { /* no metacharacters; just tack on to the return list */
- if (top == NULL)
- top = r = nnew(List);
- else
- r = r->n = nnew(List);
- r->w = s->w;
- } else {
- if (top == NULL)
- top = r = sort(doglob(s->w, s->m));
- else
- r->n = sort(doglob(s->w, s->m));
- while (r->n != NULL)
- r = r->n;
- }
- }
- r->n = NULL;
- return top;
-}
-
-/* Matches a pattern p against the contents of directory d */
-
-static List *dmatch(char *d, char *p, char *m) {
- bool matched = FALSE;
- List *top, *r;
- static DIR *dirp;
- static struct dirent *dp;
- static struct stat s;
- int i;
-
- /*
- return a match if there are no metacharacters; allows globbing through
- directories with no read permission. make sure the file exists, though.
- */
- matched = TRUE;
- if (m != NULL)
- for (i = 0; p[i] != '\0'; i++)
- if (m[i]) {
- matched = FALSE;
- break;
- }
-
- if (matched) {
- char *path = nprint("%s/%s", d, p);
- if (stat(path, &s) < 0)
- return NULL;
- r = nnew(List);
- r->w = ncpy(p);
- r->m = NULL;
- r->n = NULL;
- return r;
- }
-
- top = r = NULL;
- if ((dirp = opendir(d)) == NULL)
- return NULL;
- /* opendir succeeds on regular files on some systems, so the stat() call is necessary (sigh) */
- if (stat(d, &s) < 0 || (s.st_mode & S_IFMT) != S_IFDIR) {
- closedir(dirp);
- return NULL;
- }
- while ((dp = readdir(dirp)) != NULL)
- if ((*dp->d_name != '.' || *p == '.') && match(p, m, dp->d_name)) { /* match ^. explicitly */
- matched = TRUE;
- if (top == NULL)
- top = r = nnew(List);
- else
- r = r->n = nnew(List);
- r->w = ncpy(dp->d_name);
- r->m = NULL;
- }
- closedir(dirp);
- if (!matched)
- return NULL;
- r->n = NULL;
- return top;
-}
-
-/*
- lglob() globs a pattern agains a list of directory roots. e.g., (/tmp /usr /bin) "*"
- will return a list with all the files in /tmp, /usr, and /bin. NULL on no match.
- slashcount indicates the number of slashes to stick between the directory and the
- matched name. e.g., for matching ////tmp/////foo*
-*/
-
-static List *lglob(List *s, char *p, char *m, size_t slashcount) {
- List *q, *r, *top, foo;
- static struct {
- List l;
- size_t size;
- } slash;
- if (slashcount+1 > slash.size) {
- slash.size = 2*(slashcount+1);
- slash.l.w = erealloc(slash.l.w, slash.size);
- }
- slash.l.w[slashcount] = '\0';
- while (slashcount > 0)
- slash.l.w[--slashcount] = '/';
- for (top = r = NULL; s != NULL; s = s->n) {
- q = dmatch(s->w, p, m);
- if (q != NULL) {
- foo.w = s->w;
- foo.m = NULL;
- foo.n = NULL;
- if (!(s->w[0] == '/' && s->w[1] == '\0')) /* need to separate */
- q = concat(&slash.l, q); /* dir/name with slash */
- q = concat(&foo, q);
- if (r == NULL)
- top = r = q;
- else
- r->n = q;
- while (r->n != NULL)
- r = r->n;
- }
- }
- return top;
-}
-
-/*
- Doglob globs a pathname in pattern form against a unix path. Returns the original
- pattern (cleaned of metacharacters) on failure, or the globbed string(s).
-*/
-
-static List *doglob(char *w, char *m) {
- static char *dir = NULL, *pattern = NULL, *metadir = NULL, *metapattern = NULL;
- static size_t dsize = 0;
- char *d, *p, *md, *mp;
- size_t psize;
- char *s = w;
- List firstdir;
- List *matched;
- if ((psize = strlen(w) + 1) > dsize || dir == NULL) {
- efree(dir); efree(pattern); efree(metadir); efree(metapattern);
- dir = ealloc(psize);
- pattern = ealloc(psize);
- metadir = ealloc(psize);
- metapattern = ealloc(psize);
- dsize = psize;
- }
- d = dir;
- p = pattern;
- md = metadir;
- mp = metapattern;
- if (*s == '/')
- while (*s == '/')
- *d++ = *s++, *md++ = *m++;
- else
- while (*s != '/' && *s != '\0')
- *d++ = *s++, *md++ = *m++; /* get first directory component */
- *d = '\0';
- /*
- Special case: no slashes in the pattern, i.e., open the current directory.
- Remember that w cannot consist of slashes alone (the other way *s could be
- zero) since doglob gets called iff there's a metacharacter to be matched
- */
- if (*s == '\0') {
- matched = dmatch(".", dir, metadir);
- goto end;
- }
- if (*w == '/') {
- firstdir.w = dir;
- firstdir.m = metadir;
- firstdir.n = NULL;
- matched = &firstdir;
- } else {
- /*
- we must glob against current directory,
- since the first character is not a slash.
- */
- matched = dmatch(".", dir, metadir);
- }
- do {
- size_t slashcount;
- sigchk();
- for (slashcount = 0; *s == '/'; s++, m++)
- slashcount++; /* skip slashes */
- while (*s != '/' && *s != '\0')
- *p++ = *s++, *mp++ = *m++; /* get pattern */
- *p = '\0';
- matched = lglob(matched, pattern, metapattern, slashcount);
- p = pattern, mp = metapattern;
- } while (*s != '\0');
-end: if (matched == NULL) {
- matched = nnew(List);
- matched->w = w;
- matched->m = NULL;
- matched->n = NULL;
- }
- return matched;
-}
-
-static List *sort(List *s) {
- size_t nel = listnel(s);
- if (nel > 1) {
- char **a;
- List *t;
- qsort(a = list2array(s, FALSE), nel, sizeof(char *), starstrcmp);
- for (t = s; t != NULL; t = t->n)
- t->w = *a++;
- }
- return s;
-}