fix typo in changelog
[debian/sudo] / glob.c
1 /*      $OpenBSD: glob.c,v 1.23 2004/05/18 02:05:52 jfb Exp $   */
2
3 /*
4  * Copyright (c) 1989, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Guido van Rossum.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      @(#)glob.c      8.3 (Berkeley) 10/13/93
35  */
36
37 /*
38  * glob(3) -- a superset of the one defined in POSIX 1003.2.
39  *
40  * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
41  *
42  * Optional extra services, controlled by flags not defined by POSIX:
43  *
44  * GLOB_MAGCHAR:
45  *      Set in gl_flags if pattern contained a globbing character.
46  * GLOB_TILDE:
47  *      expand ~user/foo to the /home/dir/of/user/foo
48  * GLOB_BRACE:
49  *      expand {1,2}{a,b} to 1a 1b 2a 2b
50  * gl_matchc:
51  *      Number of matches in the current invocation of glob.
52  */
53
54 #include <config.h>
55
56 #include <sys/param.h>
57 #include <sys/stat.h>
58
59 #include <stdio.h>
60 #ifdef STDC_HEADERS
61 # include <stdlib.h>
62 # include <stddef.h>
63 #else
64 # ifdef HAVE_STDLIB_H
65 #  include <stdlib.h>
66 # endif
67 #endif /* STDC_HEADERS */
68 #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
69 # include <malloc.h>
70 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
71 #ifdef HAVE_STRING_H
72 # include <string.h>
73 #else
74 # ifdef HAVE_STRINGS_H
75 #  include <strings.h>
76 # endif
77 #endif /* HAVE_STRING_H */
78 #ifdef HAVE_UNISTD_H
79 # include <unistd.h>
80 #endif /* HAVE_UNISTD_H */
81 #include <ctype.h>
82 #ifdef HAVE_DIRENT_H
83 # include <dirent.h>
84 #else
85 # define dirent direct
86 # ifdef HAVE_SYS_NDIR_H
87 #  include <sys/ndir.h>
88 # endif
89 # ifdef HAVE_SYS_DIR_H
90 #  include <sys/dir.h>
91 # endif
92 # ifdef HAVE_NDIR_H
93 #  include <ndir.h>
94 # endif
95 #endif
96 #include <errno.h>
97 #include <limits.h>
98 #include <pwd.h>
99
100 #include <compat.h>
101 #include "emul/glob.h"
102
103 #define DOLLAR          '$'
104 #define DOT             '.'
105 #define EOS             '\0'
106 #define LBRACKET        '['
107 #define NOT             '!'
108 #define QUESTION        '?'
109 #define QUOTE           '\\'
110 #define RANGE           '-'
111 #define RBRACKET        ']'
112 #define SEP             '/'
113 #define STAR            '*'
114 #define TILDE           '~'
115 #define UNDERSCORE      '_'
116 #define LBRACE          '{'
117 #define RBRACE          '}'
118 #define SLASH           '/'
119 #define COMMA           ','
120
121 #ifndef DEBUG
122
123 #define M_QUOTE         0x8000
124 #define M_PROTECT       0x4000
125 #define M_MASK          0xffff
126 #define M_ASCII         0x00ff
127
128 typedef unsigned short Char;
129
130 #else
131
132 #define M_QUOTE         0x80
133 #define M_PROTECT       0x40
134 #define M_MASK          0xff
135 #define M_ASCII         0x7f
136
137 typedef char Char;
138
139 #endif
140
141
142 #define CHAR(c)         ((Char)((c)&M_ASCII))
143 #define META(c)         ((Char)((c)|M_QUOTE))
144 #define M_ALL           META('*')
145 #define M_END           META(']')
146 #define M_NOT           META('!')
147 #define M_ONE           META('?')
148 #define M_RNG           META('-')
149 #define M_SET           META('[')
150 #define ismeta(c)       (((c)&M_QUOTE) != 0)
151
152
153 static int       compare __P((const void *, const void *));
154 static int       g_Ctoc __P((const Char *, char *, unsigned int));
155 static int       g_lstat __P((Char *, struct stat *, glob_t *));
156 static DIR      *g_opendir __P((Char *, glob_t *));
157 static Char     *g_strchr __P((Char *, int));
158 static int       g_stat __P((Char *, struct stat *, glob_t *));
159 static int       glob0 __P((const Char *, glob_t *));
160 static int       glob1 __P((Char *, Char *, glob_t *));
161 static int       glob2 __P((Char *, Char *, Char *, Char *, Char *, Char *,
162                     glob_t *));
163 static int       glob3 __P((Char *, Char *, Char *, Char *, Char *, Char *,
164                     Char *, Char *, glob_t *));
165 static int       globextend __P((const Char *, glob_t *));
166 static const Char *
167                  globtilde __P((const Char *, Char *, size_t, glob_t *));
168 static int       globexp1 __P((const Char *, glob_t *));
169 static int       globexp2 __P((const Char *, const Char *, glob_t *, int *));
170 static int       match __P((Char *, Char *, Char *));
171 #ifdef DEBUG
172 static void      qprintf __P((const char *, Char *));
173 #endif
174
175 int
176 glob(pattern, flags, errfunc, pglob)
177         const char *pattern;
178         int flags, (*errfunc) __P((const char *, int));
179         glob_t *pglob;
180 {
181         const unsigned char *patnext;
182         int c;
183         Char *bufnext, *bufend, patbuf[PATH_MAX];
184
185         patnext = (unsigned char *) pattern;
186         if (!(flags & GLOB_APPEND)) {
187                 pglob->gl_pathc = 0;
188                 pglob->gl_pathv = NULL;
189                 if (!(flags & GLOB_DOOFFS))
190                         pglob->gl_offs = 0;
191         }
192         pglob->gl_flags = flags & ~GLOB_MAGCHAR;
193         pglob->gl_errfunc = errfunc;
194         pglob->gl_matchc = 0;
195
196         bufnext = patbuf;
197         bufend = bufnext + PATH_MAX - 1;
198         if (flags & GLOB_NOESCAPE)
199                 while (bufnext < bufend && (c = *patnext++) != EOS)
200                         *bufnext++ = c;
201         else {
202                 /* Protect the quoted characters. */
203                 while (bufnext < bufend && (c = *patnext++) != EOS)
204                         if (c == QUOTE) {
205                                 if ((c = *patnext++) == EOS) {
206                                         c = QUOTE;
207                                         --patnext;
208                                 }
209                                 *bufnext++ = c | M_PROTECT;
210                         } else
211                                 *bufnext++ = c;
212         }
213         *bufnext = EOS;
214
215         if (flags & GLOB_BRACE)
216                 return globexp1(patbuf, pglob);
217         else
218                 return glob0(patbuf, pglob);
219 }
220
221 /*
222  * Expand recursively a glob {} pattern. When there is no more expansion
223  * invoke the standard globbing routine to glob the rest of the magic
224  * characters
225  */
226 static int
227 globexp1(pattern, pglob)
228         const Char *pattern;
229         glob_t *pglob;
230 {
231         const Char* ptr = pattern;
232         int rv;
233
234         /* Protect a single {}, for find(1), like csh */
235         if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
236                 return glob0(pattern, pglob);
237
238         while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
239                 if (!globexp2(ptr, pattern, pglob, &rv))
240                         return rv;
241
242         return glob0(pattern, pglob);
243 }
244
245
246 /*
247  * Recursive brace globbing helper. Tries to expand a single brace.
248  * If it succeeds then it invokes globexp1 with the new pattern.
249  * If it fails then it tries to glob the rest of the pattern and returns.
250  */
251 static int
252 globexp2(ptr, pattern, pglob, rv)
253         const Char *ptr, *pattern;
254         glob_t *pglob;
255         int *rv;
256 {
257         int     i;
258         Char   *lm, *ls;
259         const Char *pe, *pm, *pl;
260         Char    patbuf[PATH_MAX];
261
262         /* copy part up to the brace */
263         for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
264                 continue;
265         *lm = EOS;
266         ls = lm;
267
268         /* Find the balanced brace */
269         for (i = 0, pe = ++ptr; *pe; pe++)
270                 if (*pe == LBRACKET) {
271                         /* Ignore everything between [] */
272                         for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
273                                 continue;
274                         if (*pe == EOS) {
275                                 /*
276                                  * We could not find a matching RBRACKET.
277                                  * Ignore and just look for RBRACE
278                                  */
279                                 pe = pm;
280                         }
281                 } else if (*pe == LBRACE)
282                         i++;
283                 else if (*pe == RBRACE) {
284                         if (i == 0)
285                                 break;
286                         i--;
287                 }
288
289         /* Non matching braces; just glob the pattern */
290         if (i != 0 || *pe == EOS) {
291                 *rv = glob0(patbuf, pglob);
292                 return 0;
293         }
294
295         for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
296                 switch (*pm) {
297                 case LBRACKET:
298                         /* Ignore everything between [] */
299                         for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
300                                 continue;
301                         if (*pm == EOS) {
302                                 /*
303                                  * We could not find a matching RBRACKET.
304                                  * Ignore and just look for RBRACE
305                                  */
306                                 pm = pl;
307                         }
308                         break;
309
310                 case LBRACE:
311                         i++;
312                         break;
313
314                 case RBRACE:
315                         if (i) {
316                                 i--;
317                                 break;
318                         }
319                         /* FALLTHROUGH */
320                 case COMMA:
321                         if (i && *pm == COMMA)
322                                 break;
323                         else {
324                                 /* Append the current string */
325                                 for (lm = ls; (pl < pm); *lm++ = *pl++)
326                                         continue;
327
328                                 /*
329                                  * Append the rest of the pattern after the
330                                  * closing brace
331                                  */
332                                 for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
333                                         continue;
334
335                                 /* Expand the current pattern */
336 #ifdef DEBUG
337                                 qprintf("globexp2:", patbuf);
338 #endif
339                                 *rv = globexp1(patbuf, pglob);
340
341                                 /* move after the comma, to the next string */
342                                 pl = pm + 1;
343                         }
344                         break;
345
346                 default:
347                         break;
348                 }
349         }
350         *rv = 0;
351         return 0;
352 }
353
354
355
356 /*
357  * expand tilde from the passwd file.
358  */
359 static const Char *
360 globtilde(pattern, patbuf, patbuf_len, pglob)
361         const Char *pattern;
362         Char *patbuf;
363         size_t patbuf_len;
364         glob_t *pglob;
365 {
366         struct passwd *pwd;
367         char *h;
368         const Char *p;
369         Char *b, *eb;
370
371         if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
372                 return pattern;
373
374         /* Copy up to the end of the string or / */
375         eb = &patbuf[patbuf_len - 1];
376         for (p = pattern + 1, h = (char *) patbuf;
377             h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
378                 continue;
379
380         *h = EOS;
381
382         if (((char *) patbuf)[0] == EOS) {
383                 /*
384                  * handle a plain ~ or ~/ by expanding $HOME
385                  * first and then trying the password file
386                  */
387                 if ((h = getenv("HOME")) == NULL) {
388                         if ((pwd = getpwuid(getuid())) == NULL)
389                                 return pattern;
390                         else
391                                 h = pwd->pw_dir;
392                 }
393         } else {
394                 /*
395                  * Expand a ~user
396                  */
397                 if ((pwd = getpwnam((char*) patbuf)) == NULL)
398                         return pattern;
399                 else
400                         h = pwd->pw_dir;
401         }
402
403         /* Copy the home directory */
404         for (b = patbuf; b < eb && *h; *b++ = *h++)
405                 continue;
406
407         /* Append the rest of the pattern */
408         while (b < eb && (*b++ = *p++) != EOS)
409                 continue;
410         *b = EOS;
411
412         return patbuf;
413 }
414
415
416 /*
417  * The main glob() routine: compiles the pattern (optionally processing
418  * quotes), calls glob1() to do the real pattern matching, and finally
419  * sorts the list (unless unsorted operation is requested).  Returns 0
420  * if things went well, nonzero if errors occurred.  It is not an error
421  * to find no matches.
422  */
423 static int
424 glob0(pattern, pglob)
425         const Char *pattern;
426         glob_t *pglob;
427 {
428         const Char *qpatnext;
429         int c, err, oldpathc;
430         Char *bufnext, patbuf[PATH_MAX];
431
432         qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob);
433         oldpathc = pglob->gl_pathc;
434         bufnext = patbuf;
435
436         /* We don't need to check for buffer overflow any more. */
437         while ((c = *qpatnext++) != EOS) {
438                 switch (c) {
439                 case LBRACKET:
440                         c = *qpatnext;
441                         if (c == NOT)
442                                 ++qpatnext;
443                         if (*qpatnext == EOS ||
444                             g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
445                                 *bufnext++ = LBRACKET;
446                                 if (c == NOT)
447                                         --qpatnext;
448                                 break;
449                         }
450                         *bufnext++ = M_SET;
451                         if (c == NOT)
452                                 *bufnext++ = M_NOT;
453                         c = *qpatnext++;
454                         do {
455                                 *bufnext++ = CHAR(c);
456                                 if (*qpatnext == RANGE &&
457                                     (c = qpatnext[1]) != RBRACKET) {
458                                         *bufnext++ = M_RNG;
459                                         *bufnext++ = CHAR(c);
460                                         qpatnext += 2;
461                                 }
462                         } while ((c = *qpatnext++) != RBRACKET);
463                         pglob->gl_flags |= GLOB_MAGCHAR;
464                         *bufnext++ = M_END;
465                         break;
466                 case QUESTION:
467                         pglob->gl_flags |= GLOB_MAGCHAR;
468                         *bufnext++ = M_ONE;
469                         break;
470                 case STAR:
471                         pglob->gl_flags |= GLOB_MAGCHAR;
472                         /* collapse adjacent stars to one,
473                          * to avoid exponential behavior
474                          */
475                         if (bufnext == patbuf || bufnext[-1] != M_ALL)
476                                 *bufnext++ = M_ALL;
477                         break;
478                 default:
479                         *bufnext++ = CHAR(c);
480                         break;
481                 }
482         }
483         *bufnext = EOS;
484 #ifdef DEBUG
485         qprintf("glob0:", patbuf);
486 #endif
487
488         if ((err = glob1(patbuf, patbuf + PATH_MAX - 1, pglob)) != 0)
489                 return(err);
490
491         /*
492          * If there was no match we are going to append the pattern
493          * if GLOB_NOCHECK was specified.
494          */
495         if (pglob->gl_pathc == oldpathc) {
496                 if (pglob->gl_flags & GLOB_NOCHECK)
497                         return(globextend(pattern, pglob));
498                 else
499                         return(GLOB_NOMATCH);
500         }
501         if (!(pglob->gl_flags & GLOB_NOSORT))
502                 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
503                     pglob->gl_pathc - oldpathc, sizeof(char *), compare);
504         return(0);
505 }
506
507 static int
508 compare(p, q)
509         const void *p, *q;
510 {
511         return(strcmp(*(char **)p, *(char **)q));
512 }
513
514 static int
515 glob1(pattern, pattern_last,  pglob)
516         Char *pattern, *pattern_last;
517         glob_t *pglob;
518 {
519         Char pathbuf[PATH_MAX];
520
521         /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
522         if (*pattern == EOS)
523                 return(0);
524         return(glob2(pathbuf, pathbuf + PATH_MAX - 1,
525             pathbuf, pathbuf + PATH_MAX - 1,
526             pattern, pattern_last, pglob));
527 }
528
529 /*
530  * The functions glob2 and glob3 are mutually recursive; there is one level
531  * of recursion for each segment in the pattern that contains one or more
532  * meta characters.
533  */
534 static int
535 glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, pglob)
536         Char *pathbuf, *pathbuf_last;
537         Char *pathend, *pathend_last;
538         Char *pattern, *pattern_last;
539         glob_t *pglob;
540 {
541         struct stat sb;
542         Char *p, *q;
543         int anymeta;
544
545         /*
546          * Loop over pattern segments until end of pattern or until
547          * segment with meta character found.
548          */
549         for (anymeta = 0;;) {
550                 if (*pattern == EOS) {          /* End of pattern? */
551                         *pathend = EOS;
552                         if (g_lstat(pathbuf, &sb, pglob))
553                                 return(0);
554
555                         if (((pglob->gl_flags & GLOB_MARK) &&
556                             pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
557                             (S_ISLNK(sb.st_mode) &&
558                             (g_stat(pathbuf, &sb, pglob) == 0) &&
559                             S_ISDIR(sb.st_mode)))) {
560                                 if (pathend+1 > pathend_last)
561                                         return (1);
562                                 *pathend++ = SEP;
563                                 *pathend = EOS;
564                         }
565                         ++pglob->gl_matchc;
566                         return(globextend(pathbuf, pglob));
567                 }
568
569                 /* Find end of next segment, copy tentatively to pathend. */
570                 q = pathend;
571                 p = pattern;
572                 while (*p != EOS && *p != SEP) {
573                         if (ismeta(*p))
574                                 anymeta = 1;
575                         if (q+1 > pathend_last)
576                                 return (1);
577                         *q++ = *p++;
578                 }
579
580                 if (!anymeta) {         /* No expansion, do next segment. */
581                         pathend = q;
582                         pattern = p;
583                         while (*pattern == SEP) {
584                                 if (pathend+1 > pathend_last)
585                                         return (1);
586                                 *pathend++ = *pattern++;
587                         }
588                 } else
589                         /* Need expansion, recurse. */
590                         return(glob3(pathbuf, pathbuf_last, pathend,
591                             pathend_last, pattern, pattern_last,
592                             p, pattern_last, pglob));
593         }
594         /* NOTREACHED */
595 }
596
597 static int
598 glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last,
599     restpattern, restpattern_last, pglob)
600         Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
601         Char *pattern, *pattern_last, *restpattern, *restpattern_last;
602         glob_t *pglob;
603 {
604         struct dirent *dp;
605         DIR *dirp;
606         int err;
607         char buf[PATH_MAX];
608
609         if (pathend > pathend_last)
610                 return (1);
611         *pathend = EOS;
612         errno = 0;
613
614         if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
615                 /* TODO: don't call for ENOENT or ENOTDIR? */
616                 if (pglob->gl_errfunc) {
617                         if (g_Ctoc(pathbuf, buf, sizeof(buf)))
618                                 return(GLOB_ABORTED);
619                         if (pglob->gl_errfunc(buf, errno) ||
620                             pglob->gl_flags & GLOB_ERR)
621                                 return(GLOB_ABORTED);
622                 }
623                 return(0);
624         }
625
626         err = 0;
627
628         /* Search directory for matching names. */
629         while ((dp = readdir(dirp))) {
630                 unsigned char *sc;
631                 Char *dc;
632
633                 /* Initial DOT must be matched literally. */
634                 if (dp->d_name[0] == DOT && *pattern != DOT)
635                         continue;
636                 dc = pathend;
637                 sc = (unsigned char *) dp->d_name;
638                 while (dc < pathend_last && (*dc++ = *sc++) != EOS)
639                         continue;
640                 if (dc >= pathend_last) {
641                         *dc = EOS;
642                         err = 1;
643                         break;
644                 }
645
646                 if (!match(pathend, pattern, restpattern)) {
647                         *pathend = EOS;
648                         continue;
649                 }
650                 err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
651                     restpattern, restpattern_last, pglob);
652                 if (err)
653                         break;
654         }
655
656         closedir(dirp);
657         return(err);
658 }
659
660 /*
661  * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
662  * add the new item, and update gl_pathc.
663  *
664  * This assumes the BSD realloc, which only copies the block when its size
665  * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
666  * behavior.
667  *
668  * Return 0 if new item added, error code if memory couldn't be allocated.
669  *
670  * Invariant of the glob_t structure:
671  *      Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
672  *      gl_pathv points to (gl_offs + gl_pathc + 1) items.
673  */
674 static int
675 globextend(path, pglob)
676         const Char *path;
677         glob_t *pglob;
678 {
679         char **pathv;
680         int i;
681         unsigned int newsize, len;
682         char *copy;
683         const Char *p;
684
685         newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
686         pathv = pglob->gl_pathv ?
687             (char **)realloc((char *)pglob->gl_pathv, newsize) :
688             (char **)malloc(newsize);
689         if (pathv == NULL) {
690                 if (pglob->gl_pathv) {
691                         free(pglob->gl_pathv);
692                         pglob->gl_pathv = NULL;
693                 }
694                 return(GLOB_NOSPACE);
695         }
696
697         if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
698                 /* first time around -- clear initial gl_offs items */
699                 pathv += pglob->gl_offs;
700                 for (i = pglob->gl_offs; --i >= 0; )
701                         *--pathv = NULL;
702         }
703         pglob->gl_pathv = pathv;
704
705         for (p = path; *p++;)
706                 continue;
707         len = (size_t)(p - path);
708         if ((copy = malloc(len)) != NULL) {
709                 if (g_Ctoc(path, copy, len)) {
710                         free(copy);
711                         return(GLOB_NOSPACE);
712                 }
713                 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
714         }
715         pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
716
717         return(copy == NULL ? GLOB_NOSPACE : 0);
718 }
719
720 /*
721  * pattern matching function for filenames.  Each occurrence of the *
722  * pattern causes a recursion level.
723  */
724 static int
725 match(name, pat, patend)
726         Char *name, *pat, *patend;
727 {
728         int ok, negate_range;
729         Char c, k;
730
731         while (pat < patend) {
732                 c = *pat++;
733                 switch (c & M_MASK) {
734                 case M_ALL:
735                         if (pat == patend)
736                                 return(1);
737                         do {
738                             if (match(name, pat, patend))
739                                     return(1);
740                         } while (*name++ != EOS);
741                         return(0);
742                 case M_ONE:
743                         if (*name++ == EOS)
744                                 return(0);
745                         break;
746                 case M_SET:
747                         ok = 0;
748                         if ((k = *name++) == EOS)
749                                 return(0);
750                         if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
751                                 ++pat;
752                         while (((c = *pat++) & M_MASK) != M_END)
753                                 if ((*pat & M_MASK) == M_RNG) {
754                                         if (c <= k && k <= pat[1])
755                                                 ok = 1;
756                                         pat += 2;
757                                 } else if (c == k)
758                                         ok = 1;
759                         if (ok == negate_range)
760                                 return(0);
761                         break;
762                 default:
763                         if (*name++ != c)
764                                 return(0);
765                         break;
766                 }
767         }
768         return(*name == EOS);
769 }
770
771 /* Free allocated data belonging to a glob_t structure. */
772 void
773 globfree(pglob)
774         glob_t *pglob;
775 {
776         int i;
777         char **pp;
778
779         if (pglob->gl_pathv != NULL) {
780                 pp = pglob->gl_pathv + pglob->gl_offs;
781                 for (i = pglob->gl_pathc; i--; ++pp)
782                         if (*pp)
783                                 free(*pp);
784                 free(pglob->gl_pathv);
785                 pglob->gl_pathv = NULL;
786         }
787 }
788
789 static DIR *
790 g_opendir(str, pglob)
791         Char *str;
792         glob_t *pglob;
793 {
794         char buf[PATH_MAX];
795
796         if (!*str) {
797                 buf[0] = '.';
798                 buf[1] = '\0';
799         } else {
800                 if (g_Ctoc(str, buf, sizeof(buf)))
801                         return(NULL);
802         }
803         return(opendir(buf));
804 }
805
806 static int
807 g_lstat(fn, sb, pglob)
808         Char *fn;
809         struct stat *sb;
810         glob_t *pglob;
811 {
812         char buf[PATH_MAX];
813
814         if (g_Ctoc(fn, buf, sizeof(buf)))
815                 return(-1);
816         return(lstat(buf, sb));
817 }
818
819 static int
820 g_stat(fn, sb, pglob)
821         Char *fn;
822         struct stat *sb;
823         glob_t *pglob;
824 {
825         char buf[PATH_MAX];
826
827         if (g_Ctoc(fn, buf, sizeof(buf)))
828                 return(-1);
829         return(stat(buf, sb));
830 }
831
832 static Char *
833 g_strchr(str, ch)
834         Char *str;
835         int ch;
836 {
837         do {
838                 if (*str == ch)
839                         return (str);
840         } while (*str++);
841         return (NULL);
842 }
843
844 static int
845 g_Ctoc(str, buf, len)
846         const Char *str;
847         char *buf;
848         unsigned int len;
849 {
850
851         while (len--) {
852                 if ((*buf++ = *str++) == EOS)
853                         return (0);
854         }
855         return (1);
856 }
857
858 #ifdef DEBUG
859 static void
860 qprintf(str, s)
861         const char *str;
862         Char *s;
863 {
864         Char *p;
865
866         (void)printf("%s:\n", str);
867         for (p = s; *p; p++)
868                 (void)printf("%c", CHAR(*p));
869         (void)printf("\n");
870         for (p = s; *p; p++)
871                 (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
872         (void)printf("\n");
873         for (p = s; *p; p++)
874                 (void)printf("%c", ismeta(*p) ? '_' : ' ');
875         (void)printf("\n");
876 }
877 #endif