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