xref: /freebsd/contrib/tcsh/sh.glob.c (revision f4b37ed0f8b307b1f3f0f630ca725d68f1dff30d)
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 
35 RCSID("$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  */
67 static	Char	 *globtilde	(Char *);
68 static	Char     *handleone	(Char *, Char **, int);
69 static	Char	**libglob	(Char **);
70 static	Char	**globexpand	(Char **, int);
71 static	int	  globbrace	(const Char *, Char ***);
72 static  void	  expbrace	(Char ***, Char ***, int);
73 static	void	  pword		(struct blk_buf *, struct Strbuf *);
74 static	void	  backeval	(struct blk_buf *, struct Strbuf *, Char *,
75 				 int);
76 static Char *
77 globtilde(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 */
108 Char *
109 globequal(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 
148 static int
149 globbrace(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 
225 static void
226 expbrace(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 
294 static Char **
295 globexpand(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 
391 static Char *
392 handleone(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 
426 static Char **
427 libglob(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 
478 Char   *
479 globone(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 
532 Char  **
533 globall(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 
564 Char **
565 glob_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 
581 void
582 rscan(Char **t, void (*f) (Char))
583 {
584     Char *p;
585 
586     while ((p = *t++) != '\0')
587 	while (*p)
588 	    (*f) (*p++);
589 }
590 
591 void
592 trim(Char **t)
593 {
594     Char *p;
595 
596     while ((p = *t++) != '\0')
597 	while (*p)
598 	    *p++ &= TRIM;
599 }
600 
601 int
602 tglob(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  */
652 Char  **
653 dobackp(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 
693 static void
694 backeval(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 
891 static void
892 pword(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 
901 int
902 Gmatch(const Char *string, const Char *pattern)
903 {
904     return Gnmatch(string, pattern, NULL);
905 }
906 
907 int
908 Gnmatch(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  */
955 int
956 t_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