1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.glob.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
   2: /*
   3:  * sh.glob.c: Regular expression expansion
   4:  */
   5: /*-
   6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
   7:  * All rights reserved.
   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(lint) && !defined(pdp11)
  39: static char *rcsid()
  40:     { return "$Id: sh.glob.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
  41: #endif
  42: 
  43: #include "sh.h"
  44: #include <glob.h>
  45: 
  46: static int noglob, nonomatch;
  47: static int pargsiz, gargsiz;
  48: 
  49: /*
  50:  * Values for gflag
  51:  */
  52: #define G_NONE  0       /* No globbing needed			*/
  53: #define G_GLOB  1       /* string contains *?[] characters	*/
  54: #define G_CSH   2       /* string contains ~`{ characters	*/
  55: 
  56: #define GLOBSPACE   100 /* Alloc increment			*/
  57: 
  58: #define LBRC '{'
  59: #define RBRC '}'
  60: #define LBRK '['
  61: #define RBRK ']'
  62: #define EOS '\0'
  63: 
  64: Char  **gargv = NULL;
  65: Char  **pargv = NULL;
  66: #ifdef  notdef
  67: int    gargc = 0;
  68: int    pargc = 0;
  69: #else
  70: long    gargc = 0;
  71: long    pargc = 0;
  72: #endif	/* pdp11 */
  73: 
  74: /*
  75:  * globbing is now done in two stages. In the first pass we expand
  76:  * csh globbing idioms ~`{ and then we proceed doing the normal
  77:  * globbing if needed ?*[
  78:  *
  79:  * Csh type globbing is handled in globexpand() and the rest is
  80:  * handled in glob() which is part of the 4.4BSD libc.
  81:  *
  82:  */
  83: static  Char     *globtilde __P((Char **, Char *));
  84: static  Char     *globequal __P((Char **, Char *));
  85: static  Char    **libglob   __P((Char **));
  86: static  Char    **globexpand    __P((Char **));
  87: static  int   globbrace __P((Char *, Char *, Char ***));
  88: static  void      pword     __P((void));
  89: static  void      psave     __P((int));
  90: static  void      backeval  __P((Char *, bool));
  91: 
  92: static Char *
  93: globtilde(nv, s)
  94:     Char  **nv, *s;
  95: {
  96:     Char    gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
  97: #ifdef apollo
  98:     int slash;
  99: #endif
 100: 
 101:     gstart = gbuf;
 102:     *gstart++ = *s++;
 103:     u = s;
 104:     for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; *s && *s != '/' && b < e;
 105:      *b++ = *s++);
 106:     *b = EOS;
 107:     if (gethdir(gstart)) {
 108:     blkfree(nv);
 109:     if (*gstart)
 110:         stderror(ERR_UNKUSER, short2str(gstart));
 111:     else
 112:         stderror(ERR_NOHOME);
 113:     }
 114:     b = &gstart[Strlen(gstart)];
 115: #ifdef apollo
 116:     slash = gstart[0] == '/' && gstart[1] == '\0';
 117: #endif
 118:     while (*s)
 119:     *b++ = *s++;
 120:     *b = EOS;
 121:     --u;
 122:     xfree((ptr_t) u);
 123: #ifdef apollo
 124:     if (slash && gstart[1] == '/')
 125:     gstart++;
 126: #endif
 127:     return (Strsave(gstart));
 128: }
 129: 
 130: static Char *
 131: globequal(nv, s)
 132:     Char  **nv, *s;
 133: {
 134:     int     dig;
 135:     Char    gp[MAXPATHLEN], *b, *d;
 136: 
 137:     /*
 138:      * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
 139:      * in stack. PWP: let =foobar pass through (for X windows)
 140:      */
 141:     if ((Isdigit(s[1]) || s[1] == '-') && (s[2] == '\0' || s[2] == '/')) {
 142:     dig = (s[1] == '-') ? -1 : s[1] - '0';
 143:     if (!getstakd(gp, dig)) {
 144:         blkfree(nv);
 145:         stderror(ERR_DEEP);
 146:     }
 147:     for (b = &s[2], d = &gp[Strlen(gp)]; *d++ = *b++;);
 148:     xfree((ptr_t) s);
 149:     return (Strsave(gp));
 150:     }
 151:     else
 152:     return (s);
 153: }
 154: 
 155: static int
 156: globbrace(s, p, bl)
 157:     Char   *s, *p, ***bl;
 158: {
 159:     int     i, len;
 160:     Char   *pm, *pe, *lm, *pl;
 161:     Char  **nv, **vl;
 162:     Char    gbuf[MAXPATHLEN];
 163:     int     size = GLOBSPACE;
 164: 
 165:     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
 166:     *vl = NULL;
 167: 
 168:     len = 0;
 169:     /* copy part up to the brace */
 170:     for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
 171:     continue;
 172: 
 173:     /* check for balanced braces */
 174:     for (i = 0, pe = ++p; *pe; pe++)
 175:     if (*pe == LBRK) {
 176:         /* Ignore everything between [] */
 177:         for (++pe; *pe != RBRK && *pe != EOS; pe++)
 178:         continue;
 179:         if (*pe == EOS) {
 180:         blkfree(nv);
 181:         return (-RBRK);
 182:         }
 183:     }
 184:     else if (*pe == LBRC)
 185:         i++;
 186:     else if (*pe == RBRC) {
 187:         if (i == 0)
 188:         break;
 189:         i--;
 190:     }
 191: 
 192:     if (i != 0 || *pe == '\0') {
 193:     blkfree(nv);
 194:     return (-RBRC);
 195:     }
 196: 
 197:     for (i = 0, pl = pm = p; pm <= pe; pm++)
 198:     switch (*pm) {
 199:     case LBRK:
 200:         for (++pm; *pm != RBRK && *pm != EOS; pm++)
 201:         continue;
 202:         if (*pm == EOS) {
 203:         *vl = NULL;
 204:         blkfree(nv);
 205:         return (-RBRK);
 206:         }
 207:         break;
 208:     case LBRC:
 209:         i++;
 210:         break;
 211:     case RBRC:
 212:         if (i) {
 213:         i--;
 214:         break;
 215:         }
 216:         /* FALLTHROUGH */
 217:     case ',':
 218:         if (i && *pm == ',')
 219:         break;
 220:         else {
 221:         Char    savec = *pm;
 222: 
 223:         *pm = EOS;
 224:         (void) Strcpy(lm, pl);
 225:         (void) Strcat(gbuf, pe + 1);
 226:         *pm = savec;
 227:         *vl++ = Strsave(gbuf);
 228:         len++;
 229:         pl = pm + 1;
 230:         if (vl == &nv[size]) {
 231:             size += GLOBSPACE;
 232:             nv = (Char **) xrealloc((ptr_t) nv, (size_t)
 233:                         size * sizeof(Char *));
 234:             vl = &nv[size - GLOBSPACE];
 235:         }
 236:         }
 237:         break;
 238:     }
 239:     *vl = NULL;
 240:     *bl = nv;
 241:     return (len);
 242: }
 243: 
 244: static Char **
 245: globexpand(v)
 246:     Char  **v;
 247: {
 248:     Char   *s;
 249:     Char  **nv, **vl, **el;
 250:     int     size = GLOBSPACE;
 251: 
 252: 
 253:     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
 254:     *vl = NULL;
 255: 
 256:     /*
 257:      * Step 1: expand backquotes.
 258:      */
 259:     while (s = *v++) {
 260:     if (Strchr(s, '`')) {
 261:         int     i;
 262: 
 263:         (void) dobackp(s, 0);
 264:         for (i = 0; i < (int)pargc; i++) {
 265:         *vl++ = pargv[i];
 266:         if (vl == &nv[size]) {
 267:             size += GLOBSPACE;
 268:             nv = (Char **) xrealloc((ptr_t) nv,
 269:                         (size_t) size * sizeof(Char *));
 270:             vl = &nv[size - GLOBSPACE];
 271:         }
 272:         }
 273:         xfree((ptr_t) pargv);
 274:         pargv = NULL;
 275:     }
 276:     else {
 277:         *vl++ = Strsave(s);
 278:         if (vl == &nv[size]) {
 279:         size += GLOBSPACE;
 280:         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
 281:                     size * sizeof(Char *));
 282:         vl = &nv[size - GLOBSPACE];
 283:         }
 284:     }
 285:     }
 286:     *vl = NULL;
 287: 
 288:     if (noglob)
 289:     return (nv);
 290: 
 291:     /*
 292:      * Step 2: expand braces
 293:      */
 294:     el = vl;
 295:     vl = nv;
 296:     for (s = *vl; s; s = *++vl) {
 297:     Char   *b;
 298:     Char  **vp, **bp;
 299: 
 300:     if (b = Strchr(s, LBRC)) {
 301:         Char  **bl;
 302:         int     len;
 303: 
 304:         if ((len = globbrace(s, b, &bl)) < 0) {
 305:         blkfree(nv);
 306:         stderror(ERR_MISSING, -len);
 307:         }
 308:         xfree((ptr_t) s);
 309:         if (len == 1) {
 310:         *vl-- = *bl;
 311:         xfree((ptr_t) bl);
 312:         continue;
 313:         }
 314:         len = blklen(bl);
 315:         if (&el[len] >= &nv[size]) {
 316:         int     l, e;
 317: 
 318:         l = &el[len] - &nv[size];
 319:         size += GLOBSPACE > l ? GLOBSPACE : l;
 320:         l = vl - nv;
 321:         e = el - nv;
 322:         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
 323:                     size * sizeof(Char *));
 324:         vl = nv + l;
 325:         el = nv + e;
 326:         }
 327:         vp = vl--;
 328:         *vp = *bl;
 329:         len--;
 330:         for (bp = el; bp != vp; bp--)
 331:         bp[len] = *bp;
 332:         el += len;
 333:         vp++;
 334:         for (bp = bl + 1; *bp; *vp++ = *bp++)
 335:         continue;
 336:         xfree((ptr_t) bl);
 337:     }
 338: 
 339:     }
 340: 
 341:     /*
 342:      * Step 3: expand ~ =
 343:      */
 344:     vl = nv;
 345:     for (s = *vl; s; s = *++vl)
 346:     switch (*s) {
 347:     case '~':
 348:         *vl = globtilde(nv, s);
 349:         break;
 350:     case '=':
 351:         *vl = globequal(nv, s);
 352:         break;
 353:     default:
 354:         break;
 355:     }
 356:     vl = nv;
 357:     return (vl);
 358: }
 359: 
 360: static Char *
 361: handleone(str, vl, action)
 362:     Char   *str, **vl;
 363:     int     action;
 364: {
 365: 
 366:     Char   *cp, **vlp = vl;
 367: 
 368:     switch (action) {
 369:     case G_ERROR:
 370:     setname(short2str(str));
 371:     blkfree(vl);
 372:     stderror(ERR_NAME | ERR_AMBIG);
 373:     break;
 374:     case G_APPEND:
 375:     trim(vlp);
 376:     str = Strsave(*vlp++);
 377:     do {
 378:         cp = Strspl(str, STRspace);
 379:         xfree((ptr_t) str);
 380:         str = Strspl(cp, *vlp);
 381:         xfree((ptr_t) cp);
 382:     }
 383:     while (*++vlp);
 384:     blkfree(vl);
 385:     break;
 386:     case G_IGNORE:
 387:     str = Strsave(strip(*vlp));
 388:     blkfree(vl);
 389:     break;
 390:     }
 391:     return (str);
 392: }
 393: 
 394: static Char **
 395: libglob(vl)
 396:     Char  **vl;
 397: {
 398:     int     gflgs = GLOB_QUOTE | GLOB_NOCHECK | GLOB_ALTNOT;
 399:     glob_t  globv;
 400:     char   *ptr;
 401: 
 402:     globv.gl_offs = 0;
 403:     globv.gl_p_v = 0;
 404:     globv.gl_p_c = 0;
 405:     nonomatch = adrof(STRnonomatch) != 0;
 406:     do {
 407:     ptr = short2qstr(*vl);
 408:     switch (glob(ptr, gflgs, 0, &globv)) {
 409:     case GLOB_ABEND:
 410:         setname(ptr);
 411:         globfree(&globv);
 412:         stderror(ERR_NAME | ERR_GLOB);
 413:         /* NOTREACHED */
 414:     case GLOB_NOSPACE:
 415:         globfree(&globv);
 416:         stderror(ERR_NOMEM);
 417:         /* NOTREACHED */
 418:     default:
 419:         break;
 420:     }
 421:     if (!nonomatch && (globv.gl_matchc == 0) &&
 422:         (globv.gl_flags & GLOB_MAGCHAR)) {
 423:         globfree(&globv);
 424:         return (NULL);
 425:     }
 426:     gflgs |= GLOB_APPEND;
 427:     }
 428:     while (*++vl);
 429:     vl = blk2short(globv.gl_p_v);
 430:     globfree(&globv);
 431:     return (vl);
 432: }
 433: 
 434: Char   *
 435: globone(str, action)
 436:     Char   *str;
 437:     int     action;
 438: {
 439: 
 440:     Char   *v[2], **vl, **vo;
 441: 
 442:     noglob = adrof(STRnoglob) != 0;
 443:     gflag = 0;
 444:     v[0] = str;
 445:     v[1] = 0;
 446:     tglob(v);
 447:     if (gflag == G_NONE)
 448:     return (strip(Strsave(str)));
 449: 
 450:     if (gflag & G_CSH) {
 451:     /*
 452: 	 * Expand back-quote, tilde and brace
 453: 	 */
 454:     vo = globexpand(v);
 455:     if (noglob || (gflag & G_GLOB) == 0) {
 456:         if (vo[0] == NULL) {
 457:         xfree((ptr_t) vo);
 458:         return (Strsave(STRNULL));
 459:         }
 460:         if (vo[1] != NULL)
 461:         return (handleone(str, vo, action));
 462:         else {
 463:         str = strip(vo[0]);
 464:         xfree((ptr_t) vo);
 465:         return (str);
 466:         }
 467:     }
 468:     }
 469:     else if (noglob || (gflag & G_GLOB) == 0)
 470:     return (strip(Strsave(str)));
 471:     else
 472:     vo = v;
 473: 
 474:     vl = libglob(vo);
 475:     if (gflag & G_CSH)
 476:     blkfree(vo);
 477:     if (vl == NULL) {
 478:     setname(short2str(str));
 479:     stderror(ERR_NAME | ERR_NOMATCH);
 480:     }
 481:     if (vl[0] == NULL) {
 482:     xfree((ptr_t) vl);
 483:     return (Strsave(STRNULL));
 484:     }
 485:     if (vl[1])
 486:     return (handleone(str, vl, action));
 487:     else {
 488:     str = strip(*vl);
 489:     xfree((ptr_t) vl);
 490:     return (str);
 491:     }
 492: }
 493: 
 494: Char  **
 495: globall(v)
 496:     Char  **v;
 497: {
 498:     Char  **vl, **vo;
 499: 
 500:     if (!v || !v[0]) {
 501:     gargv = saveblk(v);
 502:     gargc = blklen(gargv);
 503:     return (gargv);
 504:     }
 505: 
 506:     noglob = adrof(STRnoglob) != 0;
 507: 
 508:     if (gflag & G_CSH)
 509:     /*
 510: 	 * Expand back-quote, tilde and brace
 511: 	 */
 512:     vl = vo = globexpand(v);
 513:     else
 514:     vl = vo = saveblk(v);
 515: 
 516:     if (!noglob && (gflag & G_GLOB)) {
 517:     vl = libglob(vo);
 518:     if (gflag & G_CSH)
 519:         blkfree(vo);
 520:     }
 521: 
 522:     gargc = vl ? blklen(vl) : 0;
 523:     return (gargv = vl);
 524: }
 525: 
 526: void
 527: ginit()
 528: {
 529:     gargsiz = GLOBSPACE;
 530:     gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
 531:     gargv[0] = 0;
 532:     gargc = 0;
 533: }
 534: 
 535: void
 536: rscan(t, f)
 537:     register Char **t;
 538:     void    (*f) ();
 539: {
 540:     register Char *p;
 541: 
 542:     while (p = *t++)
 543:     while (*p)
 544:         (*f) (*p++);
 545: }
 546: 
 547: void
 548: trim(t)
 549:     register Char **t;
 550: {
 551:     register Char *p;
 552: 
 553:     while (p = *t++)
 554:     while (*p)
 555:         *p++ &= TRIM;
 556: }
 557: 
 558: void
 559: tglob(t)
 560:     register Char **t;
 561: {
 562:     register Char *p, c;
 563: 
 564:     while (p = *t++) {
 565:     if (*p == '~' || *p == '=')
 566:         gflag |= G_CSH;
 567:     else if (*p == '{' &&
 568:          (p[1] == '\0' || p[1] == '}' && p[2] == '\0'))
 569:         continue;
 570:     while (c = *p++)
 571:         if (isglob(c))
 572:         gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB;
 573:     }
 574: }
 575: 
 576: /*
 577:  * Command substitute cp.  If literal, then this is a substitution from a
 578:  * << redirection, and so we should not crunch blanks and tabs, separating
 579:  * words only at newlines.
 580:  */
 581: #ifndef TC_BUFSIZ
 582:     /* jpn: needs to fit TERMCAP doing eval of tset results */
 583: #define TC_BUFSIZ 1024+4
 584: #endif
 585: 
 586: Char  **
 587: dobackp(cp, literal)
 588:     Char   *cp;
 589:     bool    literal;
 590: {
 591:     register Char *lp, *rp;
 592:     Char   *ep, word[TC_BUFSIZ];
 593: 
 594:     if (pargv) {
 595: #ifdef notdef
 596:     abort();
 597: #endif
 598:     blkfree(pargv);
 599:     }
 600:     pargsiz = GLOBSPACE;
 601:     pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
 602:     pargv[0] = NOSTR;
 603:     pargcp = pargs = word;
 604:     pargc = 0;
 605:     pnleft = TC_BUFSIZ - 4;
 606:     for (;;) {
 607:     for (lp = cp; *lp != '`'; lp++) {
 608:         if (*lp == 0) {
 609:         if (pargcp != pargs)
 610:             pword();
 611:         return (pargv);
 612:         }
 613:         psave(*lp);
 614:     }
 615:     lp++;
 616:     for (rp = lp; *rp && *rp != '`'; rp++)
 617:         if (*rp == '\\') {
 618:         rp++;
 619:         if (!*rp)
 620:             goto oops;
 621:         }
 622:     if (!*rp)
 623:     oops:  stderror(ERR_UNMATCHED, '`');
 624:     ep = Strsave(lp);
 625:     ep[rp - lp] = 0;
 626:     backeval(ep, literal);
 627:     cp = rp + 1;
 628:     }
 629: }
 630: 
 631: static void
 632: backeval(cp, literal)
 633:     Char   *cp;
 634:     bool    literal;
 635: {
 636:     register int icnt, c;
 637:     register Char *ip;
 638:     struct command faket;
 639:     bool    hadnl;
 640:     int     pvec[2], quoted;
 641:     Char   *fakecom[2], ibuf[BUFSIZ];
 642:     char    tibuf[BUFSIZ];
 643: 
 644:     hadnl = 0;
 645:     icnt = 0;
 646:     quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
 647:     faket.t_dtyp = NODE_COMMAND;
 648:     faket.t_dflg = 0;
 649:     faket.t_dlef = 0;
 650:     faket.t_drit = 0;
 651:     faket.t_dspr = 0;
 652:     faket.t_dcom = fakecom;
 653:     fakecom[0] = STRfk_com1;
 654:     fakecom[1] = 0;
 655: 
 656:     /*
 657:      * We do the psave job to temporarily change the current job so that the
 658:      * following fork is considered a separate job.  This is so that when
 659:      * backquotes are used in a builtin function that calls glob the "current
 660:      * job" is not corrupted.  We only need one level of pushed jobs as long as
 661:      * we are sure to fork here.
 662:      */
 663:     psavejob();
 664: 
 665:     /*
 666:      * It would be nicer if we could integrate this redirection more with the
 667:      * routines in sh.sem.c by doing a fake execute on a builtin function that
 668:      * was piped out.
 669:      */
 670:     mypipe(pvec);
 671:     if (pfork(&faket, -1) == 0) {
 672:     struct wordent paraml;
 673:     struct command *t;
 674: 
 675:     (void) close(pvec[0]);
 676:     (void) dmove(pvec[1], 1);
 677:     (void) dmove(SHDIAG, 2);
 678:     initdesc();
 679:     /*
 680: 	 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
 681: 	 * posted to comp.bugs.4bsd 12 Sep. 1989.
 682: 	 */
 683:     if (pargv)      /* mg, 21.dec.88 */
 684:         blkfree(pargv), pargv = 0, pargsiz = 0;
 685:     /* mg, 21.dec.88 */
 686:     arginp = cp;
 687:     while (*cp)
 688:         *cp++ &= TRIM;
 689:     (void) lex(&paraml);
 690:     if (seterr)
 691:         stderror(ERR_OLD);
 692:     alias(&paraml);
 693:     t = syntax(paraml.next, &paraml, 0);
 694:     if (seterr)
 695:         stderror(ERR_OLD);
 696:     if (t)
 697:         t->t_dflg |= F_NOFORK;
 698: #ifdef SIGTSTP
 699:     (void) sigignore(SIGTSTP);
 700: #endif
 701: #ifdef SIGTTIN
 702:     (void) sigignore(SIGTTIN);
 703: #endif
 704: #ifdef SIGTTOU
 705:     (void) sigignore(SIGTTOU);
 706: #endif
 707:     execute(t, -1, NULL, NULL);
 708:     exitstat();
 709:     }
 710:     xfree((ptr_t) cp);
 711:     (void) close(pvec[1]);
 712:     c = 0;
 713:     ip = NULL;
 714:     do {
 715:     int     cnt = 0;
 716: 
 717:     for (;;) {
 718:         if (icnt == 0) {
 719:         int     i;
 720: 
 721:         ip = ibuf;
 722:         do
 723:             icnt = read(pvec[0], tibuf, BUFSIZ);
 724:         while (icnt == -1 && errno == EINTR);
 725:         if (icnt <= 0) {
 726:             c = -1;
 727:             break;
 728:         }
 729:         for (i = 0; i < icnt; i++)
 730:             ip[i] = (unsigned char) tibuf[i];
 731:         }
 732:         if (hadnl)
 733:         break;
 734:         --icnt;
 735:         c = (*ip++ & TRIM);
 736:         if (c == 0)
 737:         break;
 738:         if (c == '\n') {
 739:         /*
 740: 		 * Continue around the loop one more time, so that we can eat
 741: 		 * the last newline without terminating this word.
 742: 		 */
 743:         hadnl = 1;
 744:         continue;
 745:         }
 746:         if (!quoted && (c == ' ' || c == '\t'))
 747:         break;
 748:         cnt++;
 749:         psave(c | quoted);
 750:     }
 751:     /*
 752: 	 * Unless at end-of-file, we will form a new word here if there were
 753: 	 * characters in the word, or in any case when we take text literally.
 754: 	 * If we didn't make empty words here when literal was set then we
 755: 	 * would lose blank lines.
 756: 	 */
 757:     if (c != -1 && (cnt || literal))
 758:         pword();
 759:     hadnl = 0;
 760:     } while (c >= 0);
 761:     (void) close(pvec[0]);
 762:     pwait();
 763:     prestjob();
 764: }
 765: 
 766: static void
 767: psave(c)
 768:     Char    c;
 769: {
 770:     if (--pnleft <= 0)
 771:     stderror(ERR_WTOOLONG);
 772:     *pargcp++ = c;
 773: }
 774: 
 775: static void
 776: pword()
 777: {
 778:     psave(0);
 779:     if ((int)pargc == pargsiz - 1) {
 780:     pargsiz += GLOBSPACE;
 781:     pargv = (Char **) xrealloc((ptr_t) pargv,
 782:                    (size_t) pargsiz * sizeof(Char *));
 783:     }
 784:     pargv[(int)pargc++] = Strsave(pargs);
 785:     pargv[(int)pargc] = NOSTR;
 786:     pargcp = pargs;
 787:     pnleft = TC_BUFSIZ - 4;
 788: }
 789: 
 790: int
 791: Gmatch(string, pattern)
 792:     register Char *string, *pattern;
 793: {
 794:     register Char stringc, pat_c;
 795:     int     match;
 796:     Char    rangec;
 797: 
 798:     for (;; ++string) {
 799:     stringc = *string & TRIM;
 800:     /*
 801: 	 * apollo comp_r bug: switch (pat_c = *pattern++) { dies
 802: 	 */
 803:     pat_c = *pattern++;
 804:     switch (pat_c) {
 805:     case 0:
 806:         return (stringc == 0);
 807:     case '?':
 808:         if (stringc == 0)
 809:         return (0);
 810:         break;
 811:     case '*':
 812:         if (!*pattern)
 813:         return (1);
 814:         while (*string)
 815:         if (Gmatch(string++, pattern))
 816:             return (1);
 817:         return (0);
 818:     case '[':
 819:         match = 0;
 820:         while (rangec = *pattern++) {
 821:         if (rangec == ']')
 822:             if (match)
 823:             break;
 824:             else
 825:             return (0);
 826:         if (match)
 827:             continue;
 828:         if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
 829:             match = (stringc <= (*pattern & TRIM) &&
 830:                   (*(pattern-2) & TRIM) <= stringc);
 831:             pattern++;
 832:         }
 833:         else
 834:             match = (stringc == (rangec & TRIM));
 835:         }
 836:         if (rangec == 0)
 837:         stderror(ERR_NAME | ERR_MISSING, ']');
 838:         break;
 839:     default:
 840:         if ((pat_c & TRIM) != stringc)
 841:         return (0);
 842:         break;
 843: 
 844:     }
 845:     }
 846: }
 847: 
 848: void
 849: Gcat(s1, s2)
 850:     Char   *s1, *s2;
 851: {
 852:     register Char *p, *q;
 853:     int     n;
 854: 
 855:     for (p = s1; *p++;);
 856:     for (q = s2; *q++;);
 857:     n = (p - s1) + (q - s2) - 1;
 858:     if ((int)++gargc >= gargsiz) {
 859:     gargsiz += GLOBSPACE;
 860:     gargv = (Char **) xrealloc((ptr_t) gargv,
 861:                    (size_t) gargsiz * sizeof(Char *));
 862:     }
 863:     gargv[(int)gargc] = 0;
 864:     p = gargv[(int)gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
 865:     for (q = s1; *p++ = *q++;);
 866:     for (p--, q = s2; *p++ = *q++;);
 867: }
 868: 
 869: #ifdef FILEC
 870: int
 871: sortscmp(a, b)
 872:     register Char **a, **b;
 873: {
 874: #if defined(NLS) && !defined(NOSTRCOLL)
 875:     char    buf[2048];
 876: 
 877: #endif
 878: 
 879:     if (!a)         /* check for NULL */
 880:     return (b ? 1 : 0);
 881:     if (!b)
 882:     return (-1);
 883: 
 884:     if (!*a)            /* check for NULL */
 885:     return (*b ? 1 : 0);
 886:     if (!*b)
 887:     return (-1);
 888: 
 889: #if defined(NLS) && !defined(NOSTRCOLL)
 890:     (void) strcpy(buf, short2str(*a));
 891:     return ((int) strcoll(buf, short2str(*b)));
 892: #else
 893:     return ((int) Strcmp(*a, *b));
 894: #endif
 895: }
 896: 
 897: #endif

Defined functions

Gcat defined in line 848; used 4 times
backeval defined in line 631; used 1 times
dobackp defined in line 586; used 2 times
ginit defined in line 526; used 1 times
globbrace defined in line 155; used 1 times
globequal defined in line 130; used 1 times
globexpand defined in line 244; used 2 times
globtilde defined in line 92; used 1 times
handleone defined in line 360; used 2 times
libglob defined in line 394; used 2 times
psave defined in line 766; used 3 times
pword defined in line 775; used 2 times
rcsid defined in line 39; never used
rscan defined in line 535; used 1 times
sortscmp defined in line 870; used 1 times

Defined variables

gargc defined in line 70; used 7 times
gargsiz defined in line 47; used 5 times
gargv defined in line 64; used 10 times
noglob defined in line 46; used 6 times
nonomatch defined in line 46; used 2 times
pargc defined in line 71; used 5 times
pargsiz defined in line 47; used 6 times
pargv defined in line 65; used 15 times

Defined macros

EOS defined in line 62; used 7 times
GLOBSPACE defined in line 56; used 14 times
G_CSH defined in line 54; used 6 times
G_GLOB defined in line 53; used 4 times
G_NONE defined in line 52; used 1 times
LBRC defined in line 58; used 3 times
LBRK defined in line 60; used 1 times
RBRC defined in line 59; used 2 times
RBRK defined in line 61; used 4 times
TC_BUFSIZ defined in line 583; used 4 times
Last modified: 1991-10-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5099
Valid CSS Valid XHTML 1.0 Strict