xref: /onnv-gate/usr/src/cmd/sh/macro.c (revision 527:cb400a149efa)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * UNIX shell
330Sstevel@tonic-gate  */
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include	"defs.h"
360Sstevel@tonic-gate #include	"sym.h"
370Sstevel@tonic-gate #include	<wait.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static unsigned char	quote;	/* used locally */
400Sstevel@tonic-gate static unsigned char	quoted;	/* used locally */
410Sstevel@tonic-gate static int getch();
42*527Schin static void comsubst(int);
43*527Schin static void flush(int);
440Sstevel@tonic-gate 
450Sstevel@tonic-gate static void
46*527Schin copyto(unsigned char endch, int trimflag)
47*527Schin /* trimflag - flag to check if argument will be trimmed */
480Sstevel@tonic-gate {
49*527Schin 	unsigned int	c;
50*527Schin 	unsigned int 	d;
51*527Schin 	unsigned char *pc;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	while ((c = getch(endch, trimflag)) != endch && c)
540Sstevel@tonic-gate 		if (quote) {
550Sstevel@tonic-gate 			if(c == '\\') { /* don't interpret next character */
560Sstevel@tonic-gate 				if (staktop >= brkend)
570Sstevel@tonic-gate 					growstak(staktop);
580Sstevel@tonic-gate 				pushstak(c);
590Sstevel@tonic-gate 				d = readwc();
600Sstevel@tonic-gate 				if(!escchar(d)) { /* both \ and following
610Sstevel@tonic-gate 						     character are quoted if next
620Sstevel@tonic-gate 						     character is not $, `, ", or \*/
630Sstevel@tonic-gate 					if (staktop >= brkend)
640Sstevel@tonic-gate 						growstak(staktop);
650Sstevel@tonic-gate 					pushstak('\\');
660Sstevel@tonic-gate 					if (staktop >= brkend)
670Sstevel@tonic-gate 						growstak(staktop);
680Sstevel@tonic-gate 					pushstak('\\');
690Sstevel@tonic-gate 					pc = readw(d);
700Sstevel@tonic-gate 					/* push entire multibyte char */
710Sstevel@tonic-gate 					while(*pc) {
720Sstevel@tonic-gate 						if (staktop >= brkend)
730Sstevel@tonic-gate 							growstak(staktop);
740Sstevel@tonic-gate 						pushstak(*pc++);
750Sstevel@tonic-gate 					}
760Sstevel@tonic-gate 				} else {
770Sstevel@tonic-gate 					pc = readw(d);
780Sstevel@tonic-gate 					/* d might be NULL */
790Sstevel@tonic-gate 					/* Evenif d is NULL, we have to save it */
800Sstevel@tonic-gate 					if (*pc) {
810Sstevel@tonic-gate 						while (*pc) {
820Sstevel@tonic-gate 							if (staktop >= brkend)
830Sstevel@tonic-gate 								growstak(staktop);
840Sstevel@tonic-gate 							pushstak(*pc++);
850Sstevel@tonic-gate 						}
860Sstevel@tonic-gate 					} else {
870Sstevel@tonic-gate 						if (staktop >= brkend)
880Sstevel@tonic-gate 							growstak(staktop);
890Sstevel@tonic-gate 						pushstak(*pc);
900Sstevel@tonic-gate 					}
910Sstevel@tonic-gate 				}
920Sstevel@tonic-gate 			} else { /* push escapes onto stack to quote characters */
930Sstevel@tonic-gate 				pc = readw(c);
940Sstevel@tonic-gate 				if (staktop >= brkend)
950Sstevel@tonic-gate 					growstak(staktop);
960Sstevel@tonic-gate 				pushstak('\\');
970Sstevel@tonic-gate 				while(*pc) {
980Sstevel@tonic-gate 					if (staktop >= brkend)
990Sstevel@tonic-gate 						growstak(staktop);
1000Sstevel@tonic-gate 					pushstak(*pc++);
1010Sstevel@tonic-gate 				}
1020Sstevel@tonic-gate 			}
1030Sstevel@tonic-gate 		} else if(c == '\\') {
1040Sstevel@tonic-gate 			c = readwc(); /* get character to be escaped */
1050Sstevel@tonic-gate 			if (staktop >= brkend)
1060Sstevel@tonic-gate 				growstak(staktop);
1070Sstevel@tonic-gate 			pushstak('\\');
1080Sstevel@tonic-gate 			pc = readw(c);
1090Sstevel@tonic-gate 			/* c might be NULL */
1100Sstevel@tonic-gate 			/* Evenif c is NULL, we have to save it */
1110Sstevel@tonic-gate 			if (*pc) {
1120Sstevel@tonic-gate 				while (*pc) {
1130Sstevel@tonic-gate 					if (staktop >= brkend)
1140Sstevel@tonic-gate 						growstak(staktop);
1150Sstevel@tonic-gate 					pushstak(*pc++);
1160Sstevel@tonic-gate 				}
1170Sstevel@tonic-gate 			} else {
1180Sstevel@tonic-gate 				if (staktop >= brkend)
1190Sstevel@tonic-gate 					growstak(staktop);
1200Sstevel@tonic-gate 				pushstak(*pc);
1210Sstevel@tonic-gate 			}
1220Sstevel@tonic-gate 		} else {
1230Sstevel@tonic-gate 			pc = readw(c);
1240Sstevel@tonic-gate 			while (*pc) {
1250Sstevel@tonic-gate 				if (staktop >= brkend)
1260Sstevel@tonic-gate 					growstak(staktop);
1270Sstevel@tonic-gate 				pushstak(*pc++);
1280Sstevel@tonic-gate 			}
1290Sstevel@tonic-gate 		}
1300Sstevel@tonic-gate 	if (staktop >= brkend)
1310Sstevel@tonic-gate 			growstak(staktop);
1320Sstevel@tonic-gate 	zerostak();
1330Sstevel@tonic-gate 	if (c != endch)
1340Sstevel@tonic-gate 		error(badsub);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate 
137*527Schin static void
138*527Schin skipto(unsigned char endch)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate 	/*
1410Sstevel@tonic-gate 	 * skip chars up to }
1420Sstevel@tonic-gate 	 */
143*527Schin 	unsigned int	c;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	while ((c = readwc()) && c != endch)
1460Sstevel@tonic-gate 	{
1470Sstevel@tonic-gate 		switch (c)
1480Sstevel@tonic-gate 		{
1490Sstevel@tonic-gate 		case SQUOTE:
1500Sstevel@tonic-gate 			skipto(SQUOTE);
1510Sstevel@tonic-gate 			break;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 		case DQUOTE:
1540Sstevel@tonic-gate 			skipto(DQUOTE);
1550Sstevel@tonic-gate 			break;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 		case DOLLAR:
1580Sstevel@tonic-gate 			if (readwc() == BRACE)
1590Sstevel@tonic-gate 				skipto('}');
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate 	if (c != endch)
1630Sstevel@tonic-gate 		error(badsub);
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate static
1670Sstevel@tonic-gate int getch(endch, trimflag)
1680Sstevel@tonic-gate unsigned char	endch;
1690Sstevel@tonic-gate int trimflag; /* flag to check if an argument is going to be trimmed, here document
1700Sstevel@tonic-gate 		 output is never trimmed
1710Sstevel@tonic-gate 	 */
1720Sstevel@tonic-gate {
173*527Schin 	unsigned int	d;
1740Sstevel@tonic-gate 	int atflag;  /* flag to check if $@ has already been seen within double
1750Sstevel@tonic-gate 		        quotes */
1760Sstevel@tonic-gate retry:
1770Sstevel@tonic-gate 	d = readwc();
1780Sstevel@tonic-gate 	if (!subchar(d))
1790Sstevel@tonic-gate 		return(d);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	if (d == DOLLAR)
1820Sstevel@tonic-gate 	{
1830Sstevel@tonic-gate 		unsigned int c;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 		if ((c = readwc(), dolchar(c)))
1860Sstevel@tonic-gate 		{
1870Sstevel@tonic-gate 			struct namnod *n = (struct namnod *)NIL;
1880Sstevel@tonic-gate 			int		dolg = 0;
1890Sstevel@tonic-gate 			BOOL		bra;
1900Sstevel@tonic-gate 			BOOL		nulflg;
191*527Schin 			unsigned char	*argp, *v;
1920Sstevel@tonic-gate 			unsigned char		idb[2];
1930Sstevel@tonic-gate 			unsigned char		*id = idb;
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 			if (bra = (c == BRACE))
1960Sstevel@tonic-gate 				c = readwc();
1970Sstevel@tonic-gate 			if (letter(c))
1980Sstevel@tonic-gate 			{
1990Sstevel@tonic-gate 				argp = (unsigned char *)relstak();
2000Sstevel@tonic-gate 				while (alphanum(c))
2010Sstevel@tonic-gate 				{
2020Sstevel@tonic-gate 					if (staktop >= brkend)
2030Sstevel@tonic-gate 						growstak(staktop);
2040Sstevel@tonic-gate 					pushstak(c);
2050Sstevel@tonic-gate 					c = readwc();
2060Sstevel@tonic-gate 				}
2070Sstevel@tonic-gate 				if (staktop >= brkend)
2080Sstevel@tonic-gate 					growstak(staktop);
2090Sstevel@tonic-gate 				zerostak();
2100Sstevel@tonic-gate 				n = lookup(absstak(argp));
2110Sstevel@tonic-gate 				setstak(argp);
2120Sstevel@tonic-gate 				if (n->namflg & N_FUNCTN)
2130Sstevel@tonic-gate 					error(badsub);
2140Sstevel@tonic-gate 				v = n->namval;
2150Sstevel@tonic-gate 				id = (unsigned char *)n->namid;
2160Sstevel@tonic-gate 				peekc = c | MARK;
2170Sstevel@tonic-gate 			}
2180Sstevel@tonic-gate 			else if (digchar(c))
2190Sstevel@tonic-gate 			{
2200Sstevel@tonic-gate 				*id = c;
2210Sstevel@tonic-gate 				idb[1] = 0;
2220Sstevel@tonic-gate 				if (astchar(c))
2230Sstevel@tonic-gate 				{
2240Sstevel@tonic-gate 					if(c == '@' && !atflag && quote) {
2250Sstevel@tonic-gate 						quoted--;
2260Sstevel@tonic-gate 						atflag = 1;
2270Sstevel@tonic-gate 					}
2280Sstevel@tonic-gate 					dolg = 1;
2290Sstevel@tonic-gate 					c = '1';
2300Sstevel@tonic-gate 				}
2310Sstevel@tonic-gate 				c -= '0';
2320Sstevel@tonic-gate 				v = ((c == 0) ? cmdadr : ((int)c <= dolc) ? dolv[c] : (unsigned char *)(dolg = 0));
2330Sstevel@tonic-gate 			}
2340Sstevel@tonic-gate 			else if (c == '$')
2350Sstevel@tonic-gate 				v = pidadr;
2360Sstevel@tonic-gate 			else if (c == '!')
2370Sstevel@tonic-gate 				v = pcsadr;
2380Sstevel@tonic-gate 			else if (c == '#')
2390Sstevel@tonic-gate 			{
2400Sstevel@tonic-gate 				itos(dolc);
2410Sstevel@tonic-gate 				v = numbuf;
2420Sstevel@tonic-gate 			}
2430Sstevel@tonic-gate 			else if (c == '?')
2440Sstevel@tonic-gate 			{
2450Sstevel@tonic-gate 				itos(retval);
2460Sstevel@tonic-gate 				v = numbuf;
2470Sstevel@tonic-gate 			}
2480Sstevel@tonic-gate 			else if (c == '-')
2490Sstevel@tonic-gate 				v = flagadr;
2500Sstevel@tonic-gate 			else if (bra)
2510Sstevel@tonic-gate 				error(badsub);
2520Sstevel@tonic-gate 			else
2530Sstevel@tonic-gate 				goto retry;
2540Sstevel@tonic-gate 			c = readwc();
2550Sstevel@tonic-gate 			if (c == ':' && bra)	/* null and unset fix */
2560Sstevel@tonic-gate 			{
2570Sstevel@tonic-gate 				nulflg = 1;
2580Sstevel@tonic-gate 				c = readwc();
2590Sstevel@tonic-gate 			}
2600Sstevel@tonic-gate 			else
2610Sstevel@tonic-gate 				nulflg = 0;
2620Sstevel@tonic-gate 			if (!defchar(c) && bra)
2630Sstevel@tonic-gate 				error(badsub);
2640Sstevel@tonic-gate 			argp = 0;
2650Sstevel@tonic-gate 			if (bra)
2660Sstevel@tonic-gate 			{
2670Sstevel@tonic-gate 				if (c != '}')
2680Sstevel@tonic-gate 				{
2690Sstevel@tonic-gate 					argp = (unsigned char *)relstak();
2700Sstevel@tonic-gate 					if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c)))
2710Sstevel@tonic-gate 						copyto('}', trimflag);
2720Sstevel@tonic-gate 					else
2730Sstevel@tonic-gate 						skipto('}');
2740Sstevel@tonic-gate 					argp = absstak(argp);
2750Sstevel@tonic-gate 				}
2760Sstevel@tonic-gate 			}
2770Sstevel@tonic-gate 			else
2780Sstevel@tonic-gate 			{
2790Sstevel@tonic-gate 				peekc = c | MARK;
2800Sstevel@tonic-gate 				c = 0;
2810Sstevel@tonic-gate 			}
2820Sstevel@tonic-gate 			if (v && (!nulflg || *v))
2830Sstevel@tonic-gate 			{
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 				if (c != '+')
2860Sstevel@tonic-gate 				{
2870Sstevel@tonic-gate 					for (;;)
2880Sstevel@tonic-gate 					{
2890Sstevel@tonic-gate 						if (*v == 0 && quote) {
2900Sstevel@tonic-gate 							if (staktop >= brkend)
2910Sstevel@tonic-gate 								growstak(staktop);
2920Sstevel@tonic-gate 							pushstak('\\');
2930Sstevel@tonic-gate 							if (staktop >= brkend)
2940Sstevel@tonic-gate 								growstak(staktop);
2950Sstevel@tonic-gate 							pushstak('\0');
2960Sstevel@tonic-gate 						} else {
2970Sstevel@tonic-gate 							while (c = *v) {
2980Sstevel@tonic-gate 								wchar_t 	wc;
299*527Schin 								int 	length;
3000Sstevel@tonic-gate 								if ((length = mbtowc(&wc, (char *)v, MB_LEN_MAX)) <= 0)
3010Sstevel@tonic-gate 									length = 1;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 								if(quote || (c == '\\' && trimflag)) {
3040Sstevel@tonic-gate 									if (staktop >= brkend)
3050Sstevel@tonic-gate 										growstak(staktop);
3060Sstevel@tonic-gate 									pushstak('\\');
3070Sstevel@tonic-gate 								}
3080Sstevel@tonic-gate 								while(length-- > 0) {
3090Sstevel@tonic-gate 									if (staktop >= brkend)
3100Sstevel@tonic-gate 										growstak(staktop);
3110Sstevel@tonic-gate 									pushstak(*v++);
3120Sstevel@tonic-gate 								}
3130Sstevel@tonic-gate 							}
3140Sstevel@tonic-gate 						}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 						if (dolg == 0 || (++dolg > dolc))
3170Sstevel@tonic-gate 							break;
3180Sstevel@tonic-gate 						else /* $* and $@ expansion */
3190Sstevel@tonic-gate 						{
3200Sstevel@tonic-gate 							v = dolv[dolg];
3210Sstevel@tonic-gate 							if(*id == '*' && quote) {
3220Sstevel@tonic-gate /* push quoted space so that " $* " will not be broken into separate arguments */
3230Sstevel@tonic-gate 								if (staktop >= brkend)
3240Sstevel@tonic-gate 									growstak(staktop);
3250Sstevel@tonic-gate 								pushstak('\\');
3260Sstevel@tonic-gate 							}
3270Sstevel@tonic-gate 							if (staktop >= brkend)
3280Sstevel@tonic-gate 								growstak(staktop);
3290Sstevel@tonic-gate 							pushstak(' ');
3300Sstevel@tonic-gate 						}
3310Sstevel@tonic-gate 					}
3320Sstevel@tonic-gate 				}
3330Sstevel@tonic-gate 			}
3340Sstevel@tonic-gate 			else if (argp)
3350Sstevel@tonic-gate 			{
3360Sstevel@tonic-gate 				if (c == '?') {
3370Sstevel@tonic-gate 					if(trimflag)
3380Sstevel@tonic-gate 						trim(argp);
339*527Schin 					failed(id, *argp ? (const char *)argp :
340*527Schin 					    badparam);
3410Sstevel@tonic-gate 				}
3420Sstevel@tonic-gate 				else if (c == '=')
3430Sstevel@tonic-gate 				{
3440Sstevel@tonic-gate 					if (n)
3450Sstevel@tonic-gate 					{
3460Sstevel@tonic-gate 						int strlngth = staktop - stakbot;
3470Sstevel@tonic-gate 						unsigned char *savptr = fixstak();
3480Sstevel@tonic-gate 						unsigned char *newargp;
3490Sstevel@tonic-gate 					/*
3500Sstevel@tonic-gate 					 * copy word onto stack, trim it, and then
3510Sstevel@tonic-gate 					 * do assignment
3520Sstevel@tonic-gate 					 */
3530Sstevel@tonic-gate 						usestak();
3540Sstevel@tonic-gate 						while(c = *argp) {
3550Sstevel@tonic-gate 							wchar_t 	wc;
356*527Schin 							int 		len;
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 							if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
3590Sstevel@tonic-gate 								len = 1;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 							if(c == '\\' && trimflag) {
3620Sstevel@tonic-gate 								argp++;
3630Sstevel@tonic-gate 								if (*argp == 0) {
3640Sstevel@tonic-gate 									argp++;
3650Sstevel@tonic-gate 									continue;
3660Sstevel@tonic-gate 								}
3670Sstevel@tonic-gate 								if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
3680Sstevel@tonic-gate 									len = 1;
3690Sstevel@tonic-gate 							}
3700Sstevel@tonic-gate 							while(len-- > 0) {
3710Sstevel@tonic-gate 								if (staktop >= brkend)
3720Sstevel@tonic-gate 									growstak(staktop);
3730Sstevel@tonic-gate 								pushstak(*argp++);
3740Sstevel@tonic-gate 							}
3750Sstevel@tonic-gate 						}
3760Sstevel@tonic-gate 						newargp = fixstak();
3770Sstevel@tonic-gate 						assign(n, newargp);
3780Sstevel@tonic-gate 						tdystak(savptr);
3790Sstevel@tonic-gate 						memcpy(stakbot, savptr, strlngth);
3800Sstevel@tonic-gate 						staktop = stakbot + strlngth;
3810Sstevel@tonic-gate 					}
3820Sstevel@tonic-gate 					else
3830Sstevel@tonic-gate 						error(badsub);
3840Sstevel@tonic-gate 				}
3850Sstevel@tonic-gate 			}
3860Sstevel@tonic-gate 			else if (flags & setflg)
3870Sstevel@tonic-gate 				failed(id, unset);
3880Sstevel@tonic-gate 			goto retry;
3890Sstevel@tonic-gate 		}
3900Sstevel@tonic-gate 		else
3910Sstevel@tonic-gate 			peekc = c | MARK;
3920Sstevel@tonic-gate 	}
3930Sstevel@tonic-gate 	else if (d == endch)
3940Sstevel@tonic-gate 		return(d);
3950Sstevel@tonic-gate 	else if (d == SQUOTE)
3960Sstevel@tonic-gate 	{
3970Sstevel@tonic-gate 		comsubst(trimflag);
3980Sstevel@tonic-gate 		goto retry;
3990Sstevel@tonic-gate 	}
4000Sstevel@tonic-gate 	else if (d == DQUOTE && trimflag)
4010Sstevel@tonic-gate 	{
4020Sstevel@tonic-gate 		if(!quote) {
4030Sstevel@tonic-gate 			atflag = 0;
4040Sstevel@tonic-gate 			quoted++;
4050Sstevel@tonic-gate 		}
4060Sstevel@tonic-gate 		quote ^= QUOTE;
4070Sstevel@tonic-gate 		goto retry;
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 	return(d);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate unsigned char *
4130Sstevel@tonic-gate macro(as)
4140Sstevel@tonic-gate unsigned char	*as;
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	/*
4170Sstevel@tonic-gate 	 * Strip "" and do $ substitution
4180Sstevel@tonic-gate 	 * Leaves result on top of stack
4190Sstevel@tonic-gate 	 */
420*527Schin 	BOOL	savqu = quoted;
421*527Schin 	unsigned char	savq = quote;
4220Sstevel@tonic-gate 	struct filehdr	fb;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	push(&fb);
4250Sstevel@tonic-gate 	estabf(as);
4260Sstevel@tonic-gate 	usestak();
4270Sstevel@tonic-gate 	quote = 0;
4280Sstevel@tonic-gate 	quoted = 0;
4290Sstevel@tonic-gate 	copyto(0, 1);
4300Sstevel@tonic-gate 	pop();
4310Sstevel@tonic-gate 	if (quoted && (stakbot == staktop)) {
4320Sstevel@tonic-gate 		if (staktop >= brkend)
4330Sstevel@tonic-gate 			growstak(staktop);
4340Sstevel@tonic-gate 		pushstak('\\');
4350Sstevel@tonic-gate 		if (staktop >= brkend)
4360Sstevel@tonic-gate 			growstak(staktop);
4370Sstevel@tonic-gate 		pushstak('\0');
4380Sstevel@tonic-gate /*
4390Sstevel@tonic-gate  * above is the fix for *'.c' bug
4400Sstevel@tonic-gate  */
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 	quote = savq;
4430Sstevel@tonic-gate 	quoted = savqu;
4440Sstevel@tonic-gate 	return(fixstak());
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate /* Save file descriptor for command substitution */
4470Sstevel@tonic-gate int savpipe = -1;
4480Sstevel@tonic-gate 
449*527Schin static void
450*527Schin comsubst(int trimflag)
451*527Schin /* trimflag - used to determine if argument will later be trimmed */
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate 	/*
4540Sstevel@tonic-gate 	 * command substn
4550Sstevel@tonic-gate 	 */
4560Sstevel@tonic-gate 	struct fileblk	cb;
457*527Schin 	unsigned int	d;
4580Sstevel@tonic-gate 	int strlngth = staktop - stakbot;
459*527Schin 	unsigned char *oldstaktop;
4600Sstevel@tonic-gate 	unsigned char *savptr = fixstak();
4610Sstevel@tonic-gate 	unsigned char	*pc;
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	usestak();
4640Sstevel@tonic-gate 	while ((d = readwc()) != SQUOTE && d) {
4650Sstevel@tonic-gate 		if(d == '\\') {
4660Sstevel@tonic-gate 			d = readwc();
4670Sstevel@tonic-gate 			if(!escchar(d) || (d == '"' && !quote)) {
4680Sstevel@tonic-gate 		/* trim quotes for `, \, or " if command substitution is within
4690Sstevel@tonic-gate 		   double quotes */
4700Sstevel@tonic-gate 				if (staktop >= brkend)
4710Sstevel@tonic-gate 					growstak(staktop);
4720Sstevel@tonic-gate 				pushstak('\\');
4730Sstevel@tonic-gate 			}
4740Sstevel@tonic-gate 		}
4750Sstevel@tonic-gate 		pc = readw(d);
4760Sstevel@tonic-gate 		/* d might be NULL */
4770Sstevel@tonic-gate 		if (*pc) {
4780Sstevel@tonic-gate 			while (*pc) {
4790Sstevel@tonic-gate 				if (staktop >= brkend)
4800Sstevel@tonic-gate 					growstak(staktop);
4810Sstevel@tonic-gate 				pushstak(*pc++);
4820Sstevel@tonic-gate 			}
4830Sstevel@tonic-gate 		} else {
4840Sstevel@tonic-gate 			if (staktop >= brkend)
4850Sstevel@tonic-gate 				growstak(staktop);
4860Sstevel@tonic-gate 			pushstak(*pc);
4870Sstevel@tonic-gate 		}
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 	{
490*527Schin 		unsigned char	*argc;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 		argc = fixstak();
4930Sstevel@tonic-gate 		push(&cb);
4940Sstevel@tonic-gate 		estabf(argc);  /* read from string */
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 	{
497*527Schin 		struct trenod	*t;
4980Sstevel@tonic-gate 		int		pv[2];
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 		/*
5010Sstevel@tonic-gate 		 * this is done like this so that the pipe
5020Sstevel@tonic-gate 		 * is open only when needed
5030Sstevel@tonic-gate 		 */
5040Sstevel@tonic-gate 	 	t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG ));
5050Sstevel@tonic-gate 		chkpipe(pv);
5060Sstevel@tonic-gate 		savpipe = pv[OTPIPE];
5070Sstevel@tonic-gate 		initf(pv[INPIPE]); /* read from pipe */
5080Sstevel@tonic-gate 		execute(t, XEC_NOSTOP, (int)(flags & errflg), 0, pv);
5090Sstevel@tonic-gate 		close(pv[OTPIPE]);
5100Sstevel@tonic-gate 		savpipe = -1;
5110Sstevel@tonic-gate 	}
5120Sstevel@tonic-gate 	tdystak(savptr);
5130Sstevel@tonic-gate 	memcpy(stakbot, savptr, strlngth);
5140Sstevel@tonic-gate 	oldstaktop = staktop = stakbot + strlngth;
5150Sstevel@tonic-gate 	while (d = readwc()) {
5160Sstevel@tonic-gate 		if(quote || (d == '\\' && trimflag)) {
517*527Schin 			unsigned char *rest;
5180Sstevel@tonic-gate 			/* quote output from command subst. if within double
5190Sstevel@tonic-gate 			   quotes or backslash part of output */
5200Sstevel@tonic-gate 			rest = readw(d);
5210Sstevel@tonic-gate 			if (staktop >= brkend)
5220Sstevel@tonic-gate 				growstak(staktop);
5230Sstevel@tonic-gate 			pushstak('\\');
5240Sstevel@tonic-gate 			while(d = *rest++) {
5250Sstevel@tonic-gate 			/* Pick up all of multibyte character */
5260Sstevel@tonic-gate 				if (staktop >= brkend)
5270Sstevel@tonic-gate 					growstak(staktop);
5280Sstevel@tonic-gate 				pushstak(d);
5290Sstevel@tonic-gate 			}
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 		else {
5320Sstevel@tonic-gate 			pc = readw(d);
5330Sstevel@tonic-gate 			while (*pc) {
5340Sstevel@tonic-gate 				if (staktop >= brkend)
5350Sstevel@tonic-gate 					growstak(staktop);
5360Sstevel@tonic-gate 				pushstak(*pc++);
5370Sstevel@tonic-gate 			}
5380Sstevel@tonic-gate 		}
5390Sstevel@tonic-gate 	}
5400Sstevel@tonic-gate 	{
5410Sstevel@tonic-gate 		extern pid_t parent;
5420Sstevel@tonic-gate 		int stat;
543*527Schin 		int rc;
5440Sstevel@tonic-gate 		int	ret = 0;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 		while ((ret = waitpid(parent,&stat,0)) != parent) {
5470Sstevel@tonic-gate 			/* break out if waitpid(2) has failed */
5480Sstevel@tonic-gate 			if (ret == -1)
5490Sstevel@tonic-gate 				break;
5500Sstevel@tonic-gate 		}
5510Sstevel@tonic-gate 		if (WIFEXITED(stat))
5520Sstevel@tonic-gate 			rc = WEXITSTATUS(stat);
5530Sstevel@tonic-gate 		else
5540Sstevel@tonic-gate 			rc = (WTERMSIG(stat) | SIGFLG);
5550Sstevel@tonic-gate 		if (rc && (flags & errflg))
5560Sstevel@tonic-gate 			exitsh(rc);
5570Sstevel@tonic-gate 		exitval = rc;
5580Sstevel@tonic-gate 		flags |= eflag;
5590Sstevel@tonic-gate 		exitset();
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate 	while (oldstaktop != staktop)
5620Sstevel@tonic-gate 	{ /* strip off trailing newlines from command substitution only */
5630Sstevel@tonic-gate 		if ((*--staktop) != NL)
5640Sstevel@tonic-gate 		{
5650Sstevel@tonic-gate 			++staktop;
5660Sstevel@tonic-gate 			break;
5670Sstevel@tonic-gate 		} else if(quote)
5680Sstevel@tonic-gate 			staktop--; /* skip past backslashes if quoting */
5690Sstevel@tonic-gate 	}
5700Sstevel@tonic-gate 	pop();
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate #define CPYSIZ	512
5740Sstevel@tonic-gate 
575*527Schin void
576*527Schin subst(int in, int ot)
5770Sstevel@tonic-gate {
578*527Schin 	unsigned int	c;
5790Sstevel@tonic-gate 	struct fileblk	fb;
580*527Schin 	int	count = CPYSIZ;
5810Sstevel@tonic-gate 	unsigned char	*pc;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	push(&fb);
5840Sstevel@tonic-gate 	initf(in);
5850Sstevel@tonic-gate 	/*
5860Sstevel@tonic-gate 	 * DQUOTE used to stop it from quoting
5870Sstevel@tonic-gate 	 */
5880Sstevel@tonic-gate 	while (c = (getch(DQUOTE, 0))) /* read characters from here document
5890Sstevel@tonic-gate 				       and interpret them */
5900Sstevel@tonic-gate 	{
5910Sstevel@tonic-gate 		if(c == '\\') {
5920Sstevel@tonic-gate 			c = readwc(); /* check if character in here document is
5930Sstevel@tonic-gate 					escaped */
5940Sstevel@tonic-gate 			if(!escchar(c) || c == '"') {
5950Sstevel@tonic-gate 				if (staktop >= brkend)
5960Sstevel@tonic-gate 					growstak(staktop);
5970Sstevel@tonic-gate 				pushstak('\\');
5980Sstevel@tonic-gate 			}
5990Sstevel@tonic-gate 		}
6000Sstevel@tonic-gate 		pc = readw(c);
6010Sstevel@tonic-gate 		/* c might be NULL */
6020Sstevel@tonic-gate 		if (*pc) {
6030Sstevel@tonic-gate 			while (*pc) {
6040Sstevel@tonic-gate 				if (staktop >= brkend)
6050Sstevel@tonic-gate 					growstak(staktop);
6060Sstevel@tonic-gate 				pushstak(*pc++);
6070Sstevel@tonic-gate 			}
6080Sstevel@tonic-gate 		} else {
6090Sstevel@tonic-gate 			if (staktop >= brkend)
6100Sstevel@tonic-gate 				growstak(staktop);
6110Sstevel@tonic-gate 			pushstak(*pc);
6120Sstevel@tonic-gate 		}
6130Sstevel@tonic-gate 		if (--count == 0)
6140Sstevel@tonic-gate 		{
6150Sstevel@tonic-gate 			flush(ot);
6160Sstevel@tonic-gate 			count = CPYSIZ;
6170Sstevel@tonic-gate 		}
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 	flush(ot);
6200Sstevel@tonic-gate 	pop();
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate 
623*527Schin static void
624*527Schin flush(int ot)
6250Sstevel@tonic-gate {
6260Sstevel@tonic-gate 	write(ot, stakbot, staktop - stakbot);
6270Sstevel@tonic-gate 	if (flags & execpr)
6280Sstevel@tonic-gate 		write(output, stakbot, staktop - stakbot);
6290Sstevel@tonic-gate 	staktop = stakbot;
6300Sstevel@tonic-gate }
631