1: #undef DEBUG
   2: /*
   3:  * Copyright (c) 1989 The Regents of the University of California.
   4:  * 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. All advertising materials mentioning features or use of this software
  18:  *    must display the following acknowledgement:
  19:  *	This product includes software developed by the University of
  20:  *	California, Berkeley and its contributors.
  21:  * 4. Neither the name of the University nor the names of its contributors
  22:  *    may be used to endorse or promote products derived from this software
  23:  *    without specific prior written permission.
  24:  *
  25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35:  * SUCH DAMAGE.
  36:  */
  37: #include "config.h"
  38: #if defined(LIBC_SCCS) && !defined(lint)
  39: static char sccsid[] = "@(#)glob.c	5.12 (Berkeley) 6/24/91";
  40: #endif /* LIBC_SCCS and not lint */
  41: /*
  42:  * Glob: the interface is a superset of the one defined in POSIX 1003.2,
  43:  * draft 9.
  44:  *
  45:  * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
  46:  *
  47:  * Optional extra services, controlled by flags not defined by POSIX:
  48:  *
  49:  * GLOB_QUOTE:
  50:  *	Escaping convention: \ inhibits any special meaning the following
  51:  *	character might have (except \ at end of string is retained).
  52:  * GLOB_MAGCHAR:
  53:  *	Set in gl_flags if pattern contained a globbing character.
  54:  * GLOB_ALTNOT:
  55:  *	Use ^ instead of ! for "not".
  56:  * gl_matchc:
  57:  *	Number of matches in the current invocation of glob.
  58:  */
  59: 
  60: #ifdef notdef
  61: #include <sys/types.h>
  62: #include <sys/param.h>
  63: #include <sys/stat.h>
  64: #include <dirent.h>
  65: #include <ctype.h>
  66: typedef void * ptr_t;
  67: #endif
  68: 
  69: #include "sh.h"
  70: #undef QUOTE
  71: #undef TILDE
  72: #undef META
  73: #undef CHAR
  74: #undef ismeta
  75: #undef Strchr
  76: 
  77: #include <glob.h>
  78: 
  79: #ifndef S_ISDIR
  80: #define S_ISDIR(a)  (((a) & S_IFMT) == S_IFDIR)
  81: #endif
  82: 
  83: #if !defined(S_ISLNK) && defined(S_IFLNK)
  84: #define S_ISLNK(a)  (((a) & S_IFMT) == S_IFLNK)
  85: #endif
  86: 
  87: #if !defined(S_ISLNK) && !defined(lstat)
  88: #define lstat stat
  89: #endif
  90: 
  91: #ifdef notdef
  92: typedef unsigned short Char;
  93: #endif
  94: 
  95: static  int  glob1      __P((Char *, glob_t *, int));
  96: static  int  glob2      __P((Char *, Char *, Char *, glob_t *, int));
  97: static  int  glob3      __P((Char *, Char *, Char *, Char *,
  98:                      glob_t *, int));
  99: static  int  globextend __P((Char *, glob_t *));
 100: static  int  match      __P((Char *, Char *, Char *, int));
 101: static  int  compare    __P((const void *, const void *));
 102: static  DIR *Opendir    __P((Char *));
 103: #ifdef S_IFLNK
 104: static  int  Lstat      __P((Char *, struct stat *));
 105: #endif
 106: static  Char    *Strchr     __P((Char *, int));
 107: #ifdef DEBUG
 108: static  void     qprintf    __P((Char *));
 109: #endif
 110: 
 111: #define DOLLAR      '$'
 112: #define DOT     '.'
 113: #define EOS     '\0'
 114: #define LBRACKET    '['
 115: #define NOT     '!'
 116: #define ALTNOT      '^'
 117: #define QUESTION    '?'
 118: #define QUOTE       '\\'
 119: #define RANGE       '-'
 120: #define RBRACKET    ']'
 121: #define SEP     '/'
 122: #define STAR        '*'
 123: #define TILDE       '~'
 124: #define UNDERSCORE  '_'
 125: 
 126: #ifdef  SHORT_STRINGS
 127: #define M_META      0x8000
 128: #define M_PROTECT   0x4000
 129: #define M_MASK      0xffff
 130: #define M_ASCII     0x00ff
 131: #else
 132: #define M_META      0x0080 /* 0200 */
 133: #define M_PROTECT   0x007f /* 0177 0300 */
 134: #define M_MASK      0x00ff /* 0377 */
 135: #define M_ASCII     0x007f /* 0177 */
 136: #endif	/* SHORT_STRINGS */
 137: 
 138: #define CHAR(c)     ((c)&M_ASCII)
 139: #define META(c)     ((c)|M_META)
 140: #define M_ALL       META('*')
 141: #define M_END       META(']')
 142: #define M_NOT       META('!')
 143: #define M_ALTNOT    META('^')
 144: #define M_ONE       META('?')
 145: #define M_RNG       META('-')
 146: #define M_SET       META('[')
 147: #define ismeta(c)   (((c)&M_META) != 0)
 148: 
 149: /*
 150:  * Need to dodge two kernel bugs:
 151:  * opendir("") != opendir(".")
 152:  * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels.
 153:  *            POSIX specifies that they should be ignored in directories.
 154:  */
 155: 
 156: static DIR *
 157: Opendir(str)
 158:     register Char *str;
 159: {
 160:     char    buf[MAXPATHLEN];
 161:     register char *dc = buf;
 162: 
 163:     if (!*str)
 164:     return (opendir("."));
 165:     while (*dc++ = *str++);
 166:     return (opendir(buf));
 167: }
 168: 
 169: #ifdef S_IFLNK
 170: static int
 171: Lstat(fn, sb)
 172:     register Char *fn;
 173:     struct stat *sb;
 174: {
 175:     char    buf[MAXPATHLEN];
 176:     register char *dc = buf;
 177: 
 178:     while (*dc++ = *fn++);
 179: # ifdef NAMEI_BUG
 180:     {
 181:     int     st;
 182: 
 183:     st = lstat(buf, sb);
 184:     if (*buf)
 185:         dc--;
 186:     return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
 187:     }
 188: # else
 189:     return (lstat(buf, sb));
 190: # endif	/* NAMEI_BUG */
 191: }
 192: #else
 193: #define Lstat Stat
 194: #endif /* S_IFLNK */
 195: 
 196: static int
 197: Stat(fn, sb)
 198:     register Char *fn;
 199:     struct stat *sb;
 200: {
 201:     char    buf[MAXPATHLEN];
 202:     register char *dc = buf;
 203: 
 204:     while (*dc++ = *fn++);
 205: #ifdef NAMEI_BUG
 206:     {
 207:     int     st;
 208: 
 209:     st = lstat(buf, sb);
 210:     if (*buf)
 211:         dc--;
 212:     return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
 213:     }
 214: #else
 215:     return (stat(buf, sb));
 216: #endif /* NAMEI_BUG */
 217: }
 218: 
 219: static Char *
 220: Strchr(str, ch)
 221:     Char *str;
 222:     int ch;
 223: {
 224:     do
 225:     if (*str == ch)
 226:         return (str);
 227:     while (*str++);
 228:     return (NULL);
 229: }
 230: 
 231: #ifdef DEBUG
 232: static void
 233: qprintf(s)
 234: Char *s;
 235: {
 236:     Char *p;
 237: 
 238:     for (p = s; *p; p++)
 239:     printf("%c", *p & 0xff);
 240:     printf("\n");
 241:     for (p = s; *p; p++)
 242:     printf("%c", *p & M_PROTECT ? '"' : ' ');
 243:     printf("\n");
 244:     for (p = s; *p; p++)
 245:     printf("%c", *p & M_META ? '_' : ' ');
 246:     printf("\n");
 247: }
 248: #endif /* DEBUG */
 249: 
 250: static int
 251: compare(p, q)
 252:     const void  *p, *q;
 253: {
 254:     return (strcmp(*(char **) p, *(char **) q));
 255: }
 256: 
 257: /*
 258:  * The main glob() routine: comp_s the pattern (optionally processing
 259:  * quotes), calls glob1() to do the real pattern matching, and finally
 260:  * sorts the list (unless unsorted operation is requested).  Returns 0
 261:  * if things went well, nonzero if errors occurred.  It is not an error
 262:  * to find no matches.
 263:  */
 264: int
 265: glob(pattern, flags, errfunc, pglob)
 266:     const char *pattern;
 267:     int     flags;
 268:     int     (*errfunc) __P((char *, int));
 269:     glob_t *pglob;
 270: {
 271:     int     err, o_pthc;
 272:     Char *bufnext, *bufend, *comp_buf, m_not;
 273:     const unsigned char *comp_pat, *patnext;
 274:     int     c, not;
 275:     Char patbuf[MAXPATHLEN + 1], *qpatnext;
 276:     int     no_match;
 277: 
 278:     patnext = (unsigned char *) pattern;
 279:     if (!(flags & GLOB_APPEND)) {
 280:     pglob->gl_p_c = 0;
 281:     pglob->gl_p_v = NULL;
 282:     if (!(flags & GLOB_DOOFFS))
 283:         pglob->gl_offs = 0;
 284:     }
 285:     pglob->gl_flags = flags & ~GLOB_MAGCHAR;
 286:     pglob->gl_errfunc = errfunc;
 287:     o_pthc = pglob->gl_p_c;
 288:     pglob->gl_matchc = 0;
 289: 
 290:     if (pglob->gl_flags & GLOB_ALTNOT) {
 291:     not = ALTNOT;
 292:     m_not = M_ALTNOT;
 293:     }
 294:     else {
 295:     not = NOT;
 296:     m_not = M_NOT;
 297:     }
 298: 
 299:     no_match = *patnext == not;
 300:     if (no_match)
 301:     patnext++;
 302: 
 303:     bufnext = patbuf;
 304:     bufend = bufnext + MAXPATHLEN;
 305:     comp_buf = bufnext;
 306:     comp_pat = patnext;
 307:     if (flags & GLOB_QUOTE) {
 308:     /* Protect the quoted characters */
 309:     while (bufnext < bufend && (c = *patnext++) != EOS)
 310:         if (c == QUOTE) {
 311:         if ((c = *patnext++) == EOS) {
 312:             c = QUOTE;
 313:             --patnext;
 314:         }
 315:         *bufnext++ = c | M_PROTECT;
 316:         }
 317:         else
 318:         *bufnext++ = c;
 319:     }
 320:     else
 321:     while (bufnext < bufend && (c = *patnext++) != EOS)
 322:         *bufnext++ = c;
 323:     *bufnext = EOS;
 324: 
 325:     bufnext = patbuf;
 326:     qpatnext = patbuf;
 327:     /* we don't need to check for buffer overflow any more */
 328:     while ((c = *qpatnext++) != EOS) {
 329:     switch (c) {
 330:     case LBRACKET:
 331:         pglob->gl_flags |= GLOB_MAGCHAR;
 332:         c = *qpatnext;
 333:         if (c == not)
 334:         ++qpatnext;
 335:         if (*qpatnext == EOS ||
 336:         Strchr(qpatnext + 1, RBRACKET) == NULL) {
 337:         *bufnext++ = LBRACKET;
 338:         if (c == not)
 339:             --qpatnext;
 340:         break;
 341:         }
 342:         *bufnext++ = M_SET;
 343:         if (c == not)
 344:         *bufnext++ = m_not;
 345:         c = *qpatnext++;
 346:         do {
 347:         *bufnext++ = CHAR(c);
 348:         if (*qpatnext == RANGE &&
 349:             (c = qpatnext[1]) != RBRACKET) {
 350:             *bufnext++ = M_RNG;
 351:             *bufnext++ = CHAR(c);
 352:             qpatnext += 2;
 353:         }
 354:         } while ((c = *qpatnext++) != RBRACKET);
 355:         *bufnext++ = M_END;
 356:         break;
 357:     case QUESTION:
 358:         pglob->gl_flags |= GLOB_MAGCHAR;
 359:         *bufnext++ = M_ONE;
 360:         break;
 361:     case STAR:
 362:         pglob->gl_flags |= GLOB_MAGCHAR;
 363:         *bufnext++ = M_ALL;
 364:         break;
 365:     default:
 366:         *bufnext++ = CHAR(c);
 367:         break;
 368:     }
 369:     }
 370:     *bufnext = EOS;
 371: #ifdef DEBUG
 372:     qprintf(patbuf);
 373: #endif
 374: 
 375:     if ((err = glob1(patbuf, pglob, no_match)) != 0)
 376:     return (err);
 377: 
 378:     if (pglob->gl_p_c == o_pthc && flags & GLOB_NOCHECK) {
 379:     if (!(flags & GLOB_QUOTE)) {
 380:         Char *dp = comp_buf;
 381:         const unsigned char *sp = comp_pat;
 382: 
 383:         while (*dp++ = *sp++);
 384:     }
 385:     else {
 386:         /*
 387: 	     * copy pattern, interpreting quotes; this is slightly different
 388: 	     * than the interpretation of quotes above -- which should prevail?
 389: 	     */
 390:         while (*comp_pat != EOS) {
 391:         if (*comp_pat == QUOTE) {
 392:             if (*++comp_pat == EOS)
 393:             --comp_pat;
 394:         }
 395:         *comp_buf++ = (unsigned char) *comp_pat++;
 396:         }
 397:         *comp_buf = EOS;
 398:     }
 399:     return (globextend(patbuf, pglob));
 400:     }
 401:     else if (!(flags & GLOB_NOSORT))
 402:     qsort((char *) (pglob->gl_p_v + pglob->gl_offs + o_pthc),
 403:           pglob->gl_p_c - o_pthc, sizeof(char *), compare);
 404:     return (0);
 405: }
 406: 
 407: static int
 408: glob1(pattern, pglob, no_match)
 409:     Char *pattern;
 410:     glob_t *pglob;
 411:     int     no_match;
 412: {
 413:     Char pathbuf[MAXPATHLEN + 1];
 414: 
 415:     /*
 416:      * a null pathname is invalid -- POSIX 1003.1 sect. 2.4.
 417:      */
 418:     if (*pattern == EOS)
 419:     return (0);
 420:     return (glob2(pathbuf, pathbuf, pattern, pglob, no_match));
 421: }
 422: 
 423: /*
 424:  * functions glob2 and glob3 are mutually recursive; there is one level
 425:  * of recursion for each segment in the pattern that contains one or
 426:  * more meta characters.
 427:  */
 428: static int
 429: glob2(pathbuf, pathend, pattern, pglob, no_match)
 430:     Char *pathbuf, *pathend, *pattern;
 431:     glob_t *pglob;
 432:     int     no_match;
 433: {
 434:     struct stat sbuf;
 435:     int anymeta;
 436:     Char *p, *q;
 437: 
 438:     /*
 439:      * loop over pattern segments until end of pattern or until segment with
 440:      * meta character found.
 441:      */
 442:     anymeta = 0;
 443:     for (;;) {
 444:     if (*pattern == EOS) {  /* end of pattern? */
 445:         *pathend = EOS;
 446:         if (Lstat(pathbuf, &sbuf))
 447:         return (0);
 448: 
 449:         if (((pglob->gl_flags & GLOB_MARK) &&
 450:          pathend[-1] != SEP) &&
 451:         (S_ISDIR(sbuf.st_mode)
 452: #ifdef S_IFLNK
 453:          || (S_ISLNK(sbuf.st_mode) &&
 454:              (Stat(pathbuf, &sbuf) == 0) &&
 455:              S_ISDIR(sbuf.st_mode))
 456: #endif
 457:          )) {
 458:         *pathend++ = SEP;
 459:         *pathend = EOS;
 460:         }
 461:         ++pglob->gl_matchc;
 462:         return (globextend(pathbuf, pglob));
 463:     }
 464: 
 465:     /* find end of next segment, copy tentatively to pathend */
 466:     q = pathend;
 467:     p = pattern;
 468:     while (*p != EOS && *p != SEP) {
 469:         if (ismeta(*p))
 470:         anymeta = 1;
 471:         *q++ = *p++;
 472:     }
 473: 
 474:     if (!anymeta) {     /* no expansion, do next segment */
 475:         pathend = q;
 476:         pattern = p;
 477:         while (*pattern == SEP)
 478:         *pathend++ = *pattern++;
 479:     }
 480:     else            /* need expansion, recurse */
 481:         return (glob3(pathbuf, pathend, pattern, p, pglob, no_match));
 482:     }
 483:     /* NOTREACHED */
 484: }
 485: 
 486: 
 487: static int
 488: glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match)
 489:     Char *pathbuf, *pathend, *pattern, *restpattern;
 490:     glob_t *pglob;
 491:     int     no_match;
 492: {
 493:     extern int errno;
 494:     DIR    *dirp;
 495:     struct dirent *dp;
 496:     int     err;
 497:     Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT;
 498: 
 499:     *pathend = EOS;
 500:     errno = 0;
 501: 
 502:     if (!(dirp = Opendir(pathbuf)))
 503:     /* todo: don't call for ENOENT or ENOTDIR? */
 504:     if (pglob->gl_errfunc &&
 505:         (*pglob->gl_errfunc) (pathbuf, errno) ||
 506:         (pglob->gl_flags & GLOB_ERR))
 507:         return (GLOB_ABEND);
 508:     else
 509:         return (0);
 510: 
 511:     err = 0;
 512: 
 513:     /* search directory for matching names */
 514:     while ((dp = readdir(dirp))) {
 515:     register unsigned char *sc;
 516:     register Char *dc;
 517: 
 518:     /* initial DOT must be matched literally */
 519:     if (dp->d_name[0] == DOT && *pattern != DOT)
 520:         continue;
 521:     for (sc = (unsigned char *) dp->d_name, dc = pathend; *dc++ = *sc++;);
 522:     if (match(pathend, pattern, restpattern, m_not) == no_match) {
 523:         *pathend = EOS;
 524:         continue;
 525:     }
 526:     err = glob2(pathbuf, --dc, restpattern, pglob, no_match);
 527:     if (err)
 528:         break;
 529:     }
 530:     /* todo: check error from readdir? */
 531:     (void) closedir(dirp);
 532:     return (err);
 533: }
 534: 
 535: 
 536: /*
 537:  * Extend the gl_p_v member of a glob_t structure to accomodate a new item,
 538:  * add the new item, and update gl_p_c.
 539:  *
 540:  * This assumes the BSD realloc, which only copies the block when its size
 541:  * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
 542:  * behavior.
 543:  *
 544:  * Return 0 if new item added, error code if memory couldn't be allocated.
 545:  *
 546:  * Invariant of the glob_t structure:
 547:  *	Either gl_p_c is zero and gl_p_v is NULL; or gl_p_c > 0 and
 548:  *	 gl_p_v points to (gl_offs + gl_p_c + 1) items.
 549:  */
 550: #define JPN
 551: #ifndef JPN
 552: static int
 553: globextend(path, pglob)
 554:     Char *path;
 555:     glob_t *pglob;
 556: {
 557:     register char **pathv;
 558:     register int i;
 559:     unsigned int newsize;
 560:     char   *copy;
 561:     Char *p;
 562: 
 563:     newsize = sizeof(*pathv) * (2 + pglob->gl_p_c + pglob->gl_offs);
 564:     pathv = (char **) (pglob->gl_p_v ?
 565:                realloc((ptr_t) pglob->gl_p_v, newsize) :
 566:                malloc((size_t) newsize));
 567:     if (pathv == NULL)
 568:     return (GLOB_NOSPACE);
 569: 
 570:     if (pglob->gl_p_v == NULL && pglob->gl_offs > 0) {
 571:     /* first time around -- clear initial gl_offs items */
 572:     pathv += pglob->gl_offs;
 573:     for (i = pglob->gl_offs; --i >= 0;)
 574:         *--pathv = NULL;
 575:     }
 576:     pglob->gl_p_v = pathv;
 577: 
 578:     for (p = path; *p++;);
 579:     if ((copy = (char *) malloc((size_t) (p - path))) != NULL) {
 580:     register char *dc = copy;
 581:     register Char *sc = path;
 582: 
 583:     while (*dc++ = *sc++);
 584:     pathv[pglob->gl_offs + pglob->gl_p_c++] = copy;
 585:     }
 586:     pathv[pglob->gl_offs + pglob->gl_p_c] = NULL;
 587:     return ((copy == NULL) ? GLOB_NOSPACE : 0);
 588: }
 589: #else
 590: /*
 591:  * jpn: pdp11 version to get around quadradic behavior of above version
 592:  * by managing the increments of storage allocation directly
 593:  * note: gl_offs not used in tcsh6.00.00
 594:  */
 595: #define NFIRST 100
 596: #define NINC 50
 597: 
 598: static int
 599: globextend(path, pglob)
 600:     Char *path;
 601:     glob_t *pglob;
 602: {
 603:     register char **pathv;
 604:     register char **opathv;
 605:     register int i;
 606:     unsigned getmem;
 607:     static unsigned int globsize = 0;
 608:     static unsigned int pathslots = 0;
 609: 
 610:     if (pglob->gl_p_c == 0) {
 611:     /* first pass; allow for NULL at end of array */
 612:     getmem = sizeof(*pathv) * (1 + NFIRST + pglob->gl_offs);
 613:     pathv = (char **) malloc((size_t) getmem);
 614:     if (pathv == NULL)
 615:         return (GLOB_NOSPACE);
 616:     globsize = getmem;
 617: #undef DEBUG
 618: #ifdef  DEBUG
 619:     xprintf("new gl_p_c globsize=%d\n",globsize);
 620: #endif	DEBUG
 621:     pathslots = NFIRST;
 622:     pglob->gl_p_v = pathv;
 623:     if (pglob->gl_offs > 0) {
 624:         /* first time around -- clear initial gl_offs items */
 625:         pathv += pglob->gl_offs;
 626:         for (i = pglob->gl_offs; --i >= 0;)
 627:         *--pathv = NULL;
 628:     }
 629:     } else if (pglob->gl_p_c >= pathslots) {
 630:     /* high water, increment needed */
 631:     char **npp;
 632:     char **opp;
 633:     opathv = pglob->gl_p_v;
 634:     getmem = globsize + (NINC * sizeof(*pathv));
 635:     pathv = (char **) malloc((size_t) getmem);
 636:     if (pathv == NULL)
 637:         return (GLOB_NOSPACE);
 638:     globsize = getmem;
 639: #ifdef  DEBUG
 640:     xprintf("new increment, globsize=%d\n",globsize);
 641: #endif	DEBUG
 642:     pathslots += NINC;
 643: 
 644:     /* copy slots including gl_offs if any, whether or not NULL */
 645:     i = pglob->gl_offs + pglob->gl_p_c ;
 646:     for( npp=pathv, opp=opathv; i > 0 ; i--) {
 647:         *npp++ = *opp++;
 648:     }
 649:     *npp = NULL;    /* no assumption that slots are NULL */
 650:     pglob->gl_p_v = pathv;
 651:     xfree(opathv);  /* free the old base pointer; data has been copied */
 652:     } else {
 653:     /* still room for more */
 654:     pathv = pglob->gl_p_v;
 655: #ifdef  DEBUG
 656:     xprintf("same gl_p_v globsize=%d\n",globsize);
 657: #endif	DEBUG
 658:     }
 659: 
 660:     /* now that a free slot has been assured, save the path there */
 661:     {
 662:     register Char *p;
 663:     char   *copy;
 664:     register char *dc;
 665:     register Char *sc;
 666:     int i;
 667: 
 668:     for (p = path; *p++;);
 669:     i = p - path;
 670:     copy = (char *) malloc((size_t) (p - path));
 671:     if (copy == NULL)
 672:         return (GLOB_NOSPACE);
 673:     dc = copy;
 674:     sc = path;
 675:     while (*dc++ = *sc++);
 676:     pathv[pglob->gl_offs + pglob->gl_p_c] = copy;
 677:     pglob->gl_p_c++;
 678:     pathv[pglob->gl_offs + pglob->gl_p_c] = NULL;
 679: #ifdef  DEBUG
 680:     xprintf("gl_p_c= %d\n",pglob->gl_p_c);
 681: #endif	DEBUG
 682: #ifdef  DEBUG2
 683:     xprintf("path is %s\n",path);
 684:     xprintf("malloc size is %d\n",i);
 685:     xprintf("copy is %s\n",copy);
 686: #endif	DEBUG2
 687:     }
 688:     return (0);
 689: }
 690: #endif	/* pdp11 */
 691: 
 692: /*
 693:  * pattern matching function for filenames.  Each occurrence of the *
 694:  * pattern causes a recursion level.
 695:  */
 696: static  int
 697: match(name, pat, patend, m_not)
 698:     register Char *name, *pat, *patend;
 699:     int m_not;
 700: {
 701:     int ok, negate_range;
 702:     Char c, k;
 703: 
 704:     while (pat < patend) {
 705:     c = *pat++;
 706:     switch (c & M_MASK) {
 707:     case M_ALL:
 708:         if (pat == patend)
 709:         return (1);
 710:         for (; *name != EOS; ++name) {
 711:         if (match(name, pat, patend, m_not))
 712:             return (1);
 713:         }
 714:         return (0);
 715:     case M_ONE:
 716:         if (*name++ == EOS)
 717:         return (0);
 718:         break;
 719:     case M_SET:
 720:         ok = 0;
 721:         k = *name++;
 722:         if (negate_range = ((*pat & M_MASK) == m_not))
 723:         ++pat;
 724:         while (((c = *pat++) & M_MASK) != M_END) {
 725:         if ((*pat & M_MASK) == M_RNG) {
 726:             if (c <= k && k <= pat[1])
 727:             ok = 1;
 728:             pat += 2;
 729:         }
 730:         else if (c == k)
 731:             ok = 1;
 732:         }
 733:         if (ok == negate_range)
 734:         return (0);
 735:         break;
 736:     default:
 737:         if (*name++ != c)
 738:         return (0);
 739:         break;
 740:     }
 741:     }
 742:     return (*name == EOS);
 743: }
 744: 
 745: /* free allocated data belonging to a glob_t structure */
 746: void
 747: globfree(pglob)
 748:     glob_t *pglob;
 749: {
 750:     register int i;
 751:     register char **pp;
 752: 
 753:     if (pglob->gl_p_v != NULL) {
 754:     pp = pglob->gl_p_v + pglob->gl_offs;
 755:     for (i = pglob->gl_p_c; i--; ++pp)
 756:         if (*pp)
 757:         xfree((ptr_t) * pp);
 758:     xfree((ptr_t) pglob->gl_p_v);
 759:     pglob->gl_p_c = 0; /* jpn */
 760:     }
 761: #ifdef DEBUG
 762:     xprintf("did globfree\n");
 763: #endif
 764: }

Defined functions

Lstat defined in line 170; never used
Opendir defined in line 156; used 1 times
Stat defined in line 196; used 2 times
Strchr defined in line 219; never used
compare defined in line 250; used 1 times
glob defined in line 264; never used
glob1 defined in line 407; used 1 times
glob2 defined in line 428; used 2 times
glob3 defined in line 487; used 1 times
globextend defined in line 598; used 2 times
globfree defined in line 746; never used
match defined in line 696; used 2 times
qprintf defined in line 232; used 1 times

Defined variables

sccsid defined in line 39; never used

Defined macros

ALTNOT defined in line 116; used 1 times
CHAR defined in line 138; used 4 times
DOLLAR defined in line 111; never used
DOT defined in line 112; used 2 times
  • in line 519(2)
EOS defined in line 113; used 20 times
JPN defined in line 550; used 1 times
LBRACKET defined in line 114; used 1 times
Lstat defined in line 193; used 1 times
META defined in line 139; used 8 times
M_ALL defined in line 140; used 1 times
M_ALTNOT defined in line 143; used 2 times
M_ASCII defined in line 135; used 1 times
M_END defined in line 141; used 2 times
M_MASK defined in line 134; used 4 times
M_META defined in line 132; used 3 times
M_NOT defined in line 142; used 2 times
M_ONE defined in line 144; used 1 times
M_PROTECT defined in line 133; used 2 times
M_RNG defined in line 145; used 2 times
M_SET defined in line 146; used 1 times
NFIRST defined in line 595; used 2 times
NINC defined in line 596; used 2 times
NOT defined in line 115; used 1 times
QUESTION defined in line 117; never used
QUOTE defined in line 118; used 4 times
RANGE defined in line 119; used 1 times
RBRACKET defined in line 120; used 3 times
SEP defined in line 121; used 4 times
STAR defined in line 122; never used
S_ISDIR defined in line 80; used 5 times
S_ISLNK defined in line 84; used 3 times
TILDE defined in line 123; used 1 times
  • in line 71
UNDERSCORE defined in line 124; never used
ismeta defined in line 147; used 2 times
lstat defined in line 88; used 4 times
Last modified: 1991-08-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4029
Valid CSS Valid XHTML 1.0 Strict