17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*33bc07fdScraigm * Common Development and Distribution License (the "License").
6*33bc07fdScraigm * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*33bc07fdScraigm * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * UNIX shell
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include "defs.h"
357c478bd9Sstevel@tonic-gate #include "sym.h"
367c478bd9Sstevel@tonic-gate #include <wait.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate static unsigned char quote; /* used locally */
397c478bd9Sstevel@tonic-gate static unsigned char quoted; /* used locally */
407c478bd9Sstevel@tonic-gate static int getch();
41965005c8Schin static void comsubst(int);
42965005c8Schin static void flush(int);
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate static void
copyto(unsigned char endch,int trimflag)45965005c8Schin copyto(unsigned char endch, int trimflag)
46965005c8Schin /* trimflag - flag to check if argument will be trimmed */
477c478bd9Sstevel@tonic-gate {
48965005c8Schin unsigned int c;
49965005c8Schin unsigned int d;
50965005c8Schin unsigned char *pc;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate while ((c = getch(endch, trimflag)) != endch && c)
537c478bd9Sstevel@tonic-gate if (quote) {
547c478bd9Sstevel@tonic-gate if(c == '\\') { /* don't interpret next character */
557c478bd9Sstevel@tonic-gate if (staktop >= brkend)
567c478bd9Sstevel@tonic-gate growstak(staktop);
577c478bd9Sstevel@tonic-gate pushstak(c);
587c478bd9Sstevel@tonic-gate d = readwc();
597c478bd9Sstevel@tonic-gate if(!escchar(d)) { /* both \ and following
607c478bd9Sstevel@tonic-gate character are quoted if next
617c478bd9Sstevel@tonic-gate character is not $, `, ", or \*/
627c478bd9Sstevel@tonic-gate if (staktop >= brkend)
637c478bd9Sstevel@tonic-gate growstak(staktop);
647c478bd9Sstevel@tonic-gate pushstak('\\');
657c478bd9Sstevel@tonic-gate if (staktop >= brkend)
667c478bd9Sstevel@tonic-gate growstak(staktop);
677c478bd9Sstevel@tonic-gate pushstak('\\');
687c478bd9Sstevel@tonic-gate pc = readw(d);
697c478bd9Sstevel@tonic-gate /* push entire multibyte char */
707c478bd9Sstevel@tonic-gate while(*pc) {
717c478bd9Sstevel@tonic-gate if (staktop >= brkend)
727c478bd9Sstevel@tonic-gate growstak(staktop);
737c478bd9Sstevel@tonic-gate pushstak(*pc++);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate } else {
767c478bd9Sstevel@tonic-gate pc = readw(d);
777c478bd9Sstevel@tonic-gate /* d might be NULL */
787c478bd9Sstevel@tonic-gate /* Evenif d is NULL, we have to save it */
797c478bd9Sstevel@tonic-gate if (*pc) {
807c478bd9Sstevel@tonic-gate while (*pc) {
817c478bd9Sstevel@tonic-gate if (staktop >= brkend)
827c478bd9Sstevel@tonic-gate growstak(staktop);
837c478bd9Sstevel@tonic-gate pushstak(*pc++);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate } else {
867c478bd9Sstevel@tonic-gate if (staktop >= brkend)
877c478bd9Sstevel@tonic-gate growstak(staktop);
887c478bd9Sstevel@tonic-gate pushstak(*pc);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate } else { /* push escapes onto stack to quote characters */
927c478bd9Sstevel@tonic-gate pc = readw(c);
937c478bd9Sstevel@tonic-gate if (staktop >= brkend)
947c478bd9Sstevel@tonic-gate growstak(staktop);
957c478bd9Sstevel@tonic-gate pushstak('\\');
967c478bd9Sstevel@tonic-gate while(*pc) {
977c478bd9Sstevel@tonic-gate if (staktop >= brkend)
987c478bd9Sstevel@tonic-gate growstak(staktop);
997c478bd9Sstevel@tonic-gate pushstak(*pc++);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate } else if(c == '\\') {
1037c478bd9Sstevel@tonic-gate c = readwc(); /* get character to be escaped */
1047c478bd9Sstevel@tonic-gate if (staktop >= brkend)
1057c478bd9Sstevel@tonic-gate growstak(staktop);
1067c478bd9Sstevel@tonic-gate pushstak('\\');
1077c478bd9Sstevel@tonic-gate pc = readw(c);
1087c478bd9Sstevel@tonic-gate /* c might be NULL */
1097c478bd9Sstevel@tonic-gate /* Evenif c is NULL, we have to save it */
1107c478bd9Sstevel@tonic-gate if (*pc) {
1117c478bd9Sstevel@tonic-gate while (*pc) {
1127c478bd9Sstevel@tonic-gate if (staktop >= brkend)
1137c478bd9Sstevel@tonic-gate growstak(staktop);
1147c478bd9Sstevel@tonic-gate pushstak(*pc++);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate } else {
1177c478bd9Sstevel@tonic-gate if (staktop >= brkend)
1187c478bd9Sstevel@tonic-gate growstak(staktop);
1197c478bd9Sstevel@tonic-gate pushstak(*pc);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate } else {
1227c478bd9Sstevel@tonic-gate pc = readw(c);
1237c478bd9Sstevel@tonic-gate while (*pc) {
1247c478bd9Sstevel@tonic-gate if (staktop >= brkend)
1257c478bd9Sstevel@tonic-gate growstak(staktop);
1267c478bd9Sstevel@tonic-gate pushstak(*pc++);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate if (staktop >= brkend)
1307c478bd9Sstevel@tonic-gate growstak(staktop);
1317c478bd9Sstevel@tonic-gate zerostak();
1327c478bd9Sstevel@tonic-gate if (c != endch)
1337c478bd9Sstevel@tonic-gate error(badsub);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
136965005c8Schin static void
skipto(unsigned char endch)137965005c8Schin skipto(unsigned char endch)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate /*
1407c478bd9Sstevel@tonic-gate * skip chars up to }
1417c478bd9Sstevel@tonic-gate */
142965005c8Schin unsigned int c;
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate while ((c = readwc()) && c != endch)
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate switch (c)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate case SQUOTE:
1497c478bd9Sstevel@tonic-gate skipto(SQUOTE);
1507c478bd9Sstevel@tonic-gate break;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate case DQUOTE:
1537c478bd9Sstevel@tonic-gate skipto(DQUOTE);
1547c478bd9Sstevel@tonic-gate break;
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate case DOLLAR:
1577c478bd9Sstevel@tonic-gate if (readwc() == BRACE)
1587c478bd9Sstevel@tonic-gate skipto('}');
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate if (c != endch)
1627c478bd9Sstevel@tonic-gate error(badsub);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate static
getch(endch,trimflag)1667c478bd9Sstevel@tonic-gate int getch(endch, trimflag)
1677c478bd9Sstevel@tonic-gate unsigned char endch;
1687c478bd9Sstevel@tonic-gate int trimflag; /* flag to check if an argument is going to be trimmed, here document
1697c478bd9Sstevel@tonic-gate output is never trimmed
1707c478bd9Sstevel@tonic-gate */
1717c478bd9Sstevel@tonic-gate {
172965005c8Schin unsigned int d;
1737c478bd9Sstevel@tonic-gate int atflag; /* flag to check if $@ has already been seen within double
1747c478bd9Sstevel@tonic-gate quotes */
1757c478bd9Sstevel@tonic-gate retry:
1767c478bd9Sstevel@tonic-gate d = readwc();
1777c478bd9Sstevel@tonic-gate if (!subchar(d))
1787c478bd9Sstevel@tonic-gate return(d);
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate if (d == DOLLAR)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate unsigned int c;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate if ((c = readwc(), dolchar(c)))
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate struct namnod *n = (struct namnod *)NIL;
1877c478bd9Sstevel@tonic-gate int dolg = 0;
1887c478bd9Sstevel@tonic-gate BOOL bra;
1897c478bd9Sstevel@tonic-gate BOOL nulflg;
190965005c8Schin unsigned char *argp, *v;
1917c478bd9Sstevel@tonic-gate unsigned char idb[2];
1927c478bd9Sstevel@tonic-gate unsigned char *id = idb;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate if (bra = (c == BRACE))
1957c478bd9Sstevel@tonic-gate c = readwc();
1967c478bd9Sstevel@tonic-gate if (letter(c))
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate argp = (unsigned char *)relstak();
1997c478bd9Sstevel@tonic-gate while (alphanum(c))
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate if (staktop >= brkend)
2027c478bd9Sstevel@tonic-gate growstak(staktop);
2037c478bd9Sstevel@tonic-gate pushstak(c);
2047c478bd9Sstevel@tonic-gate c = readwc();
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate if (staktop >= brkend)
2077c478bd9Sstevel@tonic-gate growstak(staktop);
2087c478bd9Sstevel@tonic-gate zerostak();
2097c478bd9Sstevel@tonic-gate n = lookup(absstak(argp));
2107c478bd9Sstevel@tonic-gate setstak(argp);
2117c478bd9Sstevel@tonic-gate if (n->namflg & N_FUNCTN)
2127c478bd9Sstevel@tonic-gate error(badsub);
2137c478bd9Sstevel@tonic-gate v = n->namval;
2147c478bd9Sstevel@tonic-gate id = (unsigned char *)n->namid;
2157c478bd9Sstevel@tonic-gate peekc = c | MARK;
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate else if (digchar(c))
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate *id = c;
2207c478bd9Sstevel@tonic-gate idb[1] = 0;
2217c478bd9Sstevel@tonic-gate if (astchar(c))
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate if(c == '@' && !atflag && quote) {
2247c478bd9Sstevel@tonic-gate quoted--;
2257c478bd9Sstevel@tonic-gate atflag = 1;
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate dolg = 1;
2287c478bd9Sstevel@tonic-gate c = '1';
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate c -= '0';
2317c478bd9Sstevel@tonic-gate v = ((c == 0) ? cmdadr : ((int)c <= dolc) ? dolv[c] : (unsigned char *)(dolg = 0));
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate else if (c == '$')
2347c478bd9Sstevel@tonic-gate v = pidadr;
2357c478bd9Sstevel@tonic-gate else if (c == '!')
2367c478bd9Sstevel@tonic-gate v = pcsadr;
2377c478bd9Sstevel@tonic-gate else if (c == '#')
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate itos(dolc);
2407c478bd9Sstevel@tonic-gate v = numbuf;
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate else if (c == '?')
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate itos(retval);
2457c478bd9Sstevel@tonic-gate v = numbuf;
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate else if (c == '-')
2487c478bd9Sstevel@tonic-gate v = flagadr;
2497c478bd9Sstevel@tonic-gate else if (bra)
2507c478bd9Sstevel@tonic-gate error(badsub);
2517c478bd9Sstevel@tonic-gate else
2527c478bd9Sstevel@tonic-gate goto retry;
2537c478bd9Sstevel@tonic-gate c = readwc();
2547c478bd9Sstevel@tonic-gate if (c == ':' && bra) /* null and unset fix */
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate nulflg = 1;
2577c478bd9Sstevel@tonic-gate c = readwc();
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate else
2607c478bd9Sstevel@tonic-gate nulflg = 0;
2617c478bd9Sstevel@tonic-gate if (!defchar(c) && bra)
2627c478bd9Sstevel@tonic-gate error(badsub);
2637c478bd9Sstevel@tonic-gate argp = 0;
2647c478bd9Sstevel@tonic-gate if (bra)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate if (c != '}')
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate argp = (unsigned char *)relstak();
2697c478bd9Sstevel@tonic-gate if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c)))
2707c478bd9Sstevel@tonic-gate copyto('}', trimflag);
2717c478bd9Sstevel@tonic-gate else
2727c478bd9Sstevel@tonic-gate skipto('}');
2737c478bd9Sstevel@tonic-gate argp = absstak(argp);
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate else
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate peekc = c | MARK;
2797c478bd9Sstevel@tonic-gate c = 0;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate if (v && (!nulflg || *v))
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate if (c != '+')
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate for (;;)
2877c478bd9Sstevel@tonic-gate {
2887c478bd9Sstevel@tonic-gate if (*v == 0 && quote) {
2897c478bd9Sstevel@tonic-gate if (staktop >= brkend)
2907c478bd9Sstevel@tonic-gate growstak(staktop);
2917c478bd9Sstevel@tonic-gate pushstak('\\');
2927c478bd9Sstevel@tonic-gate if (staktop >= brkend)
2937c478bd9Sstevel@tonic-gate growstak(staktop);
2947c478bd9Sstevel@tonic-gate pushstak('\0');
2957c478bd9Sstevel@tonic-gate } else {
2967c478bd9Sstevel@tonic-gate while (c = *v) {
2977c478bd9Sstevel@tonic-gate wchar_t wc;
298965005c8Schin int length;
2997c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)v, MB_LEN_MAX)) <= 0)
3007c478bd9Sstevel@tonic-gate length = 1;
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate if(quote || (c == '\\' && trimflag)) {
3037c478bd9Sstevel@tonic-gate if (staktop >= brkend)
3047c478bd9Sstevel@tonic-gate growstak(staktop);
3057c478bd9Sstevel@tonic-gate pushstak('\\');
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate while(length-- > 0) {
3087c478bd9Sstevel@tonic-gate if (staktop >= brkend)
3097c478bd9Sstevel@tonic-gate growstak(staktop);
3107c478bd9Sstevel@tonic-gate pushstak(*v++);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate if (dolg == 0 || (++dolg > dolc))
3167c478bd9Sstevel@tonic-gate break;
3177c478bd9Sstevel@tonic-gate else /* $* and $@ expansion */
3187c478bd9Sstevel@tonic-gate {
3197c478bd9Sstevel@tonic-gate v = dolv[dolg];
3207c478bd9Sstevel@tonic-gate if(*id == '*' && quote) {
3217c478bd9Sstevel@tonic-gate /* push quoted space so that " $* " will not be broken into separate arguments */
3227c478bd9Sstevel@tonic-gate if (staktop >= brkend)
3237c478bd9Sstevel@tonic-gate growstak(staktop);
3247c478bd9Sstevel@tonic-gate pushstak('\\');
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate if (staktop >= brkend)
3277c478bd9Sstevel@tonic-gate growstak(staktop);
3287c478bd9Sstevel@tonic-gate pushstak(' ');
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate else if (argp)
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate if (c == '?') {
3367c478bd9Sstevel@tonic-gate if(trimflag)
3377c478bd9Sstevel@tonic-gate trim(argp);
338965005c8Schin failed(id, *argp ? (const char *)argp :
339965005c8Schin badparam);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate else if (c == '=')
3427c478bd9Sstevel@tonic-gate {
3437c478bd9Sstevel@tonic-gate if (n)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate int strlngth = staktop - stakbot;
3467c478bd9Sstevel@tonic-gate unsigned char *savptr = fixstak();
3477c478bd9Sstevel@tonic-gate unsigned char *newargp;
3487c478bd9Sstevel@tonic-gate /*
3497c478bd9Sstevel@tonic-gate * copy word onto stack, trim it, and then
3507c478bd9Sstevel@tonic-gate * do assignment
3517c478bd9Sstevel@tonic-gate */
3527c478bd9Sstevel@tonic-gate usestak();
3537c478bd9Sstevel@tonic-gate while(c = *argp) {
3547c478bd9Sstevel@tonic-gate wchar_t wc;
355965005c8Schin int len;
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
3587c478bd9Sstevel@tonic-gate len = 1;
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate if(c == '\\' && trimflag) {
3617c478bd9Sstevel@tonic-gate argp++;
3627c478bd9Sstevel@tonic-gate if (*argp == 0) {
3637c478bd9Sstevel@tonic-gate argp++;
3647c478bd9Sstevel@tonic-gate continue;
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
3677c478bd9Sstevel@tonic-gate len = 1;
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate while(len-- > 0) {
3707c478bd9Sstevel@tonic-gate if (staktop >= brkend)
3717c478bd9Sstevel@tonic-gate growstak(staktop);
3727c478bd9Sstevel@tonic-gate pushstak(*argp++);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate newargp = fixstak();
3767c478bd9Sstevel@tonic-gate assign(n, newargp);
3777c478bd9Sstevel@tonic-gate tdystak(savptr);
378*33bc07fdScraigm (void) memcpystak(stakbot, savptr, strlngth);
3797c478bd9Sstevel@tonic-gate staktop = stakbot + strlngth;
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate else
3827c478bd9Sstevel@tonic-gate error(badsub);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate else if (flags & setflg)
3867c478bd9Sstevel@tonic-gate failed(id, unset);
3877c478bd9Sstevel@tonic-gate goto retry;
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate else
3907c478bd9Sstevel@tonic-gate peekc = c | MARK;
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate else if (d == endch)
3937c478bd9Sstevel@tonic-gate return(d);
3947c478bd9Sstevel@tonic-gate else if (d == SQUOTE)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate comsubst(trimflag);
3977c478bd9Sstevel@tonic-gate goto retry;
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate else if (d == DQUOTE && trimflag)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate if(!quote) {
4027c478bd9Sstevel@tonic-gate atflag = 0;
4037c478bd9Sstevel@tonic-gate quoted++;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate quote ^= QUOTE;
4067c478bd9Sstevel@tonic-gate goto retry;
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate return(d);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate unsigned char *
macro(as)4127c478bd9Sstevel@tonic-gate macro(as)
4137c478bd9Sstevel@tonic-gate unsigned char *as;
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate /*
4167c478bd9Sstevel@tonic-gate * Strip "" and do $ substitution
4177c478bd9Sstevel@tonic-gate * Leaves result on top of stack
4187c478bd9Sstevel@tonic-gate */
419965005c8Schin BOOL savqu = quoted;
420965005c8Schin unsigned char savq = quote;
4217c478bd9Sstevel@tonic-gate struct filehdr fb;
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate push(&fb);
4247c478bd9Sstevel@tonic-gate estabf(as);
4257c478bd9Sstevel@tonic-gate usestak();
4267c478bd9Sstevel@tonic-gate quote = 0;
4277c478bd9Sstevel@tonic-gate quoted = 0;
4287c478bd9Sstevel@tonic-gate copyto(0, 1);
4297c478bd9Sstevel@tonic-gate pop();
4307c478bd9Sstevel@tonic-gate if (quoted && (stakbot == staktop)) {
4317c478bd9Sstevel@tonic-gate if (staktop >= brkend)
4327c478bd9Sstevel@tonic-gate growstak(staktop);
4337c478bd9Sstevel@tonic-gate pushstak('\\');
4347c478bd9Sstevel@tonic-gate if (staktop >= brkend)
4357c478bd9Sstevel@tonic-gate growstak(staktop);
4367c478bd9Sstevel@tonic-gate pushstak('\0');
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate * above is the fix for *'.c' bug
4397c478bd9Sstevel@tonic-gate */
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate quote = savq;
4427c478bd9Sstevel@tonic-gate quoted = savqu;
4437c478bd9Sstevel@tonic-gate return(fixstak());
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate /* Save file descriptor for command substitution */
4467c478bd9Sstevel@tonic-gate int savpipe = -1;
4477c478bd9Sstevel@tonic-gate
448965005c8Schin static void
comsubst(int trimflag)449965005c8Schin comsubst(int trimflag)
450965005c8Schin /* trimflag - used to determine if argument will later be trimmed */
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate /*
4537c478bd9Sstevel@tonic-gate * command substn
4547c478bd9Sstevel@tonic-gate */
4557c478bd9Sstevel@tonic-gate struct fileblk cb;
456965005c8Schin unsigned int d;
4577c478bd9Sstevel@tonic-gate int strlngth = staktop - stakbot;
458965005c8Schin unsigned char *oldstaktop;
4597c478bd9Sstevel@tonic-gate unsigned char *savptr = fixstak();
4607c478bd9Sstevel@tonic-gate unsigned char *pc;
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate usestak();
4637c478bd9Sstevel@tonic-gate while ((d = readwc()) != SQUOTE && d) {
4647c478bd9Sstevel@tonic-gate if(d == '\\') {
4657c478bd9Sstevel@tonic-gate d = readwc();
4667c478bd9Sstevel@tonic-gate if(!escchar(d) || (d == '"' && !quote)) {
4677c478bd9Sstevel@tonic-gate /* trim quotes for `, \, or " if command substitution is within
4687c478bd9Sstevel@tonic-gate double quotes */
4697c478bd9Sstevel@tonic-gate if (staktop >= brkend)
4707c478bd9Sstevel@tonic-gate growstak(staktop);
4717c478bd9Sstevel@tonic-gate pushstak('\\');
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate pc = readw(d);
4757c478bd9Sstevel@tonic-gate /* d might be NULL */
4767c478bd9Sstevel@tonic-gate if (*pc) {
4777c478bd9Sstevel@tonic-gate while (*pc) {
4787c478bd9Sstevel@tonic-gate if (staktop >= brkend)
4797c478bd9Sstevel@tonic-gate growstak(staktop);
4807c478bd9Sstevel@tonic-gate pushstak(*pc++);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate } else {
4837c478bd9Sstevel@tonic-gate if (staktop >= brkend)
4847c478bd9Sstevel@tonic-gate growstak(staktop);
4857c478bd9Sstevel@tonic-gate pushstak(*pc);
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate {
489965005c8Schin unsigned char *argc;
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate argc = fixstak();
4927c478bd9Sstevel@tonic-gate push(&cb);
4937c478bd9Sstevel@tonic-gate estabf(argc); /* read from string */
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate {
496965005c8Schin struct trenod *t;
4977c478bd9Sstevel@tonic-gate int pv[2];
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate /*
5007c478bd9Sstevel@tonic-gate * this is done like this so that the pipe
5017c478bd9Sstevel@tonic-gate * is open only when needed
5027c478bd9Sstevel@tonic-gate */
5037c478bd9Sstevel@tonic-gate t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG ));
5047c478bd9Sstevel@tonic-gate chkpipe(pv);
5057c478bd9Sstevel@tonic-gate savpipe = pv[OTPIPE];
5067c478bd9Sstevel@tonic-gate initf(pv[INPIPE]); /* read from pipe */
5077c478bd9Sstevel@tonic-gate execute(t, XEC_NOSTOP, (int)(flags & errflg), 0, pv);
5087c478bd9Sstevel@tonic-gate close(pv[OTPIPE]);
5097c478bd9Sstevel@tonic-gate savpipe = -1;
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate tdystak(savptr);
512*33bc07fdScraigm (void) memcpystak(stakbot, savptr, strlngth);
5137c478bd9Sstevel@tonic-gate oldstaktop = staktop = stakbot + strlngth;
5147c478bd9Sstevel@tonic-gate while (d = readwc()) {
5157c478bd9Sstevel@tonic-gate if(quote || (d == '\\' && trimflag)) {
516965005c8Schin unsigned char *rest;
5177c478bd9Sstevel@tonic-gate /* quote output from command subst. if within double
5187c478bd9Sstevel@tonic-gate quotes or backslash part of output */
5197c478bd9Sstevel@tonic-gate rest = readw(d);
5207c478bd9Sstevel@tonic-gate if (staktop >= brkend)
5217c478bd9Sstevel@tonic-gate growstak(staktop);
5227c478bd9Sstevel@tonic-gate pushstak('\\');
5237c478bd9Sstevel@tonic-gate while(d = *rest++) {
5247c478bd9Sstevel@tonic-gate /* Pick up all of multibyte character */
5257c478bd9Sstevel@tonic-gate if (staktop >= brkend)
5267c478bd9Sstevel@tonic-gate growstak(staktop);
5277c478bd9Sstevel@tonic-gate pushstak(d);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate else {
5317c478bd9Sstevel@tonic-gate pc = readw(d);
5327c478bd9Sstevel@tonic-gate while (*pc) {
5337c478bd9Sstevel@tonic-gate if (staktop >= brkend)
5347c478bd9Sstevel@tonic-gate growstak(staktop);
5357c478bd9Sstevel@tonic-gate pushstak(*pc++);
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate {
5407c478bd9Sstevel@tonic-gate extern pid_t parent;
5417c478bd9Sstevel@tonic-gate int stat;
542965005c8Schin int rc;
5437c478bd9Sstevel@tonic-gate int ret = 0;
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate while ((ret = waitpid(parent,&stat,0)) != parent) {
5467c478bd9Sstevel@tonic-gate /* break out if waitpid(2) has failed */
5477c478bd9Sstevel@tonic-gate if (ret == -1)
5487c478bd9Sstevel@tonic-gate break;
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate if (WIFEXITED(stat))
5517c478bd9Sstevel@tonic-gate rc = WEXITSTATUS(stat);
5527c478bd9Sstevel@tonic-gate else
5537c478bd9Sstevel@tonic-gate rc = (WTERMSIG(stat) | SIGFLG);
5547c478bd9Sstevel@tonic-gate if (rc && (flags & errflg))
5557c478bd9Sstevel@tonic-gate exitsh(rc);
5567c478bd9Sstevel@tonic-gate exitval = rc;
5577c478bd9Sstevel@tonic-gate flags |= eflag;
5587c478bd9Sstevel@tonic-gate exitset();
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate while (oldstaktop != staktop)
5617c478bd9Sstevel@tonic-gate { /* strip off trailing newlines from command substitution only */
5627c478bd9Sstevel@tonic-gate if ((*--staktop) != NL)
5637c478bd9Sstevel@tonic-gate {
5647c478bd9Sstevel@tonic-gate ++staktop;
5657c478bd9Sstevel@tonic-gate break;
5667c478bd9Sstevel@tonic-gate } else if(quote)
5677c478bd9Sstevel@tonic-gate staktop--; /* skip past backslashes if quoting */
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate pop();
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate #define CPYSIZ 512
5737c478bd9Sstevel@tonic-gate
574965005c8Schin void
subst(int in,int ot)575965005c8Schin subst(int in, int ot)
5767c478bd9Sstevel@tonic-gate {
577965005c8Schin unsigned int c;
5787c478bd9Sstevel@tonic-gate struct fileblk fb;
579965005c8Schin int count = CPYSIZ;
5807c478bd9Sstevel@tonic-gate unsigned char *pc;
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate push(&fb);
5837c478bd9Sstevel@tonic-gate initf(in);
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate * DQUOTE used to stop it from quoting
5867c478bd9Sstevel@tonic-gate */
5877c478bd9Sstevel@tonic-gate while (c = (getch(DQUOTE, 0))) /* read characters from here document
5887c478bd9Sstevel@tonic-gate and interpret them */
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate if(c == '\\') {
5917c478bd9Sstevel@tonic-gate c = readwc(); /* check if character in here document is
5927c478bd9Sstevel@tonic-gate escaped */
5937c478bd9Sstevel@tonic-gate if(!escchar(c) || c == '"') {
5947c478bd9Sstevel@tonic-gate if (staktop >= brkend)
5957c478bd9Sstevel@tonic-gate growstak(staktop);
5967c478bd9Sstevel@tonic-gate pushstak('\\');
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate pc = readw(c);
6007c478bd9Sstevel@tonic-gate /* c might be NULL */
6017c478bd9Sstevel@tonic-gate if (*pc) {
6027c478bd9Sstevel@tonic-gate while (*pc) {
6037c478bd9Sstevel@tonic-gate if (staktop >= brkend)
6047c478bd9Sstevel@tonic-gate growstak(staktop);
6057c478bd9Sstevel@tonic-gate pushstak(*pc++);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate } else {
6087c478bd9Sstevel@tonic-gate if (staktop >= brkend)
6097c478bd9Sstevel@tonic-gate growstak(staktop);
6107c478bd9Sstevel@tonic-gate pushstak(*pc);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate if (--count == 0)
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate flush(ot);
6157c478bd9Sstevel@tonic-gate count = CPYSIZ;
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate flush(ot);
6197c478bd9Sstevel@tonic-gate pop();
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate
622965005c8Schin static void
flush(int ot)623965005c8Schin flush(int ot)
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate write(ot, stakbot, staktop - stakbot);
6267c478bd9Sstevel@tonic-gate if (flags & execpr)
6277c478bd9Sstevel@tonic-gate write(output, stakbot, staktop - stakbot);
6287c478bd9Sstevel@tonic-gate staktop = stakbot;
6297c478bd9Sstevel@tonic-gate }
630