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