Home | History | Annotate | Line # | Download | only in csh
glob.c revision 1.8
      1 /*-
      2  * Copyright (c) 1980, 1991, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 /*static char sccsid[] = "from: @(#)glob.c	8.1 (Berkeley) 5/31/93";*/
     36 static char *rcsid = "$Id: glob.c,v 1.8 1994/09/21 00:10:56 mycroft Exp $";
     37 #endif /* not lint */
     38 
     39 #include <sys/param.h>
     40 #include <glob.h>
     41 #include <errno.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include <unistd.h>
     45 #if __STDC__
     46 # include <stdarg.h>
     47 #else
     48 # include <varargs.h>
     49 #endif
     50 
     51 #include "csh.h"
     52 #include "extern.h"
     53 
     54 static int noglob;
     55 static int pargsiz, gargsiz;
     56 
     57 /*
     58  * Values for gflag
     59  */
     60 #define	G_NONE	0		/* No globbing needed			*/
     61 #define	G_GLOB	1		/* string contains *?[] characters	*/
     62 #define	G_CSH	2		/* string contains ~`{ characters	*/
     63 
     64 #define	GLOBSPACE	100	/* Alloc increment			*/
     65 
     66 #define LBRC '{'
     67 #define RBRC '}'
     68 #define LBRK '['
     69 #define RBRK ']'
     70 #define EOS '\0'
     71 
     72 Char  **gargv = NULL;
     73 long    gargc = 0;
     74 Char  **pargv = NULL;
     75 long    pargc = 0;
     76 
     77 /*
     78  * globbing is now done in two stages. In the first pass we expand
     79  * csh globbing idioms ~`{ and then we proceed doing the normal
     80  * globbing if needed ?*[
     81  *
     82  * Csh type globbing is handled in globexpand() and the rest is
     83  * handled in glob() which is part of the 4.4BSD libc.
     84  *
     85  */
     86 static Char	*globtilde __P((Char **, Char *));
     87 static Char	**libglob __P((Char **));
     88 static Char	**globexpand __P((Char **));
     89 static int	globbrace __P((Char *, Char *, Char ***));
     90 static void	expbrace __P((Char ***, Char ***, int));
     91 static int	pmatch __P((Char *, Char *));
     92 static void	pword __P((void));
     93 static void	psave __P((int));
     94 static void	backeval __P((Char *, bool));
     95 
     96 
     97 static Char *
     98 globtilde(nv, s)
     99     Char  **nv, *s;
    100 {
    101     Char    gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
    102 
    103     gstart = gbuf;
    104     *gstart++ = *s++;
    105     u = s;
    106     for (b = gstart, e = &gbuf[MAXPATHLEN - 1];
    107 	 *s && *s != '/' && *s != ':' && b < e;
    108 	 *b++ = *s++)
    109 	 continue;
    110     *b = EOS;
    111     if (gethdir(gstart)) {
    112 	blkfree(nv);
    113 	if (*gstart)
    114 	    stderror(ERR_UNKUSER, vis_str(gstart));
    115 	else
    116 	    stderror(ERR_NOHOME);
    117     }
    118     b = &gstart[Strlen(gstart)];
    119     while (*s)
    120 	*b++ = *s++;
    121     *b = EOS;
    122     --u;
    123     xfree((ptr_t) u);
    124     return (Strsave(gstart));
    125 }
    126 
    127 static int
    128 globbrace(s, p, bl)
    129     Char   *s, *p, ***bl;
    130 {
    131     int     i, len;
    132     Char   *pm, *pe, *lm, *pl;
    133     Char  **nv, **vl;
    134     Char    gbuf[MAXPATHLEN];
    135     int     size = GLOBSPACE;
    136 
    137     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
    138     *vl = NULL;
    139 
    140     len = 0;
    141     /* copy part up to the brace */
    142     for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
    143 	continue;
    144 
    145     /* check for balanced braces */
    146     for (i = 0, pe = ++p; *pe; pe++)
    147 	if (*pe == LBRK) {
    148 	    /* Ignore everything between [] */
    149 	    for (++pe; *pe != RBRK && *pe != EOS; pe++)
    150 		continue;
    151 	    if (*pe == EOS) {
    152 		blkfree(nv);
    153 		return (-RBRK);
    154 	    }
    155 	}
    156 	else if (*pe == LBRC)
    157 	    i++;
    158 	else if (*pe == RBRC) {
    159 	    if (i == 0)
    160 		break;
    161 	    i--;
    162 	}
    163 
    164     if (i != 0 || *pe == '\0') {
    165 	blkfree(nv);
    166 	return (-RBRC);
    167     }
    168 
    169     for (i = 0, pl = pm = p; pm <= pe; pm++)
    170 	switch (*pm) {
    171 	case LBRK:
    172 	    for (++pm; *pm != RBRK && *pm != EOS; pm++)
    173 		continue;
    174 	    if (*pm == EOS) {
    175 		*vl = NULL;
    176 		blkfree(nv);
    177 		return (-RBRK);
    178 	    }
    179 	    break;
    180 	case LBRC:
    181 	    i++;
    182 	    break;
    183 	case RBRC:
    184 	    if (i) {
    185 		i--;
    186 		break;
    187 	    }
    188 	    /* FALLTHROUGH */
    189 	case ',':
    190 	    if (i && *pm == ',')
    191 		break;
    192 	    else {
    193 		Char    savec = *pm;
    194 
    195 		*pm = EOS;
    196 		(void) Strcpy(lm, pl);
    197 		(void) Strcat(gbuf, pe + 1);
    198 		*pm = savec;
    199 		*vl++ = Strsave(gbuf);
    200 		len++;
    201 		pl = pm + 1;
    202 		if (vl == &nv[size]) {
    203 		    size += GLOBSPACE;
    204 		    nv = (Char **) xrealloc((ptr_t) nv, (size_t)
    205 					    size * sizeof(Char *));
    206 		    vl = &nv[size - GLOBSPACE];
    207 		}
    208 	    }
    209 	    break;
    210 	default:
    211 	    break;
    212 	}
    213     *vl = NULL;
    214     *bl = nv;
    215     return (len);
    216 }
    217 
    218 
    219 static void
    220 expbrace(nvp, elp, size)
    221     Char ***nvp, ***elp;
    222     int size;
    223 {
    224     Char **vl, **el, **nv, *s;
    225 
    226     vl = nv = *nvp;
    227     if (elp != NULL)
    228 	el = *elp;
    229     else
    230 	for (el = vl; *el; el++)
    231 	    continue;
    232 
    233     for (s = *vl; s; s = *++vl) {
    234 	Char   *b;
    235 	Char  **vp, **bp;
    236 
    237 	/* leave {} untouched for find */
    238 	if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
    239 	    continue;
    240 	if ((b = Strchr(s, '{')) != NULL) {
    241 	    Char  **bl;
    242 	    int     len;
    243 
    244 	    if ((len = globbrace(s, b, &bl)) < 0) {
    245 		xfree((ptr_t) nv);
    246 		stderror(ERR_MISSING, -len);
    247 	    }
    248 	    xfree((ptr_t) s);
    249 	    if (len == 1) {
    250 		*vl-- = *bl;
    251 		xfree((ptr_t) bl);
    252 		continue;
    253 	    }
    254 	    len = blklen(bl);
    255 	    if (&el[len] >= &nv[size]) {
    256 		int     l, e;
    257 
    258 		l = &el[len] - &nv[size];
    259 		size += GLOBSPACE > l ? GLOBSPACE : l;
    260 		l = vl - nv;
    261 		e = el - nv;
    262 		nv = (Char **) xrealloc((ptr_t) nv, (size_t)
    263 					size * sizeof(Char *));
    264 		vl = nv + l;
    265 		el = nv + e;
    266 	    }
    267 	    vp = vl--;
    268 	    *vp = *bl;
    269 	    len--;
    270 	    for (bp = el; bp != vp; bp--)
    271 		bp[len] = *bp;
    272 	    el += len;
    273 	    vp++;
    274 	    for (bp = bl + 1; *bp; *vp++ = *bp++)
    275 		continue;
    276 	    xfree((ptr_t) bl);
    277 	}
    278 
    279     }
    280     if (elp != NULL)
    281 	*elp = el;
    282     *nvp = nv;
    283 }
    284 
    285 static Char **
    286 globexpand(v)
    287     Char  **v;
    288 {
    289     Char   *s;
    290     Char  **nv, **vl, **el;
    291     int     size = GLOBSPACE;
    292 
    293 
    294     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
    295     *vl = NULL;
    296 
    297     /*
    298      * Step 1: expand backquotes.
    299      */
    300     while ((s = *v++) != NULL) {
    301 	if (Strchr(s, '`')) {
    302 	    int     i;
    303 
    304 	    (void) dobackp(s, 0);
    305 	    for (i = 0; i < pargc; i++) {
    306 		*vl++ = pargv[i];
    307 		if (vl == &nv[size]) {
    308 		    size += GLOBSPACE;
    309 		    nv = (Char **) xrealloc((ptr_t) nv,
    310 					    (size_t) size * sizeof(Char *));
    311 		    vl = &nv[size - GLOBSPACE];
    312 		}
    313 	    }
    314 	    xfree((ptr_t) pargv);
    315 	    pargv = NULL;
    316 	}
    317 	else {
    318 	    *vl++ = Strsave(s);
    319 	    if (vl == &nv[size]) {
    320 		size += GLOBSPACE;
    321 		nv = (Char **) xrealloc((ptr_t) nv, (size_t)
    322 					size * sizeof(Char *));
    323 		vl = &nv[size - GLOBSPACE];
    324 	    }
    325 	}
    326     }
    327     *vl = NULL;
    328 
    329     if (noglob)
    330 	return (nv);
    331 
    332     /*
    333      * Step 2: expand braces
    334      */
    335     el = vl;
    336     expbrace(&nv, &el, size);
    337 
    338     /*
    339      * Step 3: expand ~
    340      */
    341     vl = nv;
    342     for (s = *vl; s; s = *++vl)
    343 	if (*s == '~')
    344 	    *vl = globtilde(nv, s);
    345     vl = nv;
    346     return (vl);
    347 }
    348 
    349 static Char *
    350 handleone(str, vl, action)
    351     Char   *str, **vl;
    352     int     action;
    353 {
    354 
    355     Char   *cp, **vlp = vl;
    356 
    357     switch (action) {
    358     case G_ERROR:
    359 	setname(vis_str(str));
    360 	blkfree(vl);
    361 	stderror(ERR_NAME | ERR_AMBIG);
    362 	break;
    363     case G_APPEND:
    364 	trim(vlp);
    365 	str = Strsave(*vlp++);
    366 	do {
    367 	    cp = Strspl(str, STRspace);
    368 	    xfree((ptr_t) str);
    369 	    str = Strspl(cp, *vlp);
    370 	    xfree((ptr_t) cp);
    371 	}
    372 	while (*++vlp);
    373 	blkfree(vl);
    374 	break;
    375     case G_IGNORE:
    376 	str = Strsave(strip(*vlp));
    377 	blkfree(vl);
    378 	break;
    379     default:
    380 	break;
    381     }
    382     return (str);
    383 }
    384 
    385 static Char **
    386 libglob(vl)
    387     Char  **vl;
    388 {
    389     int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
    390     glob_t  globv;
    391     char   *ptr;
    392     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
    393 
    394     if (!vl || !vl[0])
    395 	return (vl);
    396 
    397     globv.gl_offs = 0;
    398     globv.gl_pathv = 0;
    399     globv.gl_pathc = 0;
    400 
    401     if (nonomatch)
    402 	gflgs |= GLOB_NOCHECK;
    403 
    404     do {
    405 	ptr = short2qstr(*vl);
    406 	switch (glob(ptr, gflgs, 0, &globv)) {
    407 	case GLOB_ABEND:
    408 	    setname(vis_str(*vl));
    409 	    stderror(ERR_NAME | ERR_GLOB);
    410 	    /* NOTREACHED */
    411 	case GLOB_NOSPACE:
    412 	    stderror(ERR_NOMEM);
    413 	    /* NOTREACHED */
    414 	default:
    415 	    break;
    416 	}
    417 	if (globv.gl_flags & GLOB_MAGCHAR) {
    418 	    match |= (globv.gl_matchc != 0);
    419 	    magic = 1;
    420 	}
    421 	gflgs |= GLOB_APPEND;
    422     }
    423     while (*++vl);
    424     vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
    425 	NULL : blk2short(globv.gl_pathv);
    426     globfree(&globv);
    427     return (vl);
    428 }
    429 
    430 Char   *
    431 globone(str, action)
    432     Char   *str;
    433     int     action;
    434 {
    435     Char   *v[2], **vl, **vo;
    436     int    gflg;
    437 
    438     noglob = adrof(STRnoglob) != 0;
    439     gflag = 0;
    440     v[0] = str;
    441     v[1] = 0;
    442     tglob(v);
    443     gflg = gflag;
    444     if (gflg == G_NONE)
    445 	return (strip(Strsave(str)));
    446 
    447     if (gflg & G_CSH) {
    448 	/*
    449 	 * Expand back-quote, tilde and brace
    450 	 */
    451 	vo = globexpand(v);
    452 	if (noglob || (gflg & G_GLOB) == 0) {
    453 	    if (vo[0] == NULL) {
    454 		xfree((ptr_t) vo);
    455 		return (Strsave(STRNULL));
    456 	    }
    457 	    if (vo[1] != NULL)
    458 		return (handleone(str, vo, action));
    459 	    else {
    460 		str = strip(vo[0]);
    461 		xfree((ptr_t) vo);
    462 		return (str);
    463 	    }
    464 	}
    465     }
    466     else if (noglob || (gflg & G_GLOB) == 0)
    467 	return (strip(Strsave(str)));
    468     else
    469 	vo = v;
    470 
    471     vl = libglob(vo);
    472     if ((gflg & G_CSH) && vl != vo)
    473 	blkfree(vo);
    474     if (vl == NULL) {
    475 	setname(vis_str(str));
    476 	stderror(ERR_NAME | ERR_NOMATCH);
    477     }
    478     if (vl[0] == NULL) {
    479 	xfree((ptr_t) vl);
    480 	return (Strsave(STRNULL));
    481     }
    482     if (vl[1] != NULL)
    483 	return (handleone(str, vl, action));
    484     else {
    485 	str = strip(*vl);
    486 	xfree((ptr_t) vl);
    487 	return (str);
    488     }
    489 }
    490 
    491 Char  **
    492 globall(v)
    493     Char  **v;
    494 {
    495     Char  **vl, **vo;
    496     int   gflg = gflag;
    497 
    498     if (!v || !v[0]) {
    499 	gargv = saveblk(v);
    500 	gargc = blklen(gargv);
    501 	return (gargv);
    502     }
    503 
    504     noglob = adrof(STRnoglob) != 0;
    505 
    506     if (gflg & G_CSH)
    507 	/*
    508 	 * Expand back-quote, tilde and brace
    509 	 */
    510 	vl = vo = globexpand(v);
    511     else
    512 	vl = vo = saveblk(v);
    513 
    514     if (!noglob && (gflg & G_GLOB) && *vl) {
    515 	vl = libglob(vo);
    516 	if ((gflg & G_CSH) && vl != vo)
    517 	    blkfree(vo);
    518     }
    519     else
    520 	trim(vl);
    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++) != NULL)
    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++) != NULL)
    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++) != NULL) {
    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++) != '\0') {
    571 	    /*
    572 	     * eat everything inside the matching backquotes
    573 	     */
    574 	    if (c == '`') {
    575 		gflag |= G_CSH;
    576 		while (*p && *p != '`')
    577 		    if (*p++ == '\\') {
    578 			if (*p)		/* Quoted chars */
    579 			    p++;
    580 			else
    581 			    break;
    582 		    }
    583 		if (*p)			/* The matching ` */
    584 		    p++;
    585 		else
    586 		    break;
    587 	    }
    588 	    else if (c == '{')
    589 		gflag |= G_CSH;
    590 	    else if (isglob(c))
    591 		gflag |= G_GLOB;
    592 	}
    593     }
    594 }
    595 
    596 /*
    597  * Command substitute cp.  If literal, then this is a substitution from a
    598  * << redirection, and so we should not crunch blanks and tabs, separating
    599  * words only at newlines.
    600  */
    601 Char  **
    602 dobackp(cp, literal)
    603     Char   *cp;
    604     bool    literal;
    605 {
    606     register Char *lp, *rp;
    607     Char   *ep, word[MAXPATHLEN];
    608     int ogflag = gflag;
    609 
    610     if (pargv) {
    611 #ifdef notdef
    612 	abort();
    613 #endif
    614 	blkfree(pargv);
    615     }
    616     pargsiz = GLOBSPACE;
    617     pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
    618     pargv[0] = NULL;
    619     pargcp = pargs = word;
    620     pargc = 0;
    621     pnleft = MAXPATHLEN - 4;
    622     for (;;) {
    623 	for (lp = cp; *lp != '`'; lp++) {
    624 	    if (*lp == 0) {
    625 		if (pargcp != pargs)
    626 		    pword();
    627 		gflag = ogflag;
    628 		return (pargv);
    629 	    }
    630 	    psave(*lp);
    631 	}
    632 	lp++;
    633 	for (rp = lp; *rp && *rp != '`'; rp++)
    634 	    if (*rp == '\\') {
    635 		rp++;
    636 		if (!*rp)
    637 		    goto oops;
    638 	    }
    639 	if (!*rp)
    640     oops:  stderror(ERR_UNMATCHED, '`');
    641 	ep = Strsave(lp);
    642 	ep[rp - lp] = 0;
    643 	backeval(ep, literal);
    644 	cp = rp + 1;
    645     }
    646 }
    647 
    648 static void
    649 backeval(cp, literal)
    650     Char   *cp;
    651     bool    literal;
    652 {
    653     register int icnt, c;
    654     register Char *ip;
    655     struct command faket;
    656     bool    hadnl;
    657     int     pvec[2], quoted;
    658     Char   *fakecom[2], ibuf[BUFSIZ];
    659     char    tibuf[BUFSIZ];
    660 
    661     hadnl = 0;
    662     icnt = 0;
    663     quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
    664     faket.t_dtyp = NODE_COMMAND;
    665     faket.t_dflg = 0;
    666     faket.t_dlef = 0;
    667     faket.t_drit = 0;
    668     faket.t_dspr = 0;
    669     faket.t_dcom = fakecom;
    670     fakecom[0] = STRfakecom1;
    671     fakecom[1] = 0;
    672 
    673     /*
    674      * We do the psave job to temporarily change the current job so that the
    675      * following fork is considered a separate job.  This is so that when
    676      * backquotes are used in a builtin function that calls glob the "current
    677      * job" is not corrupted.  We only need one level of pushed jobs as long as
    678      * we are sure to fork here.
    679      */
    680     psavejob();
    681 
    682     /*
    683      * It would be nicer if we could integrate this redirection more with the
    684      * routines in sh.sem.c by doing a fake execute on a builtin function that
    685      * was piped out.
    686      */
    687     mypipe(pvec);
    688     if (pfork(&faket, -1) == 0) {
    689 	struct wordent paraml;
    690 	struct command *t;
    691 
    692 	(void) close(pvec[0]);
    693 	(void) dmove(pvec[1], 1);
    694 	(void) dmove(SHERR, 2);
    695 	initdesc();
    696 	/*
    697 	 * Bugfix for nested backquotes by Michael Greim <greim (at) sbsvax.UUCP>,
    698 	 * posted to comp.bugs.4bsd 12 Sep. 1989.
    699 	 */
    700 	if (pargv)		/* mg, 21.dec.88 */
    701 	    blkfree(pargv), pargv = 0, pargsiz = 0;
    702 	/* mg, 21.dec.88 */
    703 	arginp = cp;
    704 	while (*cp)
    705 	    *cp++ &= TRIM;
    706 
    707         /*
    708 	 * In the child ``forget'' everything about current aliases or
    709 	 * eval vectors.
    710 	 */
    711 	alvec = NULL;
    712 	evalvec = NULL;
    713 	alvecp = NULL;
    714 	evalp = NULL;
    715 	(void) lex(&paraml);
    716 	if (seterr)
    717 	    stderror(ERR_OLD);
    718 	alias(&paraml);
    719 	t = syntax(paraml.next, &paraml, 0);
    720 	if (seterr)
    721 	    stderror(ERR_OLD);
    722 	if (t)
    723 	    t->t_dflg |= F_NOFORK;
    724 	(void) signal(SIGTSTP, SIG_IGN);
    725 	(void) signal(SIGTTIN, SIG_IGN);
    726 	(void) signal(SIGTTOU, SIG_IGN);
    727 	execute(t, -1, NULL, NULL);
    728 	exitstat();
    729     }
    730     xfree((ptr_t) cp);
    731     (void) close(pvec[1]);
    732     c = 0;
    733     ip = NULL;
    734     do {
    735 	int     cnt = 0;
    736 
    737 	for (;;) {
    738 	    if (icnt == 0) {
    739 		int     i;
    740 
    741 		ip = ibuf;
    742 		do
    743 		    icnt = read(pvec[0], tibuf, BUFSIZ);
    744 		while (icnt == -1 && errno == EINTR);
    745 		if (icnt <= 0) {
    746 		    c = -1;
    747 		    break;
    748 		}
    749 		for (i = 0; i < icnt; i++)
    750 		    ip[i] = (unsigned char) tibuf[i];
    751 	    }
    752 	    if (hadnl)
    753 		break;
    754 	    --icnt;
    755 	    c = (*ip++ & TRIM);
    756 	    if (c == 0)
    757 		break;
    758 	    if (c == '\n') {
    759 		/*
    760 		 * Continue around the loop one more time, so that we can eat
    761 		 * the last newline without terminating this word.
    762 		 */
    763 		hadnl = 1;
    764 		continue;
    765 	    }
    766 	    if (!quoted && (c == ' ' || c == '\t'))
    767 		break;
    768 	    cnt++;
    769 	    psave(c | quoted);
    770 	}
    771 	/*
    772 	 * Unless at end-of-file, we will form a new word here if there were
    773 	 * characters in the word, or in any case when we take text literally.
    774 	 * If we didn't make empty words here when literal was set then we
    775 	 * would lose blank lines.
    776 	 */
    777 	if (c != -1 && (cnt || literal))
    778 	    pword();
    779 	hadnl = 0;
    780     } while (c >= 0);
    781     (void) close(pvec[0]);
    782     pwait();
    783     prestjob();
    784 }
    785 
    786 static void
    787 psave(c)
    788     int    c;
    789 {
    790     if (--pnleft <= 0)
    791 	stderror(ERR_WTOOLONG);
    792     *pargcp++ = c;
    793 }
    794 
    795 static void
    796 pword()
    797 {
    798     psave(0);
    799     if (pargc == pargsiz - 1) {
    800 	pargsiz += GLOBSPACE;
    801 	pargv = (Char **) xrealloc((ptr_t) pargv,
    802 				   (size_t) pargsiz * sizeof(Char *));
    803     }
    804     pargv[pargc++] = Strsave(pargs);
    805     pargv[pargc] = NULL;
    806     pargcp = pargs;
    807     pnleft = MAXPATHLEN - 4;
    808 }
    809 
    810 int
    811 Gmatch(string, pattern)
    812     Char *string, *pattern;
    813 {
    814     Char **blk, **p;
    815     int	   gpol = 1, gres = 0;
    816 
    817     if (*pattern == '^') {
    818 	gpol = 0;
    819 	pattern++;
    820     }
    821 
    822     blk = (Char **) xmalloc(GLOBSPACE * sizeof(Char *));
    823     blk[0] = Strsave(pattern);
    824     blk[1] = NULL;
    825 
    826     expbrace(&blk, NULL, GLOBSPACE);
    827 
    828     for (p = blk; *p; p++)
    829 	gres |= pmatch(string, *p);
    830 
    831     blkfree(blk);
    832     return(gres == gpol);
    833 }
    834 
    835 static int
    836 pmatch(string, pattern)
    837     register Char *string, *pattern;
    838 {
    839     register Char stringc, patternc;
    840     int     match, negate_range;
    841     Char    rangec;
    842 
    843     for (;; ++string) {
    844 	stringc = *string & TRIM;
    845 	patternc = *pattern++;
    846 	switch (patternc) {
    847 	case 0:
    848 	    return (stringc == 0);
    849 	case '?':
    850 	    if (stringc == 0)
    851 		return (0);
    852 	    break;
    853 	case '*':
    854 	    if (!*pattern)
    855 		return (1);
    856 	    while (*string)
    857 		if (Gmatch(string++, pattern))
    858 		    return (1);
    859 	    return (0);
    860 	case '[':
    861 	    match = 0;
    862 	    if ((negate_range = (*pattern == '^')) != 0)
    863 		pattern++;
    864 	    while ((rangec = *pattern++) != '\0') {
    865 		if (rangec == ']')
    866 		    break;
    867 		if (match)
    868 		    continue;
    869 		if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
    870 		    match = (stringc <= (*pattern & TRIM) &&
    871 			      (*(pattern-2) & TRIM) <= stringc);
    872 		    pattern++;
    873 		}
    874 		else
    875 		    match = (stringc == (rangec & TRIM));
    876 	    }
    877 	    if (rangec == 0)
    878 		stderror(ERR_NAME | ERR_MISSING, ']');
    879 	    if (match == negate_range)
    880 		return (0);
    881 	    break;
    882 	default:
    883 	    if ((patternc & TRIM) != stringc)
    884 		return (0);
    885 	    break;
    886 
    887 	}
    888     }
    889 }
    890 
    891 void
    892 Gcat(s1, s2)
    893     Char   *s1, *s2;
    894 {
    895     register Char *p, *q;
    896     int     n;
    897 
    898     for (p = s1; *p++;)
    899 	continue;
    900     for (q = s2; *q++;)
    901 	continue;
    902     n = (p - s1) + (q - s2) - 1;
    903     if (++gargc >= gargsiz) {
    904 	gargsiz += GLOBSPACE;
    905 	gargv = (Char **) xrealloc((ptr_t) gargv,
    906 				   (size_t) gargsiz * sizeof(Char *));
    907     }
    908     gargv[gargc] = 0;
    909     p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
    910     for (q = s1; (*p++ = *q++) != '\0';)
    911 	continue;
    912     for (p--, q = s2; (*p++ = *q++) != '\0';)
    913 	continue;
    914 }
    915 
    916 #ifdef FILEC
    917 int
    918 sortscmp(a, b)
    919     register const ptr_t a, b;
    920 {
    921 #if defined(NLS) && !defined(NOSTRCOLL)
    922     char    buf[2048];
    923 #endif
    924 
    925     if (!a)			/* check for NULL */
    926 	return (b ? 1 : 0);
    927     if (!b)
    928 	return (-1);
    929 
    930     if (!*(Char **)a)			/* check for NULL */
    931 	return (*(Char **)b ? 1 : 0);
    932     if (!*(Char **)b)
    933 	return (-1);
    934 
    935 #if defined(NLS) && !defined(NOSTRCOLL)
    936     (void) strcpy(buf, short2str(*(Char **)a));
    937     return ((int) strcoll(buf, short2str(*(Char **)b)));
    938 #else
    939     return ((int) Strcmp(*(Char **)a, *(Char **)b));
    940 #endif
    941 }
    942 #endif /* FILEC */
    943