xref: /dragonfly/contrib/tcsh-6/sh.glob.c (revision b97fef05)
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  */
63 static	Char	 *globtilde	(Char *);
64 static	Char     *handleone	(Char *, Char **, int);
65 static	Char	**libglob	(Char **);
66 static	Char	**globexpand	(Char **, int);
67 static	int	  globbrace	(const Char *, Char ***);
68 static  void	  expbrace	(Char ***, Char ***, int);
69 static	void	  pword		(struct blk_buf *, struct Strbuf *);
70 static	void	  backeval	(struct blk_buf *, struct Strbuf *, Char *,
71 				 int);
72 static Char *
73 globtilde(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 */
109 Char *
110 globequal(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 
149 static int
150 globbrace(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 
226 static void
227 expbrace(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 
295 static Char **
296 globexpand(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 
392 static Char *
393 handleone(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 
427 static Char **
428 libglob(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 
479 Char   *
480 globone(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 
535 Char  **
536 globall(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 
567 Char **
568 glob_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 
584 void
585 rscan(Char **t, void (*f) (Char))
586 {
587     Char *p;
588 
589     while ((p = *t++) != NULL)
590 	while (*p)
591 	    (*f) (*p++);
592 }
593 
594 void
595 trim(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 
609 int
610 tglob(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  */
660 Char  **
661 dobackp(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 
701 static void
702 backeval(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 
876 static void
877 pword(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 
886 int
887 Gmatch(const Char *string, const Char *pattern)
888 {
889     return Gnmatch(string, pattern, NULL);
890 }
891 
892 int
893 Gnmatch(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  */
940 int
941 t_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