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