# 2.11BSD#431 - /usr/src/bin/tcsh/glob.c

##### Functions

    glob              X
    globfree          X

##### Macros

    ALTNOT            X
    CHAR              X
    DOLLAR            X
    DOT               X
    EOS               X
    JPN               X
    LBRACKET          X
    Lstat             X
    META              X
    M_ALL             X
    M_ALTNOT          X
    M_ASCII           X
    M_END             X
    M_MASK            X
    M_META            X
    M_NOT             X
    M_ONE             X
    M_PROTECT         X
    M_RNG             X
    M_SET             X
    NFIRST            X
    NINC              X
    NOT               X
    QUESTION          X
    QUOTE             X
    RANGE             X
    RBRACKET          X
    SEP               X
    STAR              X
    S_ISDIR           X
    S_ISLNK           X
    TILDE             X
    UNDERSCORE        X
    ismeta            X
    lstat             X

       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

- in line 502

Stat defined in line 196; used 2 times

- in line 193, 454

Strchr defined in line 219; never used
compare defined in line 250; used 1 times

- in line 403

glob defined in line 264; never used
glob1 defined in line 407; used 1 times

- in line 375

glob2 defined in line 428; used 2 times

- in line 420, 526

glob3 defined in line 487; used 1 times

- in line 481

globextend defined in line 598; used 2 times

- in line 399, 462

globfree defined in line 746; never used
match defined in line 696; used 2 times

- in line 522, 711

qprintf defined in line 232; used 1 times

- in line 372

#### Defined variables

sccsid defined in line 39; never used

#### Defined macros

ALTNOT defined in line 116; used 1 times

- in line 291

CHAR defined in line 138; used 4 times

- in line 73, 347-351(2), 366

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

- in line 309-311(2), 321-328(3), 335, 370, 390-397(3), 418, 444-445(2), 459, 468, 499, 523, 710, 716, 742

JPN defined in line 550; used 1 times

- in line 551

LBRACKET defined in line 114; used 1 times

- in line 337

Lstat defined in line 193; used 1 times

- in line 446

META defined in line 139; used 8 times

- in line 72, 140-146(7)

M_ALL defined in line 140; used 1 times

- in line 363

M_ALTNOT defined in line 143; used 2 times

- in line 292, 497

M_ASCII defined in line 135; used 1 times

- in line 138

M_END defined in line 141; used 2 times

- in line 355, 724

M_MASK defined in line 134; used 4 times

- in line 706, 722-725(3)

M_META defined in line 132; used 3 times

- in line 139, 147, 245

M_NOT defined in line 142; used 2 times

- in line 296, 497

M_ONE defined in line 144; used 1 times

- in line 359

M_PROTECT defined in line 133; used 2 times

- in line 242, 315

M_RNG defined in line 145; used 2 times

- in line 350, 725

M_SET defined in line 146; used 1 times

- in line 342

NFIRST defined in line 595; used 2 times

- in line 612, 621

NINC defined in line 596; used 2 times

- in line 634, 642

NOT defined in line 115; used 1 times

- in line 295

QUESTION defined in line 117; never used
QUOTE defined in line 118; used 4 times

- in line 70, 310-312(2), 391

RANGE defined in line 119; used 1 times

- in line 348

RBRACKET defined in line 120; used 3 times

- in line 336, 349-354(2)

SEP defined in line 121; used 4 times

- in line 450, 458, 468, 477

STAR defined in line 122; never used
S_ISDIR defined in line 80; used 5 times

- in line 79, 186, 212, 451-455(2)

S_ISLNK defined in line 84; used 3 times

- in line 83-87(2), 453

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

- in line 74, 469

lstat defined in line 88; used 4 times

- in line 87, 183, 189, 209

Last modified: 1991-08-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1430 |