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