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