1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * UNIX shell 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #include "defs.h" 36*7c478bd9Sstevel@tonic-gate #include "sym.h" 37*7c478bd9Sstevel@tonic-gate #include <wait.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate static unsigned char quote; /* used locally */ 40*7c478bd9Sstevel@tonic-gate static unsigned char quoted; /* used locally */ 41*7c478bd9Sstevel@tonic-gate static int getch(); 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate static void 44*7c478bd9Sstevel@tonic-gate copyto(endch, trimflag) 45*7c478bd9Sstevel@tonic-gate int trimflag; /* flag to check if argument will be trimmed */ 46*7c478bd9Sstevel@tonic-gate register unsigned char endch; 47*7c478bd9Sstevel@tonic-gate { 48*7c478bd9Sstevel@tonic-gate register unsigned int c; 49*7c478bd9Sstevel@tonic-gate register unsigned int d; 50*7c478bd9Sstevel@tonic-gate register unsigned char *pc; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate while ((c = getch(endch, trimflag)) != endch && c) 53*7c478bd9Sstevel@tonic-gate if (quote) { 54*7c478bd9Sstevel@tonic-gate if(c == '\\') { /* don't interpret next character */ 55*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 56*7c478bd9Sstevel@tonic-gate growstak(staktop); 57*7c478bd9Sstevel@tonic-gate pushstak(c); 58*7c478bd9Sstevel@tonic-gate d = readwc(); 59*7c478bd9Sstevel@tonic-gate if(!escchar(d)) { /* both \ and following 60*7c478bd9Sstevel@tonic-gate character are quoted if next 61*7c478bd9Sstevel@tonic-gate character is not $, `, ", or \*/ 62*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 63*7c478bd9Sstevel@tonic-gate growstak(staktop); 64*7c478bd9Sstevel@tonic-gate pushstak('\\'); 65*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 66*7c478bd9Sstevel@tonic-gate growstak(staktop); 67*7c478bd9Sstevel@tonic-gate pushstak('\\'); 68*7c478bd9Sstevel@tonic-gate pc = readw(d); 69*7c478bd9Sstevel@tonic-gate /* push entire multibyte char */ 70*7c478bd9Sstevel@tonic-gate while(*pc) { 71*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 72*7c478bd9Sstevel@tonic-gate growstak(staktop); 73*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate } else { 76*7c478bd9Sstevel@tonic-gate pc = readw(d); 77*7c478bd9Sstevel@tonic-gate /* d might be NULL */ 78*7c478bd9Sstevel@tonic-gate /* Evenif d is NULL, we have to save it */ 79*7c478bd9Sstevel@tonic-gate if (*pc) { 80*7c478bd9Sstevel@tonic-gate while (*pc) { 81*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 82*7c478bd9Sstevel@tonic-gate growstak(staktop); 83*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate } else { 86*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 87*7c478bd9Sstevel@tonic-gate growstak(staktop); 88*7c478bd9Sstevel@tonic-gate pushstak(*pc); 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate } else { /* push escapes onto stack to quote characters */ 92*7c478bd9Sstevel@tonic-gate pc = readw(c); 93*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 94*7c478bd9Sstevel@tonic-gate growstak(staktop); 95*7c478bd9Sstevel@tonic-gate pushstak('\\'); 96*7c478bd9Sstevel@tonic-gate while(*pc) { 97*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 98*7c478bd9Sstevel@tonic-gate growstak(staktop); 99*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate } else if(c == '\\') { 103*7c478bd9Sstevel@tonic-gate c = readwc(); /* get character to be escaped */ 104*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 105*7c478bd9Sstevel@tonic-gate growstak(staktop); 106*7c478bd9Sstevel@tonic-gate pushstak('\\'); 107*7c478bd9Sstevel@tonic-gate pc = readw(c); 108*7c478bd9Sstevel@tonic-gate /* c might be NULL */ 109*7c478bd9Sstevel@tonic-gate /* Evenif c is NULL, we have to save it */ 110*7c478bd9Sstevel@tonic-gate if (*pc) { 111*7c478bd9Sstevel@tonic-gate while (*pc) { 112*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 113*7c478bd9Sstevel@tonic-gate growstak(staktop); 114*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate } else { 117*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 118*7c478bd9Sstevel@tonic-gate growstak(staktop); 119*7c478bd9Sstevel@tonic-gate pushstak(*pc); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate } else { 122*7c478bd9Sstevel@tonic-gate pc = readw(c); 123*7c478bd9Sstevel@tonic-gate while (*pc) { 124*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 125*7c478bd9Sstevel@tonic-gate growstak(staktop); 126*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 130*7c478bd9Sstevel@tonic-gate growstak(staktop); 131*7c478bd9Sstevel@tonic-gate zerostak(); 132*7c478bd9Sstevel@tonic-gate if (c != endch) 133*7c478bd9Sstevel@tonic-gate error(badsub); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate static 137*7c478bd9Sstevel@tonic-gate skipto(endch) 138*7c478bd9Sstevel@tonic-gate register unsigned char endch; 139*7c478bd9Sstevel@tonic-gate { 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * skip chars up to } 142*7c478bd9Sstevel@tonic-gate */ 143*7c478bd9Sstevel@tonic-gate register unsigned int c; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate while ((c = readwc()) && c != endch) 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate switch (c) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate case SQUOTE: 150*7c478bd9Sstevel@tonic-gate skipto(SQUOTE); 151*7c478bd9Sstevel@tonic-gate break; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate case DQUOTE: 154*7c478bd9Sstevel@tonic-gate skipto(DQUOTE); 155*7c478bd9Sstevel@tonic-gate break; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate case DOLLAR: 158*7c478bd9Sstevel@tonic-gate if (readwc() == BRACE) 159*7c478bd9Sstevel@tonic-gate skipto('}'); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate if (c != endch) 163*7c478bd9Sstevel@tonic-gate error(badsub); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate static 167*7c478bd9Sstevel@tonic-gate int getch(endch, trimflag) 168*7c478bd9Sstevel@tonic-gate unsigned char endch; 169*7c478bd9Sstevel@tonic-gate int trimflag; /* flag to check if an argument is going to be trimmed, here document 170*7c478bd9Sstevel@tonic-gate output is never trimmed 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate { 173*7c478bd9Sstevel@tonic-gate register unsigned int d; 174*7c478bd9Sstevel@tonic-gate int atflag; /* flag to check if $@ has already been seen within double 175*7c478bd9Sstevel@tonic-gate quotes */ 176*7c478bd9Sstevel@tonic-gate retry: 177*7c478bd9Sstevel@tonic-gate d = readwc(); 178*7c478bd9Sstevel@tonic-gate if (!subchar(d)) 179*7c478bd9Sstevel@tonic-gate return(d); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate if (d == DOLLAR) 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate unsigned int c; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate if ((c = readwc(), dolchar(c))) 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate struct namnod *n = (struct namnod *)NIL; 188*7c478bd9Sstevel@tonic-gate int dolg = 0; 189*7c478bd9Sstevel@tonic-gate BOOL bra; 190*7c478bd9Sstevel@tonic-gate BOOL nulflg; 191*7c478bd9Sstevel@tonic-gate register unsigned char *argp, *v; 192*7c478bd9Sstevel@tonic-gate unsigned char idb[2]; 193*7c478bd9Sstevel@tonic-gate unsigned char *id = idb; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (bra = (c == BRACE)) 196*7c478bd9Sstevel@tonic-gate c = readwc(); 197*7c478bd9Sstevel@tonic-gate if (letter(c)) 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate argp = (unsigned char *)relstak(); 200*7c478bd9Sstevel@tonic-gate while (alphanum(c)) 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 203*7c478bd9Sstevel@tonic-gate growstak(staktop); 204*7c478bd9Sstevel@tonic-gate pushstak(c); 205*7c478bd9Sstevel@tonic-gate c = readwc(); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 208*7c478bd9Sstevel@tonic-gate growstak(staktop); 209*7c478bd9Sstevel@tonic-gate zerostak(); 210*7c478bd9Sstevel@tonic-gate n = lookup(absstak(argp)); 211*7c478bd9Sstevel@tonic-gate setstak(argp); 212*7c478bd9Sstevel@tonic-gate if (n->namflg & N_FUNCTN) 213*7c478bd9Sstevel@tonic-gate error(badsub); 214*7c478bd9Sstevel@tonic-gate v = n->namval; 215*7c478bd9Sstevel@tonic-gate id = (unsigned char *)n->namid; 216*7c478bd9Sstevel@tonic-gate peekc = c | MARK; 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate else if (digchar(c)) 219*7c478bd9Sstevel@tonic-gate { 220*7c478bd9Sstevel@tonic-gate *id = c; 221*7c478bd9Sstevel@tonic-gate idb[1] = 0; 222*7c478bd9Sstevel@tonic-gate if (astchar(c)) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate if(c == '@' && !atflag && quote) { 225*7c478bd9Sstevel@tonic-gate quoted--; 226*7c478bd9Sstevel@tonic-gate atflag = 1; 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate dolg = 1; 229*7c478bd9Sstevel@tonic-gate c = '1'; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate c -= '0'; 232*7c478bd9Sstevel@tonic-gate v = ((c == 0) ? cmdadr : ((int)c <= dolc) ? dolv[c] : (unsigned char *)(dolg = 0)); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate else if (c == '$') 235*7c478bd9Sstevel@tonic-gate v = pidadr; 236*7c478bd9Sstevel@tonic-gate else if (c == '!') 237*7c478bd9Sstevel@tonic-gate v = pcsadr; 238*7c478bd9Sstevel@tonic-gate else if (c == '#') 239*7c478bd9Sstevel@tonic-gate { 240*7c478bd9Sstevel@tonic-gate itos(dolc); 241*7c478bd9Sstevel@tonic-gate v = numbuf; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate else if (c == '?') 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate itos(retval); 246*7c478bd9Sstevel@tonic-gate v = numbuf; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate else if (c == '-') 249*7c478bd9Sstevel@tonic-gate v = flagadr; 250*7c478bd9Sstevel@tonic-gate else if (bra) 251*7c478bd9Sstevel@tonic-gate error(badsub); 252*7c478bd9Sstevel@tonic-gate else 253*7c478bd9Sstevel@tonic-gate goto retry; 254*7c478bd9Sstevel@tonic-gate c = readwc(); 255*7c478bd9Sstevel@tonic-gate if (c == ':' && bra) /* null and unset fix */ 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate nulflg = 1; 258*7c478bd9Sstevel@tonic-gate c = readwc(); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate else 261*7c478bd9Sstevel@tonic-gate nulflg = 0; 262*7c478bd9Sstevel@tonic-gate if (!defchar(c) && bra) 263*7c478bd9Sstevel@tonic-gate error(badsub); 264*7c478bd9Sstevel@tonic-gate argp = 0; 265*7c478bd9Sstevel@tonic-gate if (bra) 266*7c478bd9Sstevel@tonic-gate { 267*7c478bd9Sstevel@tonic-gate if (c != '}') 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate argp = (unsigned char *)relstak(); 270*7c478bd9Sstevel@tonic-gate if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c))) 271*7c478bd9Sstevel@tonic-gate copyto('}', trimflag); 272*7c478bd9Sstevel@tonic-gate else 273*7c478bd9Sstevel@tonic-gate skipto('}'); 274*7c478bd9Sstevel@tonic-gate argp = absstak(argp); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate else 278*7c478bd9Sstevel@tonic-gate { 279*7c478bd9Sstevel@tonic-gate peekc = c | MARK; 280*7c478bd9Sstevel@tonic-gate c = 0; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate if (v && (!nulflg || *v)) 283*7c478bd9Sstevel@tonic-gate { 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate if (c != '+') 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate for (;;) 288*7c478bd9Sstevel@tonic-gate { 289*7c478bd9Sstevel@tonic-gate if (*v == 0 && quote) { 290*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 291*7c478bd9Sstevel@tonic-gate growstak(staktop); 292*7c478bd9Sstevel@tonic-gate pushstak('\\'); 293*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 294*7c478bd9Sstevel@tonic-gate growstak(staktop); 295*7c478bd9Sstevel@tonic-gate pushstak('\0'); 296*7c478bd9Sstevel@tonic-gate } else { 297*7c478bd9Sstevel@tonic-gate while (c = *v) { 298*7c478bd9Sstevel@tonic-gate wchar_t wc; 299*7c478bd9Sstevel@tonic-gate register int length; 300*7c478bd9Sstevel@tonic-gate if ((length = mbtowc(&wc, (char *)v, MB_LEN_MAX)) <= 0) 301*7c478bd9Sstevel@tonic-gate length = 1; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if(quote || (c == '\\' && trimflag)) { 304*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 305*7c478bd9Sstevel@tonic-gate growstak(staktop); 306*7c478bd9Sstevel@tonic-gate pushstak('\\'); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate while(length-- > 0) { 309*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 310*7c478bd9Sstevel@tonic-gate growstak(staktop); 311*7c478bd9Sstevel@tonic-gate pushstak(*v++); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate if (dolg == 0 || (++dolg > dolc)) 317*7c478bd9Sstevel@tonic-gate break; 318*7c478bd9Sstevel@tonic-gate else /* $* and $@ expansion */ 319*7c478bd9Sstevel@tonic-gate { 320*7c478bd9Sstevel@tonic-gate v = dolv[dolg]; 321*7c478bd9Sstevel@tonic-gate if(*id == '*' && quote) { 322*7c478bd9Sstevel@tonic-gate /* push quoted space so that " $* " will not be broken into separate arguments */ 323*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 324*7c478bd9Sstevel@tonic-gate growstak(staktop); 325*7c478bd9Sstevel@tonic-gate pushstak('\\'); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 328*7c478bd9Sstevel@tonic-gate growstak(staktop); 329*7c478bd9Sstevel@tonic-gate pushstak(' '); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate else if (argp) 335*7c478bd9Sstevel@tonic-gate { 336*7c478bd9Sstevel@tonic-gate if (c == '?') { 337*7c478bd9Sstevel@tonic-gate if(trimflag) 338*7c478bd9Sstevel@tonic-gate trim(argp); 339*7c478bd9Sstevel@tonic-gate failed(id, *argp ? argp : (unsigned char *)badparam); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate else if (c == '=') 342*7c478bd9Sstevel@tonic-gate { 343*7c478bd9Sstevel@tonic-gate if (n) 344*7c478bd9Sstevel@tonic-gate { 345*7c478bd9Sstevel@tonic-gate int strlngth = staktop - stakbot; 346*7c478bd9Sstevel@tonic-gate unsigned char *savptr = fixstak(); 347*7c478bd9Sstevel@tonic-gate unsigned char *newargp; 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * copy word onto stack, trim it, and then 350*7c478bd9Sstevel@tonic-gate * do assignment 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate usestak(); 353*7c478bd9Sstevel@tonic-gate while(c = *argp) { 354*7c478bd9Sstevel@tonic-gate wchar_t wc; 355*7c478bd9Sstevel@tonic-gate register int len; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0) 358*7c478bd9Sstevel@tonic-gate len = 1; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate if(c == '\\' && trimflag) { 361*7c478bd9Sstevel@tonic-gate argp++; 362*7c478bd9Sstevel@tonic-gate if (*argp == 0) { 363*7c478bd9Sstevel@tonic-gate argp++; 364*7c478bd9Sstevel@tonic-gate continue; 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0) 367*7c478bd9Sstevel@tonic-gate len = 1; 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate while(len-- > 0) { 370*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 371*7c478bd9Sstevel@tonic-gate growstak(staktop); 372*7c478bd9Sstevel@tonic-gate pushstak(*argp++); 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate newargp = fixstak(); 376*7c478bd9Sstevel@tonic-gate assign(n, newargp); 377*7c478bd9Sstevel@tonic-gate tdystak(savptr); 378*7c478bd9Sstevel@tonic-gate memcpy(stakbot, savptr, strlngth); 379*7c478bd9Sstevel@tonic-gate staktop = stakbot + strlngth; 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate else 382*7c478bd9Sstevel@tonic-gate error(badsub); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate else if (flags & setflg) 386*7c478bd9Sstevel@tonic-gate failed(id, unset); 387*7c478bd9Sstevel@tonic-gate goto retry; 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate else 390*7c478bd9Sstevel@tonic-gate peekc = c | MARK; 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate else if (d == endch) 393*7c478bd9Sstevel@tonic-gate return(d); 394*7c478bd9Sstevel@tonic-gate else if (d == SQUOTE) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate comsubst(trimflag); 397*7c478bd9Sstevel@tonic-gate goto retry; 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate else if (d == DQUOTE && trimflag) 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate if(!quote) { 402*7c478bd9Sstevel@tonic-gate atflag = 0; 403*7c478bd9Sstevel@tonic-gate quoted++; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate quote ^= QUOTE; 406*7c478bd9Sstevel@tonic-gate goto retry; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate return(d); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate unsigned char * 412*7c478bd9Sstevel@tonic-gate macro(as) 413*7c478bd9Sstevel@tonic-gate unsigned char *as; 414*7c478bd9Sstevel@tonic-gate { 415*7c478bd9Sstevel@tonic-gate /* 416*7c478bd9Sstevel@tonic-gate * Strip "" and do $ substitution 417*7c478bd9Sstevel@tonic-gate * Leaves result on top of stack 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate register BOOL savqu = quoted; 420*7c478bd9Sstevel@tonic-gate register unsigned char savq = quote; 421*7c478bd9Sstevel@tonic-gate struct filehdr fb; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate push(&fb); 424*7c478bd9Sstevel@tonic-gate estabf(as); 425*7c478bd9Sstevel@tonic-gate usestak(); 426*7c478bd9Sstevel@tonic-gate quote = 0; 427*7c478bd9Sstevel@tonic-gate quoted = 0; 428*7c478bd9Sstevel@tonic-gate copyto(0, 1); 429*7c478bd9Sstevel@tonic-gate pop(); 430*7c478bd9Sstevel@tonic-gate if (quoted && (stakbot == staktop)) { 431*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 432*7c478bd9Sstevel@tonic-gate growstak(staktop); 433*7c478bd9Sstevel@tonic-gate pushstak('\\'); 434*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 435*7c478bd9Sstevel@tonic-gate growstak(staktop); 436*7c478bd9Sstevel@tonic-gate pushstak('\0'); 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * above is the fix for *'.c' bug 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate quote = savq; 442*7c478bd9Sstevel@tonic-gate quoted = savqu; 443*7c478bd9Sstevel@tonic-gate return(fixstak()); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate /* Save file descriptor for command substitution */ 446*7c478bd9Sstevel@tonic-gate int savpipe = -1; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate comsubst(trimflag) 449*7c478bd9Sstevel@tonic-gate int trimflag; /* used to determine if argument will later be trimmed */ 450*7c478bd9Sstevel@tonic-gate { 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * command substn 453*7c478bd9Sstevel@tonic-gate */ 454*7c478bd9Sstevel@tonic-gate struct fileblk cb; 455*7c478bd9Sstevel@tonic-gate register unsigned int d; 456*7c478bd9Sstevel@tonic-gate int strlngth = staktop - stakbot; 457*7c478bd9Sstevel@tonic-gate register unsigned char *oldstaktop; 458*7c478bd9Sstevel@tonic-gate unsigned char *savptr = fixstak(); 459*7c478bd9Sstevel@tonic-gate unsigned char *pc; 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate usestak(); 462*7c478bd9Sstevel@tonic-gate while ((d = readwc()) != SQUOTE && d) { 463*7c478bd9Sstevel@tonic-gate if(d == '\\') { 464*7c478bd9Sstevel@tonic-gate d = readwc(); 465*7c478bd9Sstevel@tonic-gate if(!escchar(d) || (d == '"' && !quote)) { 466*7c478bd9Sstevel@tonic-gate /* trim quotes for `, \, or " if command substitution is within 467*7c478bd9Sstevel@tonic-gate double quotes */ 468*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 469*7c478bd9Sstevel@tonic-gate growstak(staktop); 470*7c478bd9Sstevel@tonic-gate pushstak('\\'); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate pc = readw(d); 474*7c478bd9Sstevel@tonic-gate /* d might be NULL */ 475*7c478bd9Sstevel@tonic-gate if (*pc) { 476*7c478bd9Sstevel@tonic-gate while (*pc) { 477*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 478*7c478bd9Sstevel@tonic-gate growstak(staktop); 479*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate } else { 482*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 483*7c478bd9Sstevel@tonic-gate growstak(staktop); 484*7c478bd9Sstevel@tonic-gate pushstak(*pc); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate { 488*7c478bd9Sstevel@tonic-gate register unsigned char *argc; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate argc = fixstak(); 491*7c478bd9Sstevel@tonic-gate push(&cb); 492*7c478bd9Sstevel@tonic-gate estabf(argc); /* read from string */ 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate { 495*7c478bd9Sstevel@tonic-gate register struct trenod *t; 496*7c478bd9Sstevel@tonic-gate int pv[2]; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* 499*7c478bd9Sstevel@tonic-gate * this is done like this so that the pipe 500*7c478bd9Sstevel@tonic-gate * is open only when needed 501*7c478bd9Sstevel@tonic-gate */ 502*7c478bd9Sstevel@tonic-gate t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG )); 503*7c478bd9Sstevel@tonic-gate chkpipe(pv); 504*7c478bd9Sstevel@tonic-gate savpipe = pv[OTPIPE]; 505*7c478bd9Sstevel@tonic-gate initf(pv[INPIPE]); /* read from pipe */ 506*7c478bd9Sstevel@tonic-gate execute(t, XEC_NOSTOP, (int)(flags & errflg), 0, pv); 507*7c478bd9Sstevel@tonic-gate close(pv[OTPIPE]); 508*7c478bd9Sstevel@tonic-gate savpipe = -1; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate tdystak(savptr); 511*7c478bd9Sstevel@tonic-gate memcpy(stakbot, savptr, strlngth); 512*7c478bd9Sstevel@tonic-gate oldstaktop = staktop = stakbot + strlngth; 513*7c478bd9Sstevel@tonic-gate while (d = readwc()) { 514*7c478bd9Sstevel@tonic-gate if(quote || (d == '\\' && trimflag)) { 515*7c478bd9Sstevel@tonic-gate register unsigned char *rest; 516*7c478bd9Sstevel@tonic-gate /* quote output from command subst. if within double 517*7c478bd9Sstevel@tonic-gate quotes or backslash part of output */ 518*7c478bd9Sstevel@tonic-gate rest = readw(d); 519*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 520*7c478bd9Sstevel@tonic-gate growstak(staktop); 521*7c478bd9Sstevel@tonic-gate pushstak('\\'); 522*7c478bd9Sstevel@tonic-gate while(d = *rest++) { 523*7c478bd9Sstevel@tonic-gate /* Pick up all of multibyte character */ 524*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 525*7c478bd9Sstevel@tonic-gate growstak(staktop); 526*7c478bd9Sstevel@tonic-gate pushstak(d); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate else { 530*7c478bd9Sstevel@tonic-gate pc = readw(d); 531*7c478bd9Sstevel@tonic-gate while (*pc) { 532*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 533*7c478bd9Sstevel@tonic-gate growstak(staktop); 534*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate { 539*7c478bd9Sstevel@tonic-gate extern pid_t parent; 540*7c478bd9Sstevel@tonic-gate int stat; 541*7c478bd9Sstevel@tonic-gate register rc; 542*7c478bd9Sstevel@tonic-gate int ret = 0; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate while ((ret = waitpid(parent,&stat,0)) != parent) { 545*7c478bd9Sstevel@tonic-gate /* break out if waitpid(2) has failed */ 546*7c478bd9Sstevel@tonic-gate if (ret == -1) 547*7c478bd9Sstevel@tonic-gate break; 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate if (WIFEXITED(stat)) 550*7c478bd9Sstevel@tonic-gate rc = WEXITSTATUS(stat); 551*7c478bd9Sstevel@tonic-gate else 552*7c478bd9Sstevel@tonic-gate rc = (WTERMSIG(stat) | SIGFLG); 553*7c478bd9Sstevel@tonic-gate if (rc && (flags & errflg)) 554*7c478bd9Sstevel@tonic-gate exitsh(rc); 555*7c478bd9Sstevel@tonic-gate exitval = rc; 556*7c478bd9Sstevel@tonic-gate flags |= eflag; 557*7c478bd9Sstevel@tonic-gate exitset(); 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate while (oldstaktop != staktop) 560*7c478bd9Sstevel@tonic-gate { /* strip off trailing newlines from command substitution only */ 561*7c478bd9Sstevel@tonic-gate if ((*--staktop) != NL) 562*7c478bd9Sstevel@tonic-gate { 563*7c478bd9Sstevel@tonic-gate ++staktop; 564*7c478bd9Sstevel@tonic-gate break; 565*7c478bd9Sstevel@tonic-gate } else if(quote) 566*7c478bd9Sstevel@tonic-gate staktop--; /* skip past backslashes if quoting */ 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate pop(); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate #define CPYSIZ 512 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate subst(in, ot) 574*7c478bd9Sstevel@tonic-gate int in, ot; 575*7c478bd9Sstevel@tonic-gate { 576*7c478bd9Sstevel@tonic-gate register unsigned int c; 577*7c478bd9Sstevel@tonic-gate struct fileblk fb; 578*7c478bd9Sstevel@tonic-gate register int count = CPYSIZ; 579*7c478bd9Sstevel@tonic-gate unsigned char *pc; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate push(&fb); 582*7c478bd9Sstevel@tonic-gate initf(in); 583*7c478bd9Sstevel@tonic-gate /* 584*7c478bd9Sstevel@tonic-gate * DQUOTE used to stop it from quoting 585*7c478bd9Sstevel@tonic-gate */ 586*7c478bd9Sstevel@tonic-gate while (c = (getch(DQUOTE, 0))) /* read characters from here document 587*7c478bd9Sstevel@tonic-gate and interpret them */ 588*7c478bd9Sstevel@tonic-gate { 589*7c478bd9Sstevel@tonic-gate if(c == '\\') { 590*7c478bd9Sstevel@tonic-gate c = readwc(); /* check if character in here document is 591*7c478bd9Sstevel@tonic-gate escaped */ 592*7c478bd9Sstevel@tonic-gate if(!escchar(c) || c == '"') { 593*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 594*7c478bd9Sstevel@tonic-gate growstak(staktop); 595*7c478bd9Sstevel@tonic-gate pushstak('\\'); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate pc = readw(c); 599*7c478bd9Sstevel@tonic-gate /* c might be NULL */ 600*7c478bd9Sstevel@tonic-gate if (*pc) { 601*7c478bd9Sstevel@tonic-gate while (*pc) { 602*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 603*7c478bd9Sstevel@tonic-gate growstak(staktop); 604*7c478bd9Sstevel@tonic-gate pushstak(*pc++); 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate } else { 607*7c478bd9Sstevel@tonic-gate if (staktop >= brkend) 608*7c478bd9Sstevel@tonic-gate growstak(staktop); 609*7c478bd9Sstevel@tonic-gate pushstak(*pc); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate if (--count == 0) 612*7c478bd9Sstevel@tonic-gate { 613*7c478bd9Sstevel@tonic-gate flush(ot); 614*7c478bd9Sstevel@tonic-gate count = CPYSIZ; 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate flush(ot); 618*7c478bd9Sstevel@tonic-gate pop(); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate flush(ot) 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate write(ot, stakbot, staktop - stakbot); 624*7c478bd9Sstevel@tonic-gate if (flags & execpr) 625*7c478bd9Sstevel@tonic-gate write(output, stakbot, staktop - stakbot); 626*7c478bd9Sstevel@tonic-gate staktop = stakbot; 627*7c478bd9Sstevel@tonic-gate } 628