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