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