1/*
2 * sh.glob.c: Regular expression expansion
3 */
4/*-
5 * Copyright (c) 1980, 1991 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32#include "sh.h"
33#include "tc.h"
34#include "tw.h"
35
36#include "glob.h"
37
38/*
39 * Values for gflag
40 */
41#define	G_NONE	0		/* No globbing needed			*/
42#define	G_GLOB	1		/* string contains *?[] characters	*/
43#define	G_CSH	2		/* string contains ~`{ characters	*/
44
45#define	GLOBSPACE	100	/* Alloc increment			*/
46
47
48#define LBRC '{'
49#define RBRC '}'
50#define LBRK '['
51#define RBRK ']'
52#define EOS '\0'
53
54/*
55 * globbing is now done in two stages. In the first pass we expand
56 * csh globbing idioms ~`{ and then we proceed doing the normal
57 * globbing if needed ?*[
58 *
59 * Csh type globbing is handled in globexpand() and the rest is
60 * handled in glob() which is part of the 4.4BSD libc.
61 *
62 */
63static	Char	 *globtilde	(Char *);
64static	Char     *handleone	(Char *, Char **, int);
65static	Char	**libglob	(Char **);
66static	Char	**globexpand	(Char **, int);
67static	int	  globbrace	(const Char *, Char ***);
68static  void	  expbrace	(Char ***, Char ***, int);
69static	void	  pword		(struct blk_buf *, struct Strbuf *);
70static	void	  backeval	(struct blk_buf *, struct Strbuf *, Char *,
71				 int);
72static Char *
73globtilde(Char *s)
74{
75    Char *name, *u, *home, *res;
76
77    u = s;
78
79    if (s[1] == '~')
80	return Strsave(s);
81
82    for (s++; *s && *s != '/' && *s != ':'; s++)
83	continue;
84
85    name = Strnsave(u + 1, s - (u + 1));
86    cleanup_push(name, xfree);
87    home = gethdir(name);
88    if (home == NULL) {
89	if (adrof(STRnonomatch)) {
90	    cleanup_until(name);
91	    return u;
92	}
93	if (*name)
94	    stderror(ERR_UNKUSER, short2str(name));
95	else
96	    stderror(ERR_NOHOME);
97    }
98    cleanup_until(name);
99    if (home[0] == '/' && home[1] == '\0' && s[0] == '/')
100	res = Strsave(s);
101    else
102	res = Strspl(home, s);
103    xfree(home);
104    xfree(u);
105    return res;
106}
107
108/* Returns a newly allocated string, old or NULL */
109Char *
110globequal(Char *old)
111{
112    int     dig;
113    const Char *dir;
114    Char    *b;
115
116    /*
117     * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
118     * in stack. PWP: let =foobar pass through (for X windows)
119     */
120    if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) {
121	/* =- */
122	const Char *olddir = varval (STRowd);
123
124	if (olddir && *olddir &&
125	    !dcwd->di_next->di_name && !dcwd->di_prev->di_name)
126	    return Strspl(olddir, &old[2]);
127	dig = -1;
128	b = &old[2];
129    }
130    else if (Isdigit(old[1])) {
131	/* =<number> */
132	dig = old[1] - '0';
133	for (b = &old[2]; Isdigit(*b); b++)
134	    dig = dig * 10 + (*b - '0');
135	if (*b != '\0' && *b != '/')
136	    /* =<number>foobar */
137	    return old;
138    }
139    else
140	/* =foobar */
141	return old;
142
143    dir = getstakd(dig);
144    if (dir == NULL)
145	return NULL;
146    return Strspl(dir, b);
147}
148
149static int
150globbrace(const Char *s, Char ***bl)
151{
152    struct Strbuf gbuf = Strbuf_INIT;
153    struct blk_buf bb = BLK_BUF_INIT;
154    int     i;
155    const Char *p, *pm, *pe, *pl;
156    size_t prefix_len;
157
158    /* copy part up to the brace */
159    for (p = s; *p != LBRC; p++)
160	;
161    prefix_len = p - s;
162
163    /* check for balanced braces */
164    for (i = 0, pe = ++p; *pe; pe++)
165	if (*pe == LBRK) {
166	    /* Ignore everything between [] */
167	    for (++pe; *pe != RBRK && *pe != EOS; pe++)
168		continue;
169	    if (*pe == EOS)
170		return (-RBRK);
171	}
172	else if (*pe == LBRC)
173	    i++;
174	else if (*pe == RBRC) {
175	    if (i == 0)
176		break;
177	    i--;
178	}
179
180    if (i != 0 || *pe == '\0')
181	return (-RBRC);
182
183    Strbuf_appendn(&gbuf, s, prefix_len);
184
185    for (i = 0, pl = pm = p; pm <= pe; pm++)
186	switch (*pm) {
187	case LBRK:
188	    for (++pm; *pm != RBRK && *pm != EOS; pm++)
189		continue;
190	    if (*pm == EOS) {
191		bb_cleanup(&bb);
192		xfree(gbuf.s);
193		return (-RBRK);
194	    }
195	    break;
196	case LBRC:
197	    i++;
198	    break;
199	case RBRC:
200	    if (i) {
201		i--;
202		break;
203	    }
204	    /* FALLTHROUGH */
205	case ',':
206	    if (i && *pm == ',')
207		break;
208	    else {
209		gbuf.len = prefix_len;
210		Strbuf_appendn(&gbuf, pl, pm - pl);
211		Strbuf_append(&gbuf, pe + 1);
212		Strbuf_terminate(&gbuf);
213		bb_append(&bb, Strsave(gbuf.s));
214		pl = pm + 1;
215	    }
216	    break;
217	default:
218	    break;
219	}
220    *bl = bb_finish(&bb);
221    xfree(gbuf.s);
222    return bb.len;
223}
224
225
226static void
227expbrace(Char ***nvp, Char ***elp, int size)
228{
229    Char **vl, **el, **nv, *s;
230
231    vl = nv = *nvp;
232    if (elp != NULL)
233	el = *elp;
234    else
235	el = vl + blklen(vl);
236
237    for (s = *vl; s; s = *++vl) {
238	Char  **vp, **bp;
239
240	/* leave {} untouched for find */
241	if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
242	    continue;
243	if (Strchr(s, '{') != NULL) {
244	    Char  **bl = NULL;
245	    int     len;
246
247	    if ((len = globbrace(s, &bl)) < 0)
248		stderror(ERR_MISSING, -len);
249	    xfree(s);
250	    if (len == 1) {
251		*vl-- = *bl;
252		xfree(bl);
253		continue;
254	    }
255	    if (&el[len] >= &nv[size]) {
256		size_t l, e;
257		l = &el[len] - &nv[size];
258		size += GLOBSPACE > l ? GLOBSPACE : l;
259		l = vl - nv;
260		e = el - nv;
261		nv = xrealloc(nv, size * sizeof(Char *));
262		*nvp = nv; /* To keep cleanups working */
263		vl = nv + l;
264		el = nv + e;
265	    }
266	    /* nv vl   el     bl
267	     * |  |    |      |
268	     * -.--..--	      x--
269	     *   |            len
270	     *   vp
271	     */
272	    vp = vl--;
273	    *vp = *bl;
274	    len--;
275	    for (bp = el; bp != vp; bp--)
276		bp[len] = *bp;
277	    el += len;
278	    /* nv vl    el bl
279	     * |  |     |  |
280	     * -.-x  ---    --
281	     *   |len
282	     *   vp
283	     */
284	    vp++;
285	    for (bp = bl + 1; *bp; *vp++ = *bp++)
286		continue;
287	    xfree(bl);
288	}
289
290    }
291    if (elp != NULL)
292	*elp = el;
293}
294
295static Char **
296globexpand(Char **v, int noglob)
297{
298    Char   *s;
299    Char  ***fnv, **vl, **el;
300    int     size = GLOBSPACE;
301
302
303    fnv = xmalloc(sizeof(Char ***));
304    *fnv = vl = xmalloc(sizeof(Char *) * size);
305    *vl = NULL;
306    cleanup_push(fnv, blk_indirect_cleanup);
307
308    /*
309     * Step 1: expand backquotes.
310     */
311    while ((s = *v++) != NULL) {
312	if (Strchr(s, '`')) {
313	    int     i;
314	    Char **expanded;
315
316	    expanded = dobackp(s, 0);
317	    for (i = 0; expanded[i] != NULL; i++) {
318		*vl++ = expanded[i];
319		if (vl == &(*fnv)[size]) {
320		    size += GLOBSPACE;
321		    *fnv = xrealloc(*fnv, size * sizeof(Char *));
322		    vl = &(*fnv)[size - GLOBSPACE];
323		}
324	    }
325	    xfree(expanded);
326	}
327	else {
328	    *vl++ = Strsave(s);
329	    if (vl == &(*fnv)[size]) {
330		size += GLOBSPACE;
331		*fnv = xrealloc(*fnv, size * sizeof(Char *));
332		vl = &(*fnv)[size - GLOBSPACE];
333	    }
334	}
335	*vl = NULL;
336    }
337
338    if (noglob)
339	goto done;
340
341    /*
342     * Step 2: expand braces
343     */
344    el = vl;
345    expbrace(fnv, &el, size);
346
347
348    /*
349     * Step 3: expand ~ =
350     */
351    vl = *fnv;
352    for (s = *vl; s; s = *++vl)
353	switch (*s) {
354	    Char *ns;
355	case '~':
356	    *vl = globtilde(s);
357	    break;
358	case '=':
359	    if ((ns = globequal(s)) == NULL) {
360		if (!adrof(STRnonomatch))
361		    stderror(ERR_DEEP); /* Error */
362	    }
363	    if (ns && ns != s) {
364		/* Expansion succeeded */
365		xfree(s);
366		*vl = ns;
367	    }
368	    break;
369	default:
370	    break;
371	}
372    vl = *fnv;
373
374    /*
375     * Step 4: expand .. if the variable symlinks==expand is set
376     */
377    if (symlinks == SYM_EXPAND) {
378	for (s = *vl; s; s = *++vl) {
379	    *vl = dnormalize(s, 1);
380	    xfree(s);
381	}
382    }
383
384 done:
385    cleanup_ignore(fnv);
386    cleanup_until(fnv);
387    vl = *fnv;
388    xfree(fnv);
389    return vl;
390}
391
392static Char *
393handleone(Char *str, Char **vl, int action)
394{
395    size_t chars;
396    Char **t, *p, *strp;
397
398    switch (action) {
399    case G_ERROR:
400	setname(short2str(str));
401	blkfree(vl);
402	stderror(ERR_NAME | ERR_AMBIG);
403	break;
404    case G_APPEND:
405	chars = 0;
406	for (t = vl; (p = *t++) != NULL; chars++)
407	    chars += Strlen(p);
408	str = xmalloc(chars * sizeof(Char));
409	for (t = vl, strp = str; (p = *t++) != NULL; chars++) {
410	    while (*p)
411		 *strp++ = *p++ & TRIM;
412	    *strp++ = ' ';
413	}
414	*--strp = '\0';
415	blkfree(vl);
416	break;
417    case G_IGNORE:
418	str = Strsave(strip(*vl));
419	blkfree(vl);
420	break;
421    default:
422	break;
423    }
424    return (str);
425}
426
427static Char **
428libglob(Char **vl)
429{
430    int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
431    glob_t  globv;
432    char   *ptr;
433    int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
434
435    if (adrof(STRglobdot))
436       gflgs |= GLOB_DOT;
437
438    if (adrof(STRglobstar))
439       gflgs |= GLOB_STAR;
440
441    if (!vl || !vl[0])
442	return(vl);
443
444    globv.gl_offs = 0;
445    globv.gl_pathv = 0;
446    globv.gl_pathc = 0;
447
448    if (nonomatch)
449	gflgs |= GLOB_NOCHECK;
450
451    do {
452	ptr = short2qstr(*vl);
453	switch (glob(ptr, gflgs, 0, &globv)) {
454	case GLOB_ABEND:
455	    globfree(&globv);
456	    setname(ptr);
457	    stderror(ERR_NAME | ERR_GLOB);
458	    /* NOTREACHED */
459	case GLOB_NOSPACE:
460	    globfree(&globv);
461	    stderror(ERR_NOMEM);
462	    /* NOTREACHED */
463	default:
464	    break;
465	}
466	if (globv.gl_flags & GLOB_MAGCHAR) {
467	    match |= (globv.gl_matchc != 0);
468	    magic = 1;
469	}
470	gflgs |= GLOB_APPEND;
471    }
472    while (*++vl);
473    vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
474	NULL : blk2short(globv.gl_pathv);
475    globfree(&globv);
476    return (vl);
477}
478
479Char   *
480globone(Char *str, int action)
481{
482    Char   *v[2], **vl, **vo;
483    int gflg, noglob;
484
485    noglob = adrof(STRnoglob) != 0;
486    v[0] = str;
487    v[1] = 0;
488    gflg = tglob(v);
489    if (gflg == G_NONE)
490	return (strip(Strsave(str)));
491
492    if (gflg & G_CSH) {
493	/*
494	 * Expand back-quote, tilde and brace
495	 */
496	vo = globexpand(v, noglob);
497	if (noglob || (gflg & G_GLOB) == 0) {
498	    vl = vo;
499	    goto result;
500	}
501	cleanup_push(vo, blk_cleanup);
502    }
503    else if (noglob || (gflg & G_GLOB) == 0)
504	return (strip(Strsave(str)));
505    else
506	vo = v;
507
508    vl = libglob(vo);
509    if (gflg & G_CSH) {
510    	if (vl != vo)
511	    cleanup_until(vo);
512	else
513	    cleanup_ignore(vo);
514    }
515    if (vl == NULL) {
516	setname(short2str(str));
517	stderror(ERR_NAME | ERR_NOMATCH);
518    }
519 result:
520    if (vl && vl[0] == NULL) {
521	if (vl != v)
522	    xfree(vl);
523	return (Strsave(STRNULL));
524    }
525    if (vl && vl[1])
526	return (handleone(str, vl, action));
527    else {
528	str = strip(*vl);
529	if (vl != v)
530	    xfree(vl);
531	return (str);
532    }
533}
534
535Char  **
536globall(Char **v, int gflg)
537{
538    Char  **vl, **vo;
539    int noglob;
540
541    if (!v || !v[0])
542	return saveblk(v);
543
544    noglob = adrof(STRnoglob) != 0;
545
546    if (gflg & G_CSH)
547	/*
548	 * Expand back-quote, tilde and brace
549	 */
550	vl = vo = globexpand(v, noglob);
551    else
552	vl = vo = saveblk(v);
553
554    if (!noglob && (gflg & G_GLOB)) {
555	cleanup_push(vo, blk_cleanup);
556	vl = libglob(vo);
557	if (vl == vo)
558	    cleanup_ignore(vo);
559	cleanup_until(vo);
560    }
561    else
562	trim(vl);
563
564    return vl;
565}
566
567Char **
568glob_all_or_error(Char **v)
569{
570    int gflag;
571
572    gflag = tglob(v);
573    if (gflag) {
574	v = globall(v, gflag);
575	if (v == NULL)
576	    stderror(ERR_NAME | ERR_NOMATCH);
577    } else {
578	v = saveblk(v);
579	trim(v);
580    }
581    return v;
582}
583
584void
585rscan(Char **t, void (*f) (Char))
586{
587    Char *p;
588
589    while ((p = *t++) != NULL)
590	while (*p)
591	    (*f) (*p++);
592}
593
594void
595trim(Char **t)
596{
597    Char *p;
598
599    while ((p = *t++) != NULL)
600	while (*p) {
601#if INVALID_BYTE != 0
602	    if ((*p & INVALID_BYTE) != INVALID_BYTE)	/* *p < INVALID_BYTE */
603#endif
604		*p &= TRIM;
605	    p++;
606	}
607}
608
609int
610tglob(Char **t)
611{
612    int gflag;
613    const Char *p;
614
615    gflag = 0;
616    while ((p = *t++) != NULL) {
617	if (*p == '~' || *p == '=')
618	    gflag |= G_CSH;
619	else if (*p == '{' &&
620		 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
621	    continue;
622	while (*p != '\0') {
623	    if (*p == '`') {
624		gflag |= G_CSH;
625#ifdef notdef
626		/*
627		 * We do want to expand echo `echo '*'`, so we don't\
628		 * use this piece of code anymore.
629		 */
630		p++;
631		while (*p && *p != '`')
632		    if (*p++ == '\\') {
633			if (*p)		/* Quoted chars */
634			    p++;
635			else
636			    break;
637		    }
638		if (!*p)		/* The matching ` */
639		    break;
640#endif
641	    }
642	    else if (*p == '{')
643		gflag |= G_CSH;
644	    else if (isglob(*p))
645		gflag |= G_GLOB;
646	    else if (symlinks == SYM_EXPAND &&
647		p[1] && ISDOTDOT(p) && (p == *(t-1) || *(p-1) == '/') )
648	    	gflag |= G_CSH;
649	    p++;
650	}
651    }
652    return gflag;
653}
654
655/*
656 * Command substitute cp.  If literal, then this is a substitution from a
657 * << redirection, and so we should not crunch blanks and tabs, separating
658 * words only at newlines.
659 */
660Char  **
661dobackp(Char *cp, int literal)
662{
663    struct Strbuf word = Strbuf_INIT;
664    struct blk_buf bb = BLK_BUF_INIT;
665    Char *lp, *rp, *ep;
666
667    cleanup_push(&bb, bb_cleanup);
668    cleanup_push(&word, Strbuf_cleanup);
669    for (;;) {
670	for (lp = cp; *lp != '\0' && *lp != '`'; lp++)
671	    ;
672	Strbuf_appendn(&word, cp, lp - cp);
673	if (*lp == 0)
674	    break;
675	lp++;
676	for (rp = lp; *rp && *rp != '`'; rp++)
677	    if (*rp == '\\') {
678		rp++;
679		if (!*rp)
680		    goto oops;
681	    }
682	if (!*rp) {
683	oops:
684	    cleanup_until(&bb);
685	    stderror(ERR_UNMATCHED, '`');
686	}
687	ep = Strnsave(lp, rp - lp);
688	cleanup_push(ep, xfree);
689	backeval(&bb, &word, ep, literal);
690	cleanup_until(ep);
691	cp = rp + 1;
692    }
693    if (word.len != 0)
694	pword(&bb, &word);
695    cleanup_ignore(&bb);
696    cleanup_until(&bb);
697    return bb_finish(&bb);
698}
699
700
701static void
702backeval(struct blk_buf *bb, struct Strbuf *word, Char *cp, int literal)
703{
704    ssize_t icnt;
705    Char c, *ip;
706    struct command faket;
707    int    hadnl;
708    int     pvec[2], quoted;
709    Char   *fakecom[2], ibuf[BUFSIZE];
710
711    hadnl = 0;
712    icnt = 0;
713    if (!literal) {
714	for (ip = cp; (*ip & QUOTE) != 0; ip++)
715		continue;
716	quoted = *ip == '\0';
717    } else
718	quoted = literal;
719    faket.t_dtyp = NODE_COMMAND;
720    faket.t_dflg = F_BACKQ;
721    faket.t_dlef = 0;
722    faket.t_drit = 0;
723    faket.t_dspr = 0;
724    faket.t_dcom = fakecom;
725    fakecom[0] = STRfakecom1;
726    fakecom[1] = 0;
727
728    /*
729     * We do the psave job to temporarily change the current job so that the
730     * following fork is considered a separate job.  This is so that when
731     * backquotes are used in a builtin function that calls glob the "current
732     * job" is not corrupted.  We only need one level of pushed jobs as long as
733     * we are sure to fork here.
734     */
735    psavejob();
736    cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */
737
738    /*
739     * It would be nicer if we could integrate this redirection more with the
740     * routines in sh.sem.c by doing a fake execute on a builtin function that
741     * was piped out.
742     */
743    mypipe(pvec);
744    cleanup_push(&pvec[0], open_cleanup);
745    cleanup_push(&pvec[1], open_cleanup);
746    if (pfork(&faket, -1) == 0) {
747	jmp_buf_t osetexit;
748	struct command *t;
749	size_t omark;
750
751	xclose(pvec[0]);
752	(void) dmove(pvec[1], 1);
753	(void) dmove(SHDIAG,  2);
754	initdesc();
755	closem();
756	arginp = cp;
757	for (arginp = cp; *cp; cp++) {
758	    *cp &= TRIM;
759	    if (is_set(STRcsubstnonl) && (*cp == '\n' || *cp == '\r'))
760		*cp = ' ';
761	}
762
763        /*
764	 * In the child ``forget'' everything about current aliases or
765	 * eval vectors.
766	 */
767	alvec = NULL;
768	evalvec = NULL;
769	alvecp = NULL;
770	evalp = NULL;
771
772	omark = cleanup_push_mark();
773	getexit(osetexit);
774	for (;;) {
775	    struct wordent paraml1;
776	    initlex(&paraml1);
777
778	    (void) setexit();
779	    justpr = 0;
780
781	    if (haderr) {
782		/* unwind */
783		doneinp = 0;
784		cleanup_pop_mark(omark);
785		resexit(osetexit);
786		reset();
787	    }
788	    if (seterr) {
789		xfree(seterr);
790		seterr = NULL;
791	    }
792
793	    freelex(&paraml1);
794	    (void) lex(&paraml1);
795	    cleanup_push(&paraml1, lex_cleanup);
796	    if (seterr)
797		stderror(ERR_OLD);
798	    alias(&paraml1);
799	    t = syntax(paraml1.next, &paraml1, 0);
800	    cleanup_push(t, syntax_cleanup);
801	    /* The F_BACKQ flag must set so the job output is correct if
802	     * printexitvalue is set.  If it's not set, the job output
803	     * will have "Exit N" appended where N is the exit status. */
804	    if (t)
805		    t->t_dflg = F_BACKQ|F_NOFORK;
806	    if (seterr)
807		stderror(ERR_OLD);
808#ifdef SIGTSTP
809	    signal(SIGTSTP, SIG_IGN);
810#endif
811#ifdef SIGTTIN
812	    signal(SIGTTIN, SIG_IGN);
813#endif
814#ifdef SIGTTOU
815	    signal(SIGTTOU, SIG_IGN);
816#endif
817	    execute(t, -1, NULL, NULL, TRUE);
818
819	    cleanup_until(&paraml1);
820	}
821    }
822    cleanup_until(&pvec[1]);
823    c = 0;
824    ip = NULL;
825    do {
826	ssize_t     cnt = 0;
827
828	for (;;) {
829	    if (icnt == 0) {
830		ip = ibuf;
831		icnt = wide_read(pvec[0], ibuf, BUFSIZE, 0);
832		if (icnt <= 0)
833		    goto eof;
834	    }
835	    if (hadnl)
836		break;
837	    --icnt;
838	    c = (*ip++ & TRIM);
839	    if (c == 0)
840		break;
841#if defined(WINNT_NATIVE) || defined(__CYGWIN__)
842	    if (c == '\r')
843	    	c = ' ';
844#endif /* WINNT_NATIVE || __CYGWIN__ */
845	    if (c == '\n') {
846		/*
847		 * Continue around the loop one more time, so that we can eat
848		 * the last newline without terminating this word.
849		 */
850		hadnl = 1;
851		continue;
852	    }
853	    if (!quoted && (c == ' ' || c == '\t'))
854		break;
855	    cnt++;
856	    if (c == '\\' || quoted)
857		c |= QUOTE;
858	    Strbuf_append1(word, c);
859	}
860	/*
861	 * Unless at end-of-file, we will form a new word here if there were
862	 * characters in the word, or in any case when we take text literally.
863	 * If we didn't make empty words here when literal was set then we
864	 * would lose blank lines.
865	 */
866	if (c != 0 && (cnt || literal))
867	    pword(bb, word);
868	hadnl = 0;
869    } while (c > 0);
870 eof:
871    cleanup_until(&pvec[0]);
872    pwait();
873    cleanup_until(&faket); /* psavejob_cleanup(); */
874}
875
876static void
877pword(struct blk_buf *bb, struct Strbuf *word)
878{
879    Char *s;
880
881    s = Strbuf_finish(word);
882    bb_append(bb, s);
883    *word = Strbuf_init;
884}
885
886int
887Gmatch(const Char *string, const Char *pattern)
888{
889    return Gnmatch(string, pattern, NULL);
890}
891
892int
893Gnmatch(const Char *string, const Char *pattern, const Char **endstr)
894{
895    Char ***fblk, **p;
896    const Char *tstring = string;
897    int	   gpol = 1, gres = 0;
898
899    if (*pattern == '^') {
900	gpol = 0;
901	pattern++;
902    }
903
904    fblk = xmalloc(sizeof(Char ***));
905    *fblk = xmalloc(GLOBSPACE * sizeof(Char *));
906    (*fblk)[0] = Strsave(pattern);
907    (*fblk)[1] = NULL;
908
909    cleanup_push(fblk, blk_indirect_cleanup);
910    expbrace(fblk, NULL, GLOBSPACE);
911
912    if (endstr == NULL)
913	/* Exact matches only */
914	for (p = *fblk; *p; p++)
915	    gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0;
916    else {
917	const Char *end;
918
919	/* partial matches */
920        end = Strend(string);
921	for (p = *fblk; *p; p++)
922	    if (t_pmatch(string, *p, &tstring, 1) != 0) {
923		gres |= 1;
924		if (end > tstring)
925		    end = tstring;
926	    }
927	*endstr = end;
928    }
929
930    cleanup_until(fblk);
931    return(gres == gpol);
932}
933
934/* t_pmatch():
935 *	Return 2 on exact match,
936 *	Return 1 on substring match.
937 *	Return 0 on no match.
938 *	*estr will point to the end of the longest exact or substring match.
939 */
940int
941t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs)
942{
943    Char stringc, patternc, rangec;
944    int     match, negate_range;
945    const Char *pestr, *nstring;
946
947    for (nstring = string;; string = nstring) {
948	stringc = *nstring++ & TRIM;
949	patternc = *pattern++ & TRIM;
950	switch (patternc) {
951	case '\0':
952	    *estr = string;
953	    return (stringc == '\0' ? 2 : 1);
954	case '?':
955	    if (stringc == 0)
956		return (0);
957	    break;
958	case '*':
959	    if (!*pattern) {
960		*estr = Strend(string);
961		return (2);
962	    }
963	    pestr = NULL;
964
965	    for (;;) {
966		switch(t_pmatch(string, pattern, estr, cs)) {
967		case 0:
968		    break;
969		case 1:
970		    pestr = *estr;/*FIXME: does not guarantee longest match */
971		    break;
972		case 2:
973		    return 2;
974		default:
975		    abort();	/* Cannot happen */
976		}
977		stringc = *string++ & TRIM;
978		if (!stringc)
979		    break;
980	    }
981
982	    if (pestr) {
983		*estr = pestr;
984		return 1;
985	    }
986	    else
987		return 0;
988
989	case '[':
990	    match = 0;
991	    if ((negate_range = (*pattern == '^')) != 0)
992		pattern++;
993	    while ((rangec = *pattern++ & TRIM) != '\0') {
994		if (rangec == ']')
995		    break;
996		if (match)
997		    continue;
998		if (*pattern == '-' && pattern[1] != ']') {
999		    Char rangec2;
1000		    pattern++;
1001		    rangec2 = *pattern++ & TRIM;
1002		    match = (globcharcoll(stringc, rangec2, 0) <= 0 &&
1003			globcharcoll(rangec, stringc, 0) <= 0);
1004		}
1005		else
1006		    match = (stringc == rangec);
1007	    }
1008	    if (rangec == '\0')
1009		stderror(ERR_NAME | ERR_MISSING, ']');
1010	    if ((!match) && (stringc == '\0'))
1011		return (0);
1012	    if (match == negate_range)
1013		return (0);
1014	    break;
1015	default:
1016	    if (cs ? patternc  != stringc
1017		: Tolower(patternc) != Tolower(stringc))
1018		return (0);
1019	    break;
1020	}
1021    }
1022}
1023