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